001    /**
002     * Copyright (c) 2000-2011 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                                                    while (xmlStreamReader.hasNext()) {
191                                                            event = xmlStreamReader.next();
192    
193                                                            if (event == XMLStreamConstants.CHARACTERS ||
194                                                                    event == XMLStreamConstants.CDATA) {
195    
196                                                                    String text = xmlStreamReader.getText();
197    
198                                                                    if (languageId.equals(defaultLanguageId)) {
199                                                                            defaultValue = text;
200                                                                    }
201    
202                                                                    if (languageId.equals(priorityLanguageId)) {
203                                                                            priorityValue = text;
204                                                                    }
205    
206                                                                    if (languageId.equals(requestedLanguageId)) {
207                                                                            value = text;
208                                                                    }
209    
210                                                                    break;
211                                                            }
212                                                            else if (event == XMLStreamConstants.END_ELEMENT) {
213                                                                    break;
214                                                            }
215                                                    }
216    
217                                                    if (Validator.isNotNull(value)) {
218                                                            break;
219                                                    }
220                                            }
221                                    }
222                                    else if (event == XMLStreamConstants.END_DOCUMENT) {
223                                            break;
224                                    }
225                            }
226    
227                            if (useDefault && Validator.isNotNull(priorityLanguageId) &&
228                                    Validator.isNull(value) && Validator.isNotNull(priorityValue)) {
229    
230                                    value = priorityValue;
231                            }
232    
233                            if (useDefault && Validator.isNull(value)) {
234                                    value = defaultValue;
235                            }
236                    }
237                    catch (Exception e) {
238                            if (_log.isWarnEnabled()) {
239                                    _log.warn(e, e);
240                            }
241                    }
242                    finally {
243                            if (contextClassLoader != portalClassLoader) {
244                                    currentThread.setContextClassLoader(contextClassLoader);
245                            }
246    
247                            if (xmlStreamReader != null) {
248                                    try {
249                                            xmlStreamReader.close();
250                                    }
251                                    catch (Exception e) {
252                                    }
253                            }
254                    }
255    
256                    _setCachedValue(xml, requestedLanguageId, useDefault, value);
257    
258                    return value;
259            }
260    
261            public Map<Locale, String> getLocalizationMap(
262                    PortletRequest portletRequest, String parameter) {
263    
264                    Locale[] locales = LanguageUtil.getAvailableLocales();
265    
266                    Map<Locale, String> map = new HashMap<Locale, String>();
267    
268                    for (Locale locale : locales) {
269                            String languageId = LocaleUtil.toLanguageId(locale);
270    
271                            String localeParameter =
272                                    parameter + StringPool.UNDERLINE + languageId;
273    
274                            map.put(
275                                    locale, ParamUtil.getString(portletRequest, localeParameter));
276                    }
277    
278                    return map;
279            }
280    
281            public Map<Locale, String> getLocalizationMap(String xml) {
282                    Locale[] locales = LanguageUtil.getAvailableLocales();
283    
284                    Map<Locale, String> map = new HashMap<Locale, String>();
285    
286                    for (Locale locale : locales) {
287                            String languageId = LocaleUtil.toLanguageId(locale);
288    
289                            map.put(locale, getLocalization(xml, languageId));
290                    }
291    
292                    return map;
293            }
294    
295            public String getLocalizationXmlFromPreferences(
296                    PortletPreferences preferences, PortletRequest portletRequest,
297                    String parameter) {
298    
299                    String xml = StringPool.BLANK;
300    
301                    Locale[] locales = LanguageUtil.getAvailableLocales();
302                    Locale defaultLocale = LocaleUtil.getDefault();
303                    String defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
304    
305                    for (Locale locale : locales) {
306                            String languageId = LocaleUtil.toLanguageId(locale);
307    
308                            String localParameter =
309                                    parameter + StringPool.UNDERLINE + languageId;
310    
311                            String value = PrefsParamUtil.getString(
312                                    preferences, portletRequest, localParameter);
313    
314                            if (Validator.isNotNull(value)) {
315                                    xml = updateLocalization(xml, parameter, value ,languageId);
316                            }
317                    }
318    
319                    if (Validator.isNull(getLocalization(xml, defaultLanguageId))) {
320                            String oldValue = PrefsParamUtil.getString(
321                                    preferences, portletRequest, parameter);
322    
323                            if (Validator.isNotNull(oldValue)) {
324                                    xml = updateLocalization(xml, parameter, oldValue);
325                            }
326                    }
327    
328                    return xml;
329            }
330    
331            public Map<Locale, String> getLocalizedParameter(
332                    PortletRequest portletRequest, String parameter) {
333    
334                    return getLocalizationMap(portletRequest, parameter);
335            }
336    
337            public String getPreferencesValue(
338                    PortletPreferences preferences, String key, String languageId) {
339    
340                    return getPreferencesValue(preferences, key, languageId, true);
341            }
342    
343            public String getPreferencesValue(
344                    PortletPreferences preferences, String key, String languageId,
345                    boolean useDefault) {
346    
347                    String localizedKey = _getPreferencesKey(key, languageId);
348    
349                    String value = preferences.getValue(localizedKey, StringPool.BLANK);
350    
351                    if (useDefault && Validator.isNull(value)) {
352                            value = preferences.getValue(key, StringPool.BLANK);
353                    }
354    
355                    return value;
356            }
357    
358            public String[] getPreferencesValues(
359                    PortletPreferences preferences, String key, String languageId) {
360    
361                    return getPreferencesValues(preferences, key, languageId, true);
362            }
363    
364            public String[] getPreferencesValues(
365                    PortletPreferences preferences, String key, String languageId,
366                    boolean useDefault) {
367    
368                    String localizedKey = _getPreferencesKey(key, languageId);
369    
370                    String[] values = preferences.getValues(localizedKey, new String[0]);
371    
372                    if (useDefault && Validator.isNull(values)) {
373                            values = preferences.getValues(key, new String[0]);
374                    }
375    
376                    return values;
377            }
378    
379            public String removeLocalization(
380                    String xml, String key, String requestedLanguageId) {
381    
382                    return removeLocalization(xml, key, requestedLanguageId, false);
383            }
384    
385            public String removeLocalization(
386                    String xml, String key, String requestedLanguageId, boolean cdata) {
387    
388                    return removeLocalization(xml, key, requestedLanguageId, cdata, true);
389            }
390    
391            public String removeLocalization(
392                    String xml, String key, String requestedLanguageId, boolean cdata,
393                    boolean localized) {
394    
395                    if (Validator.isNull(xml)) {
396                            return StringPool.BLANK;
397                    }
398    
399                    xml = _sanitizeXML(xml);
400    
401                    String systemDefaultLanguageId = LocaleUtil.toLanguageId(
402                            LocaleUtil.getDefault());
403    
404                    XMLStreamReader xmlStreamReader = null;
405                    XMLStreamWriter xmlStreamWriter = null;
406    
407                    ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
408    
409                    Thread currentThread = Thread.currentThread();
410    
411                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
412    
413                    try {
414                            if (contextClassLoader != portalClassLoader) {
415                                    currentThread.setContextClassLoader(portalClassLoader);
416                            }
417    
418                            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
419    
420                            xmlStreamReader = xmlInputFactory.createXMLStreamReader(
421                                    new UnsyncStringReader(xml));
422    
423                            String availableLocales = StringPool.BLANK;
424                            String defaultLanguageId = StringPool.BLANK;
425    
426                            // Read root node
427    
428                            if (xmlStreamReader.hasNext()) {
429                                    xmlStreamReader.nextTag();
430    
431                                    availableLocales = xmlStreamReader.getAttributeValue(
432                                            null, _AVAILABLE_LOCALES);
433                                    defaultLanguageId = xmlStreamReader.getAttributeValue(
434                                            null, _DEFAULT_LOCALE);
435    
436                                    if (Validator.isNull(defaultLanguageId)) {
437                                            defaultLanguageId = systemDefaultLanguageId;
438                                    }
439                            }
440    
441                            if ((availableLocales != null) &&
442                                    (availableLocales.indexOf(requestedLanguageId) != -1)) {
443    
444                                    availableLocales = StringUtil.remove(
445                                            availableLocales, requestedLanguageId, StringPool.COMMA);
446    
447                                    UnsyncStringWriter unsyncStringWriter =
448                                            new UnsyncStringWriter();
449    
450                                    XMLOutputFactory xmlOutputFactory =
451                                            XMLOutputFactory.newInstance();
452    
453                                    xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
454                                            unsyncStringWriter);
455    
456                                    xmlStreamWriter.writeStartDocument();
457                                    xmlStreamWriter.writeStartElement(_ROOT);
458    
459                                    if (localized) {
460                                            xmlStreamWriter.writeAttribute(
461                                                    _AVAILABLE_LOCALES, availableLocales);
462                                            xmlStreamWriter.writeAttribute(
463                                                    _DEFAULT_LOCALE, defaultLanguageId);
464                                    }
465    
466                                    _copyNonExempt(
467                                            xmlStreamReader, xmlStreamWriter, requestedLanguageId,
468                                            defaultLanguageId, cdata);
469    
470                                    xmlStreamWriter.writeEndElement();
471                                    xmlStreamWriter.writeEndDocument();
472    
473                                    xmlStreamWriter.close();
474                                    xmlStreamWriter = null;
475    
476                                    xml = unsyncStringWriter.toString();
477                            }
478                    }
479                    catch (Exception e) {
480                            if (_log.isWarnEnabled()) {
481                                    _log.warn(e, e);
482                            }
483                    }
484                    finally {
485                            if (contextClassLoader != portalClassLoader) {
486                                    currentThread.setContextClassLoader(contextClassLoader);
487                            }
488    
489                            if (xmlStreamReader != null) {
490                                    try {
491                                            xmlStreamReader.close();
492                                    }
493                                    catch (Exception e) {
494                                    }
495                            }
496    
497                            if (xmlStreamWriter != null) {
498                                    try {
499                                            xmlStreamWriter.close();
500                                    }
501                                    catch (Exception e) {
502                                    }
503                            }
504                    }
505    
506                    return xml;
507            }
508    
509            public void setLocalizedPreferencesValues (
510                            PortletRequest portletRequest, PortletPreferences preferences,
511                            String parameter)
512                    throws Exception {
513    
514                    Map<Locale, String> map = getLocalizationMap(
515                            portletRequest, parameter);
516    
517                    for (Map.Entry<Locale, String> entry : map.entrySet()) {
518                            String languageId = LocaleUtil.toLanguageId(entry.getKey());
519                            String value = entry.getValue();
520    
521                            setPreferencesValue(preferences, parameter, languageId, value);
522                    }
523            }
524    
525            public void setPreferencesValue(
526                            PortletPreferences preferences, String key, String languageId,
527                            String value)
528                    throws Exception {
529    
530                    preferences.setValue(_getPreferencesKey(key, languageId), value);
531            }
532    
533            public void setPreferencesValues(
534                            PortletPreferences preferences, String key, String languageId,
535                            String[] values)
536                    throws Exception {
537    
538                    preferences.setValues(_getPreferencesKey(key, languageId), values);
539            }
540    
541            public String updateLocalization(String xml, String key, String value) {
542                    String defaultLanguageId = LocaleUtil.toLanguageId(
543                            LocaleUtil.getDefault());
544    
545                    return updateLocalization(
546                            xml, key, value, defaultLanguageId, defaultLanguageId);
547            }
548    
549            public String updateLocalization(
550                    String xml, String key, String value, String requestedLanguageId) {
551    
552                    String defaultLanguageId = LocaleUtil.toLanguageId(
553                            LocaleUtil.getDefault());
554    
555                    return updateLocalization(
556                            xml, key, value, requestedLanguageId, defaultLanguageId);
557            }
558    
559            public String updateLocalization(
560                    String xml, String key, String value, String requestedLanguageId,
561                    String defaultLanguageId) {
562    
563                    return updateLocalization(
564                            xml, key, value, requestedLanguageId, defaultLanguageId, false);
565            }
566    
567            public String updateLocalization(
568                    String xml, String key, String value, String requestedLanguageId,
569                    String defaultLanguageId, boolean cdata) {
570    
571                    return updateLocalization(
572                            xml, key, value, requestedLanguageId, defaultLanguageId, cdata,
573                            true);
574            }
575    
576            public String updateLocalization(
577                    String xml, String key, String value, String requestedLanguageId,
578                    String defaultLanguageId, boolean cdata, boolean localized) {
579    
580                    xml = _sanitizeXML(xml);
581    
582                    XMLStreamReader xmlStreamReader = null;
583                    XMLStreamWriter xmlStreamWriter = null;
584    
585                    ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
586    
587                    Thread currentThread = Thread.currentThread();
588    
589                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
590    
591                    try {
592                            if (contextClassLoader != portalClassLoader) {
593                                    currentThread.setContextClassLoader(portalClassLoader);
594                            }
595    
596                            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
597    
598                            xmlStreamReader = xmlInputFactory.createXMLStreamReader(
599                                    new UnsyncStringReader(xml));
600    
601                            String availableLocales = StringPool.BLANK;
602    
603                            // Read root node
604    
605                            if (xmlStreamReader.hasNext()) {
606                                    xmlStreamReader.nextTag();
607    
608                                    availableLocales = xmlStreamReader.getAttributeValue(
609                                            null, _AVAILABLE_LOCALES);
610    
611                                    if (Validator.isNull(availableLocales)) {
612                                            availableLocales = defaultLanguageId;
613                                    }
614    
615                                    if (availableLocales.indexOf(requestedLanguageId) == -1) {
616                                            availableLocales = StringUtil.add(
617                                                    availableLocales, requestedLanguageId,
618                                                    StringPool.COMMA);
619                                    }
620                            }
621    
622                            UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
623    
624                            XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
625    
626                            xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
627                                    unsyncStringWriter);
628    
629                            xmlStreamWriter.writeStartDocument();
630                            xmlStreamWriter.writeStartElement(_ROOT);
631    
632                            if (localized) {
633                                    xmlStreamWriter.writeAttribute(
634                                            _AVAILABLE_LOCALES, availableLocales);
635                                    xmlStreamWriter.writeAttribute(
636                                            _DEFAULT_LOCALE, defaultLanguageId);
637                            }
638    
639                            _copyNonExempt(
640                                    xmlStreamReader, xmlStreamWriter, requestedLanguageId,
641                                    defaultLanguageId, cdata);
642    
643                            xmlStreamWriter.writeStartElement(key);
644    
645                            if (localized) {
646                                    xmlStreamWriter.writeAttribute(
647                                            _LANGUAGE_ID, requestedLanguageId);
648                            }
649    
650                            if (cdata) {
651                                    xmlStreamWriter.writeCData(value);
652                            }
653                            else {
654                                    xmlStreamWriter.writeCharacters(value);
655                            }
656    
657                            xmlStreamWriter.writeEndElement();
658                            xmlStreamWriter.writeEndElement();
659                            xmlStreamWriter.writeEndDocument();
660    
661                            xmlStreamWriter.close();
662                            xmlStreamWriter = null;
663    
664                            xml = unsyncStringWriter.toString();
665                    }
666                    catch (Exception e) {
667                            if (_log.isWarnEnabled()) {
668                                    _log.warn(e, e);
669                            }
670                    }
671                    finally {
672                            if (contextClassLoader != portalClassLoader) {
673                                    currentThread.setContextClassLoader(contextClassLoader);
674                            }
675    
676                            if (xmlStreamReader != null) {
677                                    try {
678                                            xmlStreamReader.close();
679                                    }
680                                    catch (Exception e) {
681                                    }
682                            }
683    
684                            if (xmlStreamWriter != null) {
685                                    try {
686                                            xmlStreamWriter.close();
687                                    }
688                                    catch (Exception e) {
689                                    }
690                            }
691                    }
692    
693                    return xml;
694            }
695    
696            private void _copyNonExempt(
697                            XMLStreamReader xmlStreamReader, XMLStreamWriter xmlStreamWriter,
698                            String exemptLanguageId, String defaultLanguageId, boolean cdata)
699                    throws XMLStreamException {
700    
701                    while (xmlStreamReader.hasNext()) {
702                            int event = xmlStreamReader.next();
703    
704                            if (event == XMLStreamConstants.START_ELEMENT) {
705                                    String languageId = xmlStreamReader.getAttributeValue(
706                                            null, _LANGUAGE_ID);
707    
708                                    if (Validator.isNull(languageId)) {
709                                            languageId = defaultLanguageId;
710                                    }
711    
712                                    if (!languageId.equals(exemptLanguageId)) {
713                                            xmlStreamWriter.writeStartElement(
714                                                    xmlStreamReader.getLocalName());
715                                            xmlStreamWriter.writeAttribute(_LANGUAGE_ID, languageId);
716    
717                                            while (xmlStreamReader.hasNext()) {
718                                                    event = xmlStreamReader.next();
719    
720                                                    if ((event == XMLStreamConstants.CHARACTERS) ||
721                                                            (event == XMLStreamConstants.CDATA)) {
722    
723                                                            String text = xmlStreamReader.getText();
724    
725                                                            if (cdata) {
726                                                                    xmlStreamWriter.writeCData(text);
727                                                            }
728                                                            else {
729                                                                    xmlStreamWriter.writeCharacters(
730                                                                            xmlStreamReader.getText());
731                                                            }
732    
733                                                            break;
734                                                    }
735                                                    else if (event == XMLStreamConstants.END_ELEMENT) {
736                                                            break;
737                                                    }
738                                            }
739    
740                                            xmlStreamWriter.writeEndElement();
741                                    }
742                            }
743                            else if (event == XMLStreamConstants.END_DOCUMENT) {
744                                    break;
745                            }
746                    }
747            }
748    
749            private String _getCachedValue(
750                    String xml, String requestedLanguageId, boolean useDefault) {
751    
752                    String value = null;
753    
754                    Map<Tuple, String> valueMap = _cache.get(xml);
755    
756                    if (valueMap != null) {
757                            Tuple subkey = new Tuple(useDefault, requestedLanguageId);
758    
759                            value = valueMap.get(subkey);
760                    }
761    
762                    return value;
763            }
764    
765            private String _getPreferencesKey(String key, String languageId) {
766                    String defaultLanguageId = LocaleUtil.toLanguageId(
767                            LocaleUtil.getDefault());
768    
769                    if (!languageId.equals(defaultLanguageId)) {
770                            key += StringPool.UNDERLINE + languageId;
771                    }
772    
773                    return key;
774            }
775    
776            private String _getRootAttribute(
777                    String xml, String name, String defaultValue) {
778    
779                    String value = null;
780    
781                    XMLStreamReader xmlStreamReader = null;
782    
783                    ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
784    
785                    Thread currentThread = Thread.currentThread();
786    
787                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
788    
789                    try {
790                            if (contextClassLoader != portalClassLoader) {
791                                    currentThread.setContextClassLoader(portalClassLoader);
792                            }
793    
794                            XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
795    
796                            xmlStreamReader = xmlInputFactory.createXMLStreamReader(
797                                    new UnsyncStringReader(xml));
798    
799                            if (xmlStreamReader.hasNext()) {
800                                    xmlStreamReader.nextTag();
801    
802                                    value = xmlStreamReader.getAttributeValue(null, name);
803                            }
804                    }
805                    catch (Exception e) {
806                            if (_log.isWarnEnabled()) {
807                                    _log.warn(e, e);
808                            }
809                    }
810                    finally {
811                            if (contextClassLoader != portalClassLoader) {
812                                    currentThread.setContextClassLoader(contextClassLoader);
813                            }
814    
815                            if (xmlStreamReader != null) {
816                                    try {
817                                            xmlStreamReader.close();
818                                    }
819                                    catch (Exception e) {
820                                    }
821                            }
822                    }
823    
824                    if (Validator.isNull(value)) {
825                            value = defaultValue;
826                    }
827    
828                    return value;
829            }
830    
831            private String _sanitizeXML(String xml) {
832                    if (Validator.isNull(xml) || (xml.indexOf("<root") == -1)) {
833                            xml = _EMPTY_ROOT_NODE;
834                    }
835    
836                    return xml;
837            }
838    
839            private void _setCachedValue(
840                    String xml, String requestedLanguageId, boolean useDefault,
841                    String value) {
842    
843                    if (Validator.isNotNull(xml) && !xml.equals(_EMPTY_ROOT_NODE)) {
844                            synchronized (_cache) {
845                                    Map<Tuple, String> map = _cache.get(xml);
846    
847                                    if (map == null) {
848                                            map = new HashMap<Tuple, String>();
849                                    }
850    
851                                    Tuple subkey = new Tuple(useDefault, requestedLanguageId);
852    
853                                    map.put(subkey, value);
854    
855                                    _cache.put(xml, map);
856                            }
857                    }
858            }
859    
860            private static final String _AVAILABLE_LOCALES = "available-locales";
861    
862            private static final String _DEFAULT_LOCALE = "default-locale";
863    
864            private static final String _EMPTY_ROOT_NODE = "<root />";
865    
866            private static final String _LANGUAGE_ID = "language-id";
867    
868            private static final String _ROOT = "root";
869    
870            private static Log _log = LogFactoryUtil.getLog(LocalizationImpl.class);
871    
872            private Map<String, Map<Tuple, String>> _cache = new ReferenceMap(
873                    ReferenceMap.SOFT, ReferenceMap.HARD);
874    
875    }