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