001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.util.LocaleUtil;
024    import com.liferay.portal.kernel.util.Localization;
025    import com.liferay.portal.kernel.util.ParamUtil;
026    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
027    import com.liferay.portal.kernel.util.PrefsParamUtil;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.util.StringUtil;
030    import com.liferay.portal.kernel.util.Tuple;
031    import com.liferay.portal.kernel.util.Validator;
032    
033    import java.util.HashMap;
034    import java.util.Locale;
035    import java.util.Map;
036    
037    import javax.portlet.PortletPreferences;
038    import javax.portlet.PortletRequest;
039    
040    import javax.xml.stream.XMLInputFactory;
041    import javax.xml.stream.XMLOutputFactory;
042    import javax.xml.stream.XMLStreamConstants;
043    import javax.xml.stream.XMLStreamException;
044    import javax.xml.stream.XMLStreamReader;
045    import javax.xml.stream.XMLStreamWriter;
046    
047    import org.apache.commons.collections.map.ReferenceMap;
048    
049    /**
050     * @author Alexander Chow
051     * @author Jorge Ferrer
052     * @author Mauro Mariuzzo
053     * @author Julio Camarero
054     * @author Brian Wing Shun Chan
055     * @author Connor McKay
056     */
057    public class LocalizationImpl implements Localization {
058    
059            public Object deserialize(JSONObject jsonObject) {
060                    Locale[] locales = LanguageUtil.getAvailableLocales();
061    
062                    Map<Locale, String> map = new HashMap<Locale, String>();
063    
064                    for (Locale locale : locales) {
065                            String languageId = LocaleUtil.toLanguageId(locale);
066    
067                            String value = jsonObject.getString(languageId);
068    
069                            if (Validator.isNotNull(value)) {
070                                    map.put(locale, value);
071                            }
072                    }
073    
074                    return map;
075            }
076    
077            public String[] getAvailableLocales(String xml) {
078                    String attributeValue = _getRootAttribute(
079                            xml, _AVAILABLE_LOCALES, StringPool.BLANK);
080    
081                    return StringUtil.split(attributeValue);
082            }
083    
084            public String getDefaultLocale(String xml) {
085                    String defaultLanguageId = LocaleUtil.toLanguageId(
086                            LocaleUtil.getDefault());
087    
088                    return _getRootAttribute(xml, _DEFAULT_LOCALE, defaultLanguageId);
089            }
090    
091            public String getLocalization(String xml, String requestedLanguageId) {
092                    return getLocalization(xml, requestedLanguageId, true);
093            }
094    
095            public String getLocalization(
096                    String xml, String requestedLanguageId, boolean useDefault) {
097    
098                    String value = _getCachedValue(xml, requestedLanguageId, useDefault);
099    
100                    if (value != null) {
101                            return value;
102                    }
103                    else {
104                            value = StringPool.BLANK;
105                    }
106    
107                    String systemDefaultLanguageId = LocaleUtil.toLanguageId(
108                            LocaleUtil.getDefault());
109    
110                    String priorityLanguageId = null;
111    
112                    Locale requestedLocale = LocaleUtil.fromLanguageId(requestedLanguageId);
113    
114                    if (useDefault && LanguageUtil.isDuplicateLanguageCode(
115                            requestedLocale.getLanguage())) {
116    
117                            Locale priorityLocale = LanguageUtil.getLocale(
118                                    requestedLocale.getLanguage());
119    
120                            if (!requestedLanguageId.equals(priorityLanguageId)) {
121                                    priorityLanguageId = LocaleUtil.toLanguageId(priorityLocale);
122                            }
123                    }
124    
125                    if (!Validator.isXml(xml)) {
126                            if (useDefault ||
127                                    requestedLanguageId.equals(systemDefaultLanguageId)) {
128    
129                                    value = xml;
130                            }
131    
132                            _setCachedValue(xml, requestedLanguageId, useDefault, value);
133    
134                            return value;
135                    }
136    
137                    XMLStreamReader xmlStreamReader = null;
138    
139                    ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
140    
141                    Thread currentThread = Thread.currentThread();
142    
143                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
144    
145                    try {
146                            if (contextClassLoader != portalClassLoader) {
147                                    currentThread.setContextClassLoader(portalClassLoader);
148                            }
149    
150                            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
151    
152                            xmlStreamReader = xmlInputFactory.createXMLStreamReader(
153                                    new UnsyncStringReader(xml));
154    
155                            String defaultLanguageId = StringPool.BLANK;
156    
157                            // Skip root node
158    
159                            if (xmlStreamReader.hasNext()) {
160                                    xmlStreamReader.nextTag();
161    
162                                    defaultLanguageId = xmlStreamReader.getAttributeValue(
163                                            null, _DEFAULT_LOCALE);
164    
165                                    if (Validator.isNull(defaultLanguageId)) {
166                                            defaultLanguageId = systemDefaultLanguageId;
167                                    }
168                            }
169    
170                            // Find specified language and/or default language
171    
172                            String defaultValue = StringPool.BLANK;
173                            String priorityValue = StringPool.BLANK;
174    
175                            while (xmlStreamReader.hasNext()) {
176                                    int event = xmlStreamReader.next();
177    
178                                    if (event == XMLStreamConstants.START_ELEMENT) {
179                                            String languageId = xmlStreamReader.getAttributeValue(
180                                                    null, _LANGUAGE_ID);
181    
182                                            if (Validator.isNull(languageId)) {
183                                                    languageId = defaultLanguageId;
184                                            }
185    
186                                            if (languageId.equals(defaultLanguageId) ||
187                                                    languageId.equals(priorityLanguageId) ||
188                                                    languageId.equals(requestedLanguageId)) {
189    
190                                                    String text = xmlStreamReader.getElementText();
191    
192                                                    if (languageId.equals(defaultLanguageId)) {
193                                                            defaultValue = text;
194                                                    }
195    
196                                                    if (languageId.equals(priorityLanguageId)) {
197                                                            priorityValue = text;
198                                                    }
199    
200                                                    if (languageId.equals(requestedLanguageId)) {
201                                                            value = text;
202                                                    }
203    
204                                                    if (Validator.isNotNull(value)) {
205                                                            break;
206                                                    }
207                                            }
208                                    }
209                                    else if (event == XMLStreamConstants.END_DOCUMENT) {
210                                            break;
211                                    }
212                            }
213    
214                            if (useDefault && Validator.isNotNull(priorityLanguageId) &&
215                                    Validator.isNull(value) && Validator.isNotNull(priorityValue)) {
216    
217                                    value = priorityValue;
218                            }
219    
220                            if (useDefault && Validator.isNull(value)) {
221                                    value = defaultValue;
222                            }
223                    }
224                    catch (Exception e) {
225                            if (_log.isWarnEnabled()) {
226                                    _log.warn(e, e);
227                            }
228                    }
229                    finally {
230                            if (contextClassLoader != portalClassLoader) {
231                                    currentThread.setContextClassLoader(contextClassLoader);
232                            }
233    
234                            if (xmlStreamReader != null) {
235                                    try {
236                                            xmlStreamReader.close();
237                                    }
238                                    catch (Exception e) {
239                                    }
240                            }
241                    }
242    
243                    _setCachedValue(xml, requestedLanguageId, useDefault, value);
244    
245                    return value;
246            }
247    
248            public Map<Locale, String> getLocalizationMap(
249                    PortletPreferences preferences, String parameter) {
250    
251                    Locale[] locales = LanguageUtil.getAvailableLocales();
252    
253                    Map<Locale, String> map = new HashMap<Locale, String>();
254    
255                    for (Locale locale : locales) {
256                            String languageId = LocaleUtil.toLanguageId(locale);
257    
258                            String localeParameter = parameter.concat(
259                                    StringPool.UNDERLINE).concat(languageId);
260    
261                            map.put(
262                                    locale,
263                                    preferences.getValue(localeParameter, StringPool.BLANK));
264                    }
265    
266                    return map;
267            }
268    
269            public Map<Locale, String> getLocalizationMap(
270                    PortletRequest portletRequest, String parameter) {
271    
272                    Locale[] locales = LanguageUtil.getAvailableLocales();
273    
274                    Map<Locale, String> map = new HashMap<Locale, String>();
275    
276                    for (Locale locale : locales) {
277                            String languageId = LocaleUtil.toLanguageId(locale);
278    
279                            String localeParameter = parameter.concat(
280                                    StringPool.UNDERLINE).concat(languageId);
281    
282                            map.put(
283                                    locale, ParamUtil.getString(portletRequest, localeParameter));
284                    }
285    
286                    return map;
287            }
288    
289            public Map<Locale, String> getLocalizationMap(String xml) {
290                    Locale[] locales = LanguageUtil.getAvailableLocales();
291    
292                    Map<Locale, String> map = new HashMap<Locale, String>();
293    
294                    for (Locale locale : locales) {
295                            String languageId = LocaleUtil.toLanguageId(locale);
296    
297                            map.put(locale, getLocalization(xml, languageId, false));
298                    }
299    
300                    return map;
301            }
302    
303            public String getLocalizationXmlFromPreferences(
304                    PortletPreferences preferences, PortletRequest portletRequest,
305                    String parameter) {
306    
307                    String xml = StringPool.BLANK;
308    
309                    Locale[] locales = LanguageUtil.getAvailableLocales();
310                    Locale defaultLocale = LocaleUtil.getDefault();
311                    String defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
312    
313                    for (Locale locale : locales) {
314                            String languageId = LocaleUtil.toLanguageId(locale);
315    
316                            String localParameter =
317                                    parameter + StringPool.UNDERLINE + languageId;
318    
319                            String value = PrefsParamUtil.getString(
320                                    preferences, portletRequest, localParameter);
321    
322                            if (Validator.isNotNull(value)) {
323                                    xml = updateLocalization(xml, parameter, value, languageId);
324                            }
325                    }
326    
327                    if (Validator.isNull(getLocalization(xml, defaultLanguageId))) {
328                            String oldValue = PrefsParamUtil.getString(
329                                    preferences, portletRequest, parameter);
330    
331                            if (Validator.isNotNull(oldValue)) {
332                                    xml = updateLocalization(xml, parameter, oldValue);
333                            }
334                    }
335    
336                    return xml;
337            }
338    
339            public Map<Locale, String> getLocalizedParameter(
340                    PortletRequest portletRequest, String parameter) {
341    
342                    return getLocalizationMap(portletRequest, parameter);
343            }
344    
345            public String getPreferencesKey(String key, String languageId) {
346                    String defaultLanguageId = LocaleUtil.toLanguageId(
347                            LocaleUtil.getDefault());
348    
349                    if (!languageId.equals(defaultLanguageId)) {
350                            key += StringPool.UNDERLINE + languageId;
351                    }
352    
353                    return key;
354            }
355    
356            public String getPreferencesValue(
357                    PortletPreferences preferences, String key, String languageId) {
358    
359                    return getPreferencesValue(preferences, key, languageId, true);
360            }
361    
362            public String getPreferencesValue(
363                    PortletPreferences preferences, String key, String languageId,
364                    boolean useDefault) {
365    
366                    String localizedKey = getPreferencesKey(key, languageId);
367    
368                    String value = preferences.getValue(localizedKey, StringPool.BLANK);
369    
370                    if (useDefault && Validator.isNull(value)) {
371                            value = preferences.getValue(key, StringPool.BLANK);
372                    }
373    
374                    return value;
375            }
376    
377            public String[] getPreferencesValues(
378                    PortletPreferences preferences, String key, String languageId) {
379    
380                    return getPreferencesValues(preferences, key, languageId, true);
381            }
382    
383            public String[] getPreferencesValues(
384                    PortletPreferences preferences, String key, String languageId,
385                    boolean useDefault) {
386    
387                    String localizedKey = getPreferencesKey(key, languageId);
388    
389                    String[] values = preferences.getValues(localizedKey, new String[0]);
390    
391                    if (useDefault && Validator.isNull(values)) {
392                            values = preferences.getValues(key, new String[0]);
393                    }
394    
395                    return values;
396            }
397    
398            public String removeLocalization(
399                    String xml, String key, String requestedLanguageId) {
400    
401                    return removeLocalization(xml, key, requestedLanguageId, false);
402            }
403    
404            public String removeLocalization(
405                    String xml, String key, String requestedLanguageId, boolean cdata) {
406    
407                    return removeLocalization(xml, key, requestedLanguageId, cdata, true);
408            }
409    
410            public String removeLocalization(
411                    String xml, String key, String requestedLanguageId, boolean cdata,
412                    boolean localized) {
413    
414                    if (Validator.isNull(xml)) {
415                            return StringPool.BLANK;
416                    }
417    
418                    xml = _sanitizeXML(xml);
419    
420                    String systemDefaultLanguageId = LocaleUtil.toLanguageId(
421                            LocaleUtil.getDefault());
422    
423                    XMLStreamReader xmlStreamReader = null;
424                    XMLStreamWriter xmlStreamWriter = null;
425    
426                    ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
427    
428                    Thread currentThread = Thread.currentThread();
429    
430                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
431    
432                    try {
433                            if (contextClassLoader != portalClassLoader) {
434                                    currentThread.setContextClassLoader(portalClassLoader);
435                            }
436    
437                            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
438    
439                            xmlStreamReader = xmlInputFactory.createXMLStreamReader(
440                                    new UnsyncStringReader(xml));
441    
442                            String availableLocales = StringPool.BLANK;
443                            String defaultLanguageId = StringPool.BLANK;
444    
445                            // Read root node
446    
447                            if (xmlStreamReader.hasNext()) {
448                                    xmlStreamReader.nextTag();
449    
450                                    availableLocales = xmlStreamReader.getAttributeValue(
451                                            null, _AVAILABLE_LOCALES);
452                                    defaultLanguageId = xmlStreamReader.getAttributeValue(
453                                            null, _DEFAULT_LOCALE);
454    
455                                    if (Validator.isNull(defaultLanguageId)) {
456                                            defaultLanguageId = systemDefaultLanguageId;
457                                    }
458                            }
459    
460                            if ((availableLocales != null) &&
461                                    (availableLocales.indexOf(requestedLanguageId) != -1)) {
462    
463                                    availableLocales = StringUtil.remove(
464                                            availableLocales, requestedLanguageId, StringPool.COMMA);
465    
466                                    UnsyncStringWriter unsyncStringWriter =
467                                            new UnsyncStringWriter();
468    
469                                    XMLOutputFactory xmlOutputFactory =
470                                            XMLOutputFactory.newInstance();
471    
472                                    xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
473                                            unsyncStringWriter);
474    
475                                    xmlStreamWriter.writeStartDocument();
476                                    xmlStreamWriter.writeStartElement(_ROOT);
477    
478                                    if (localized) {
479                                            xmlStreamWriter.writeAttribute(
480                                                    _AVAILABLE_LOCALES, availableLocales);
481                                            xmlStreamWriter.writeAttribute(
482                                                    _DEFAULT_LOCALE, defaultLanguageId);
483                                    }
484    
485                                    _copyNonExempt(
486                                            xmlStreamReader, xmlStreamWriter, requestedLanguageId,
487                                            defaultLanguageId, cdata);
488    
489                                    xmlStreamWriter.writeEndElement();
490                                    xmlStreamWriter.writeEndDocument();
491    
492                                    xmlStreamWriter.close();
493                                    xmlStreamWriter = null;
494    
495                                    xml = unsyncStringWriter.toString();
496                            }
497                    }
498                    catch (Exception e) {
499                            if (_log.isWarnEnabled()) {
500                                    _log.warn(e, e);
501                            }
502                    }
503                    finally {
504                            if (contextClassLoader != portalClassLoader) {
505                                    currentThread.setContextClassLoader(contextClassLoader);
506                            }
507    
508                            if (xmlStreamReader != null) {
509                                    try {
510                                            xmlStreamReader.close();
511                                    }
512                                    catch (Exception e) {
513                                    }
514                            }
515    
516                            if (xmlStreamWriter != null) {
517                                    try {
518                                            xmlStreamWriter.close();
519                                    }
520                                    catch (Exception e) {
521                                    }
522                            }
523                    }
524    
525                    return xml;
526            }
527    
528            public void setLocalizedPreferencesValues(
529                            PortletRequest portletRequest, PortletPreferences preferences,
530                            String parameter)
531                    throws Exception {
532    
533                    Map<Locale, String> map = getLocalizationMap(portletRequest, parameter);
534    
535                    for (Map.Entry<Locale, String> entry : map.entrySet()) {
536                            String languageId = LocaleUtil.toLanguageId(entry.getKey());
537                            String value = entry.getValue();
538    
539                            setPreferencesValue(preferences, parameter, languageId, value);
540                    }
541            }
542    
543            public void setPreferencesValue(
544                            PortletPreferences preferences, String key, String languageId,
545                            String value)
546                    throws Exception {
547    
548                    preferences.setValue(getPreferencesKey(key, languageId), value);
549            }
550    
551            public void setPreferencesValues(
552                            PortletPreferences preferences, String key, String languageId,
553                            String[] values)
554                    throws Exception {
555    
556                    preferences.setValues(getPreferencesKey(key, languageId), values);
557            }
558    
559            public String updateLocalization(String xml, String key, String value) {
560                    String defaultLanguageId = LocaleUtil.toLanguageId(
561                            LocaleUtil.getDefault());
562    
563                    return updateLocalization(
564                            xml, key, value, defaultLanguageId, defaultLanguageId);
565            }
566    
567            public String updateLocalization(
568                    String xml, String key, String value, String requestedLanguageId) {
569    
570                    String defaultLanguageId = LocaleUtil.toLanguageId(
571                            LocaleUtil.getDefault());
572    
573                    return updateLocalization(
574                            xml, key, value, requestedLanguageId, defaultLanguageId);
575            }
576    
577            public String updateLocalization(
578                    String xml, String key, String value, String requestedLanguageId,
579                    String defaultLanguageId) {
580    
581                    return updateLocalization(
582                            xml, key, value, requestedLanguageId, defaultLanguageId, false);
583            }
584    
585            public String updateLocalization(
586                    String xml, String key, String value, String requestedLanguageId,
587                    String defaultLanguageId, boolean cdata) {
588    
589                    return updateLocalization(
590                            xml, key, value, requestedLanguageId, defaultLanguageId, cdata,
591                            true);
592            }
593    
594            public String updateLocalization(
595                    String xml, String key, String value, String requestedLanguageId,
596                    String defaultLanguageId, boolean cdata, boolean localized) {
597    
598                    xml = _sanitizeXML(xml);
599    
600                    XMLStreamReader xmlStreamReader = null;
601                    XMLStreamWriter xmlStreamWriter = null;
602    
603                    ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
604    
605                    Thread currentThread = Thread.currentThread();
606    
607                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
608    
609                    try {
610                            if (contextClassLoader != portalClassLoader) {
611                                    currentThread.setContextClassLoader(portalClassLoader);
612                            }
613    
614                            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
615    
616                            xmlStreamReader = xmlInputFactory.createXMLStreamReader(
617                                    new UnsyncStringReader(xml));
618    
619                            String availableLocales = StringPool.BLANK;
620    
621                            // Read root node
622    
623                            if (xmlStreamReader.hasNext()) {
624                                    xmlStreamReader.nextTag();
625    
626                                    availableLocales = xmlStreamReader.getAttributeValue(
627                                            null, _AVAILABLE_LOCALES);
628    
629                                    if (Validator.isNull(availableLocales)) {
630                                            availableLocales = defaultLanguageId;
631                                    }
632    
633                                    if (availableLocales.indexOf(requestedLanguageId) == -1) {
634                                            availableLocales = StringUtil.add(
635                                                    availableLocales, requestedLanguageId,
636                                                    StringPool.COMMA);
637                                    }
638                            }
639    
640                            UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
641    
642                            XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
643    
644                            xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
645                                    unsyncStringWriter);
646    
647                            xmlStreamWriter.writeStartDocument();
648                            xmlStreamWriter.writeStartElement(_ROOT);
649    
650                            if (localized) {
651                                    xmlStreamWriter.writeAttribute(
652                                            _AVAILABLE_LOCALES, availableLocales);
653                                    xmlStreamWriter.writeAttribute(
654                                            _DEFAULT_LOCALE, defaultLanguageId);
655                            }
656    
657                            _copyNonExempt(
658                                    xmlStreamReader, xmlStreamWriter, requestedLanguageId,
659                                    defaultLanguageId, cdata);
660    
661                            xmlStreamWriter.writeStartElement(key);
662    
663                            if (localized) {
664                                    xmlStreamWriter.writeAttribute(
665                                            _LANGUAGE_ID, requestedLanguageId);
666                            }
667    
668                            if (cdata) {
669                                    xmlStreamWriter.writeCData(value);
670                            }
671                            else {
672                                    xmlStreamWriter.writeCharacters(value);
673                            }
674    
675                            xmlStreamWriter.writeEndElement();
676                            xmlStreamWriter.writeEndElement();
677                            xmlStreamWriter.writeEndDocument();
678    
679                            xmlStreamWriter.close();
680                            xmlStreamWriter = null;
681    
682                            xml = unsyncStringWriter.toString();
683                    }
684                    catch (Exception e) {
685                            if (_log.isWarnEnabled()) {
686                                    _log.warn(e, e);
687                            }
688                    }
689                    finally {
690                            if (contextClassLoader != portalClassLoader) {
691                                    currentThread.setContextClassLoader(contextClassLoader);
692                            }
693    
694                            if (xmlStreamReader != null) {
695                                    try {
696                                            xmlStreamReader.close();
697                                    }
698                                    catch (Exception e) {
699                                    }
700                            }
701    
702                            if (xmlStreamWriter != null) {
703                                    try {
704                                            xmlStreamWriter.close();
705                                    }
706                                    catch (Exception e) {
707                                    }
708                            }
709                    }
710    
711                    return xml;
712            }
713    
714            private void _copyNonExempt(
715                            XMLStreamReader xmlStreamReader, XMLStreamWriter xmlStreamWriter,
716                            String exemptLanguageId, String defaultLanguageId, boolean cdata)
717                    throws XMLStreamException {
718    
719                    while (xmlStreamReader.hasNext()) {
720                            int event = xmlStreamReader.next();
721    
722                            if (event == XMLStreamConstants.START_ELEMENT) {
723                                    String languageId = xmlStreamReader.getAttributeValue(
724                                            null, _LANGUAGE_ID);
725    
726                                    if (Validator.isNull(languageId)) {
727                                            languageId = defaultLanguageId;
728                                    }
729    
730                                    if (!languageId.equals(exemptLanguageId)) {
731                                            xmlStreamWriter.writeStartElement(
732                                                    xmlStreamReader.getLocalName());
733                                            xmlStreamWriter.writeAttribute(_LANGUAGE_ID, languageId);
734    
735                                            while (xmlStreamReader.hasNext()) {
736                                                    event = xmlStreamReader.next();
737    
738                                                    if ((event == XMLStreamConstants.CHARACTERS) ||
739                                                            (event == XMLStreamConstants.CDATA)) {
740    
741                                                            String text = xmlStreamReader.getText();
742    
743                                                            if (cdata) {
744                                                                    xmlStreamWriter.writeCData(text);
745                                                            }
746                                                            else {
747                                                                    xmlStreamWriter.writeCharacters(
748                                                                            xmlStreamReader.getText());
749                                                            }
750    
751                                                            break;
752                                                    }
753                                                    else if (event == XMLStreamConstants.END_ELEMENT) {
754                                                            break;
755                                                    }
756                                            }
757    
758                                            xmlStreamWriter.writeEndElement();
759                                    }
760                            }
761                            else if (event == XMLStreamConstants.END_DOCUMENT) {
762                                    break;
763                            }
764                    }
765            }
766    
767            private String _getCachedValue(
768                    String xml, String requestedLanguageId, boolean useDefault) {
769    
770                    String value = null;
771    
772                    Map<Tuple, String> valueMap = _cache.get(xml);
773    
774                    if (valueMap != null) {
775                            Tuple subkey = new Tuple(useDefault, requestedLanguageId);
776    
777                            value = valueMap.get(subkey);
778                    }
779    
780                    return value;
781            }
782    
783            private String _getRootAttribute(
784                    String xml, String name, String defaultValue) {
785    
786                    String value = null;
787    
788                    XMLStreamReader xmlStreamReader = null;
789    
790                    ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
791    
792                    Thread currentThread = Thread.currentThread();
793    
794                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
795    
796                    try {
797                            if (contextClassLoader != portalClassLoader) {
798                                    currentThread.setContextClassLoader(portalClassLoader);
799                            }
800    
801                            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
802    
803                            xmlStreamReader = xmlInputFactory.createXMLStreamReader(
804                                    new UnsyncStringReader(xml));
805    
806                            if (xmlStreamReader.hasNext()) {
807                                    xmlStreamReader.nextTag();
808    
809                                    value = xmlStreamReader.getAttributeValue(null, name);
810                            }
811                    }
812                    catch (Exception e) {
813                            if (_log.isWarnEnabled()) {
814                                    _log.warn(e, e);
815                            }
816                    }
817                    finally {
818                            if (contextClassLoader != portalClassLoader) {
819                                    currentThread.setContextClassLoader(contextClassLoader);
820                            }
821    
822                            if (xmlStreamReader != null) {
823                                    try {
824                                            xmlStreamReader.close();
825                                    }
826                                    catch (Exception e) {
827                                    }
828                            }
829                    }
830    
831                    if (Validator.isNull(value)) {
832                            value = defaultValue;
833                    }
834    
835                    return value;
836            }
837    
838            private String _sanitizeXML(String xml) {
839                    if (Validator.isNull(xml) || (xml.indexOf("<root") == -1)) {
840                            xml = _EMPTY_ROOT_NODE;
841                    }
842    
843                    return xml;
844            }
845    
846            private void _setCachedValue(
847                    String xml, String requestedLanguageId, boolean useDefault,
848                    String value) {
849    
850                    if (Validator.isNotNull(xml) && !xml.equals(_EMPTY_ROOT_NODE)) {
851                            synchronized (_cache) {
852                                    Map<Tuple, String> map = _cache.get(xml);
853    
854                                    if (map == null) {
855                                            map = new HashMap<Tuple, String>();
856                                    }
857    
858                                    Tuple subkey = new Tuple(useDefault, requestedLanguageId);
859    
860                                    map.put(subkey, value);
861    
862                                    _cache.put(xml, map);
863                            }
864                    }
865            }
866    
867            private static final String _AVAILABLE_LOCALES = "available-locales";
868    
869            private static final String _DEFAULT_LOCALE = "default-locale";
870    
871            private static final String _EMPTY_ROOT_NODE = "<root />";
872    
873            private static final String _LANGUAGE_ID = "language-id";
874    
875            private static final String _ROOT = "root";
876    
877            private static Log _log = LogFactoryUtil.getLog(LocalizationImpl.class);
878    
879            private Map<String, Map<Tuple, String>> _cache = new ReferenceMap(
880                    ReferenceMap.SOFT, ReferenceMap.HARD);
881    
882    }