/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.util;
import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.language.LanguageUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.security.pacl.DoPrivileged;
import com.liferay.portal.kernel.security.xml.SecureXMLFactoryProviderUtil;
import com.liferay.portal.kernel.settings.LocalizedValuesMap;
import com.liferay.portal.kernel.settings.Settings;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.ClassLoaderUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.Localization;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.PrefsParamUtil;
import com.liferay.portal.kernel.util.ResourceBundleUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Tuple;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.xml.Document;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.language.LanguageResources;
import com.liferay.util.ContentUtil;
import com.liferay.util.xml.XMLUtil;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.function.Function;
import javax.portlet.PortletPreferences;
import javax.portlet.PortletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import org.apache.commons.collections.map.ReferenceMap;
/**
* @author Alexander Chow
* @author Jorge Ferrer
* @author Mauro Mariuzzo
* @author Julio Camarero
* @author Brian Wing Shun Chan
* @author Connor McKay
*/
@DoPrivileged
public class LocalizationImpl implements Localization {
@Override
public Object deserialize(JSONObject jsonObject) {
Map<Locale, String> map = new HashMap<>();
for (Locale locale : LanguageUtil.getAvailableLocales()) {
String languageId = LocaleUtil.toLanguageId(locale);
String value = jsonObject.getString(languageId);
if (Validator.isNotNull(value)) {
map.put(locale, value);
}
}
return map;
}
@Override
public String[] getAvailableLanguageIds(Document document) {
String attributeValue = _getRootAttributeValue(
document, _AVAILABLE_LOCALES, StringPool.BLANK);
return StringUtil.split(attributeValue);
}
@Override
public String[] getAvailableLanguageIds(String xml) {
String attributeValue = _getRootAttributeValue(
xml, _AVAILABLE_LOCALES, StringPool.BLANK);
return StringUtil.split(attributeValue);
}
@Override
public Locale getDefaultImportLocale(
String className, long classPK, Locale contentDefaultLocale,
Locale[] contentAvailableLocales) {
if (LanguageUtil.isAvailableLocale(contentDefaultLocale)) {
return contentDefaultLocale;
}
Locale defaultLocale = LocaleUtil.getSiteDefault();
if (ArrayUtil.contains(contentAvailableLocales, defaultLocale)) {
return defaultLocale;
}
for (Locale contentAvailableLocale : contentAvailableLocales) {
if (LanguageUtil.isAvailableLocale(contentAvailableLocale)) {
return contentAvailableLocale;
}
}
if (_log.isWarnEnabled()) {
StringBundler sb = new StringBundler(9);
sb.append("Language ");
sb.append(LocaleUtil.toLanguageId(contentDefaultLocale));
sb.append(" is missing for ");
sb.append(className);
sb.append(" with primary key ");
sb.append(classPK);
sb.append(". Setting default language to ");
sb.append(LocaleUtil.toLanguageId(defaultLocale));
sb.append(".");
_log.warn(sb.toString());
}
return defaultLocale;
}
@Override
public String getDefaultLanguageId(Document document) {
return getDefaultLanguageId(document, LocaleUtil.getSiteDefault());
}
@Override
public String getDefaultLanguageId(
Document document, Locale defaultLocale) {
String defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
return _getRootAttributeValue(
document, _DEFAULT_LOCALE, defaultLanguageId);
}
@Override
public String getDefaultLanguageId(String xml) {
return getDefaultLanguageId(xml, LocaleUtil.getSiteDefault());
}
@Override
public String getDefaultLanguageId(String xml, Locale defaultLocale) {
String defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
return _getRootAttributeValue(xml, _DEFAULT_LOCALE, defaultLanguageId);
}
@Override
public String getLocalization(
Function<String, String> localizationFunction,
String requestedLanguageId, String defaultLanguageId) {
String value = localizationFunction.apply(requestedLanguageId);
if (!Validator.isBlank(value)) {
return value;
}
if (!Validator.isBlank(defaultLanguageId)) {
return localizationFunction.apply(defaultLanguageId);
}
return StringPool.BLANK;
}
@Override
public String getLocalization(String xml, String requestedLanguageId) {
return getLocalization(xml, requestedLanguageId, true);
}
@Override
public String getLocalization(
String xml, String requestedLanguageId, boolean useDefault) {
return getLocalization(
xml, requestedLanguageId, useDefault, StringPool.BLANK);
}
@Override
public String getLocalization(
String xml, String requestedLanguageId, boolean useDefault,
String defaultValue) {
if (!Validator.isXml(xml)) {
if (useDefault) {
return xml;
}
if (requestedLanguageId.equals(
LocaleUtil.toLanguageId(LocaleUtil.getSiteDefault()))) {
return xml;
}
return defaultValue;
}
String value = _getCachedValue(xml, requestedLanguageId, useDefault);
if (value != null) {
return value;
}
String systemDefaultLanguageId = LocaleUtil.toLanguageId(
LocaleUtil.getSiteDefault());
String priorityLanguageId = null;
Locale requestedLocale = LocaleUtil.fromLanguageId(requestedLanguageId);
if (useDefault &&
LanguageUtil.isDuplicateLanguageCode(
requestedLocale.getLanguage())) {
Locale priorityLocale = LanguageUtil.getLocale(
requestedLocale.getLanguage());
if (!requestedLanguageId.equals(priorityLanguageId)) {
priorityLanguageId = LocaleUtil.toLanguageId(priorityLocale);
}
}
XMLStreamReader xmlStreamReader = null;
ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
ClassLoader contextClassLoader =
ClassLoaderUtil.getContextClassLoader();
try {
if (contextClassLoader != portalClassLoader) {
ClassLoaderUtil.setContextClassLoader(portalClassLoader);
}
XMLInputFactory xmlInputFactory =
SecureXMLFactoryProviderUtil.newXMLInputFactory();
xmlStreamReader = xmlInputFactory.createXMLStreamReader(
new UnsyncStringReader(xml));
String defaultLanguageId = StringPool.BLANK;
// Skip root node
if (xmlStreamReader.hasNext()) {
xmlStreamReader.nextTag();
defaultLanguageId = xmlStreamReader.getAttributeValue(
null, _DEFAULT_LOCALE);
if (Validator.isNull(defaultLanguageId)) {
defaultLanguageId = systemDefaultLanguageId;
}
}
// Find specified language and/or default language
String priorityValue = null;
String defaultLocalizationValue = null;
while (xmlStreamReader.hasNext()) {
int event = xmlStreamReader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
String languageId = xmlStreamReader.getAttributeValue(
null, _LANGUAGE_ID);
if (Validator.isNull(languageId)) {
languageId = defaultLanguageId;
}
if (languageId.equals(defaultLanguageId) ||
languageId.equals(priorityLanguageId) ||
languageId.equals(requestedLanguageId)) {
String text = xmlStreamReader.getElementText();
if (languageId.equals(defaultLanguageId)) {
defaultLocalizationValue = text;
}
if (languageId.equals(priorityLanguageId)) {
priorityValue = text;
}
if (languageId.equals(requestedLanguageId)) {
value = text;
}
if (Validator.isNotNull(value)) {
break;
}
}
}
else if (event == XMLStreamConstants.END_DOCUMENT) {
break;
}
}
if (useDefault && Validator.isNotNull(priorityLanguageId) &&
Validator.isNull(value) && Validator.isNotNull(priorityValue)) {
value = priorityValue;
}
if (useDefault && Validator.isNull(value)) {
value = defaultLocalizationValue;
}
if (Validator.isNull(value)) {
value = defaultValue;
}
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(e, e);
}
}
finally {
if (contextClassLoader != portalClassLoader) {
ClassLoaderUtil.setContextClassLoader(contextClassLoader);
}
if (xmlStreamReader != null) {
try {
xmlStreamReader.close();
}
catch (Exception e) {
}
}
}
_setCachedValue(xml, requestedLanguageId, useDefault, value);
return value;
}
@Override
public Map<Locale, String> getLocalizationMap(
Collection<Locale> locales, Locale defaultLocale, String key) {
Map<Locale, String> map = new HashMap<>();
String defaultValue = LanguageUtil.get(defaultLocale, key);
for (Locale locale : locales) {
String value = LanguageUtil.get(locale, key);
if (!locale.equals(defaultLocale) && value.equals(defaultValue)) {
continue;
}
map.put(locale, value);
}
return map;
}
@Override
public Map<Locale, String> getLocalizationMap(
HttpServletRequest request, String parameter) {
Map<Locale, String> map = new HashMap<>();
for (Locale locale : LanguageUtil.getAvailableLocales()) {
String localizedParameter = getLocalizedName(
parameter, LocaleUtil.toLanguageId(locale));
map.put(locale, ParamUtil.getString(request, localizedParameter));
}
return map;
}
@Override
public Map<Locale, String> getLocalizationMap(
PortletPreferences preferences, String preferenceName) {
return getLocalizationMap(preferences, preferenceName, null);
}
@Override
public Map<Locale, String> getLocalizationMap(
PortletPreferences preferences, String preferenceName,
String propertyName) {
String defaultPropertyValue = null;
if (propertyName != null) {
defaultPropertyValue = PropsUtil.get(propertyName);
}
Class<?> clazz = getClass();
return getLocalizationMap(
preferences, preferenceName, propertyName, defaultPropertyValue,
clazz.getClassLoader());
}
@Override
public Map<Locale, String> getLocalizationMap(
PortletPreferences preferences, String preferenceName,
String propertyName, String defaultPropertyValue,
ClassLoader classLoader) {
Map<Locale, String> map = new HashMap<>();
for (Locale locale : LanguageUtil.getAvailableLocales()) {
String localizedPreference = getLocalizedName(
preferenceName, LocaleUtil.toLanguageId(locale));
map.put(
locale,
preferences.getValue(localizedPreference, StringPool.BLANK));
}
if (Validator.isNull(propertyName)) {
return map;
}
Locale defaultLocale = LocaleUtil.getSiteDefault();
String defaultValue = map.get(defaultLocale);
if (Validator.isNotNull(defaultValue)) {
return map;
}
map.put(
defaultLocale, ContentUtil.get(classLoader, defaultPropertyValue));
return map;
}
@Override
public Map<Locale, String> getLocalizationMap(
PortletRequest portletRequest, String parameter) {
return getLocalizationMap(
portletRequest, parameter, new HashMap<Locale, String>());
}
@Override
public Map<Locale, String> getLocalizationMap(
PortletRequest portletRequest, String parameter,
Map<Locale, String> defaultValues) {
Map<Locale, String> map = new HashMap<>();
for (Locale locale : LanguageUtil.getAvailableLocales()) {
String localizedParameter = getLocalizedName(
parameter, LocaleUtil.toLanguageId(locale));
map.put(
locale,
ParamUtil.getString(
portletRequest, localizedParameter,
defaultValues.get(locale)));
}
return map;
}
@Override
public Map<Locale, String> getLocalizationMap(String xml) {
return getLocalizationMap(xml, false);
}
@Override
public Map<Locale, String> getLocalizationMap(
String xml, boolean useDefault) {
Map<Locale, String> map = new HashMap<>();
for (Locale locale : LanguageUtil.getAvailableLocales()) {
String languageId = LocaleUtil.toLanguageId(locale);
String value = getLocalization(xml, languageId, useDefault);
if (Validator.isNotNull(value)) {
map.put(locale, value);
}
}
return map;
}
@Override
public Map<Locale, String> getLocalizationMap(
String bundleName, ClassLoader classLoader, String key,
boolean includeBetaLocales) {
if (key == null) {
return null;
}
Map<Locale, String> map = new HashMap<>();
Locale defaultLocale = LocaleUtil.getSiteDefault();
String defaultValue = _getLocalization(
bundleName, defaultLocale, classLoader, key, key);
map.put(defaultLocale, defaultValue);
Set<Locale> locales = null;
if (includeBetaLocales) {
locales = LanguageUtil.getAvailableLocales();
}
else {
locales = LanguageUtil.getSupportedLocales();
}
for (Locale locale : locales) {
if (locale.equals(defaultLocale)) {
continue;
}
String value = _getLocalization(
bundleName, locale, classLoader, key, null);
if (Validator.isNotNull(value) && !value.equals(defaultValue)) {
map.put(locale, value);
}
}
return map;
}
@Override
public Map<Locale, String> getLocalizationMap(
String[] languageIds, String[] values) {
Map<Locale, String> map = new HashMap<>();
for (int i = 0; i < values.length; i++) {
Locale locale = LocaleUtil.fromLanguageId(languageIds[i]);
map.put(locale, values[i]);
}
return map;
}
@Override
public String getLocalizationXmlFromPreferences(
PortletPreferences preferences, PortletRequest portletRequest,
String parameter) {
return getLocalizationXmlFromPreferences(
preferences, portletRequest, parameter, null, null);
}
@Override
public String getLocalizationXmlFromPreferences(
PortletPreferences preferences, PortletRequest portletRequest,
String parameter, String defaultValue) {
return getLocalizationXmlFromPreferences(
preferences, portletRequest, parameter, defaultValue, null);
}
@Override
public String getLocalizationXmlFromPreferences(
PortletPreferences preferences, PortletRequest portletRequest,
String parameter, String prefix, String defaultValue) {
String xml = null;
Locale defaultLocale = LocaleUtil.getSiteDefault();
String defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
for (Locale locale : LanguageUtil.getAvailableLocales()) {
String languageId = LocaleUtil.toLanguageId(locale);
String localizedKey = getLocalizedName(parameter, languageId);
String prefixedLocalizedKey = localizedKey;
if (Validator.isNotNull(prefix)) {
prefixedLocalizedKey = prefix + "--" + localizedKey + "--";
}
String value = ParamUtil.getString(
portletRequest, prefixedLocalizedKey,
preferences.getValue(localizedKey, null));
if (value != null) {
xml = updateLocalization(xml, parameter, value, languageId);
}
}
if (getLocalization(xml, defaultLanguageId, true, null) == null) {
String oldValue = PrefsParamUtil.getString(
preferences, portletRequest, parameter, defaultValue);
if (Validator.isNotNull(oldValue)) {
xml = updateLocalization(xml, parameter, oldValue);
}
}
return xml;
}
@Override
public String getLocalizedName(String name, String languageId) {
return name.concat(StringPool.UNDERLINE).concat(languageId);
}
@Override
public Map<Locale, String> getMap(LocalizedValuesMap localizedValuesMap) {
Map<Locale, String> map = localizedValuesMap.getValues();
Locale locale = LocaleUtil.getDefault();
if (map.get(locale) == null) {
map.put(locale, localizedValuesMap.getDefaultValue());
}
return map;
}
/**
* @deprecated As of 7.0.0
*/
@Deprecated
@Override
public String getPreferencesKey(String key, String languageId) {
String defaultLanguageId = LocaleUtil.toLanguageId(
LocaleUtil.getSiteDefault());
if (!languageId.equals(defaultLanguageId)) {
key = getLocalizedName(key, languageId);
}
return key;
}
@Override
public String getPreferencesValue(
PortletPreferences preferences, String key, String languageId) {
return getPreferencesValue(preferences, key, languageId, true);
}
@Override
public String getPreferencesValue(
PortletPreferences preferences, String key, String languageId,
boolean useDefault) {
String localizedKey = getLocalizedName(key, languageId);
String value = preferences.getValue(localizedKey, StringPool.BLANK);
if (useDefault && Validator.isNull(value)) {
value = preferences.getValue(
_getDefaultLocalizedName(key), StringPool.BLANK);
if (Validator.isNull(value)) {
value = preferences.getValue(key, StringPool.BLANK);
}
}
return value;
}
@Override
public String[] getPreferencesValues(
PortletPreferences preferences, String key, String languageId) {
return getPreferencesValues(preferences, key, languageId, true);
}
@Override
public String[] getPreferencesValues(
PortletPreferences preferences, String key, String languageId,
boolean useDefault) {
String localizedKey = getLocalizedName(key, languageId);
String[] values = preferences.getValues(localizedKey, new String[0]);
if (useDefault && ArrayUtil.isEmpty(values)) {
values = preferences.getValues(
_getDefaultLocalizedName(key), new String[0]);
if (ArrayUtil.isEmpty(values)) {
values = preferences.getValues(key, new String[0]);
}
}
return values;
}
@Override
public String getSettingsValue(
Settings settings, String key, String languageId) {
return getSettingsValue(settings, key, languageId, true);
}
@Override
public String getSettingsValue(
Settings settings, String key, String languageId, boolean useDefault) {
String localizedKey = getLocalizedName(key, languageId);
String value = settings.getValue(localizedKey, StringPool.BLANK);
if (useDefault && Validator.isNull(value)) {
value = settings.getValue(
_getDefaultLocalizedName(key), StringPool.BLANK);
if (Validator.isNull(value)) {
value = settings.getValue(key, StringPool.BLANK);
}
}
return value;
}
@Override
public String[] getSettingsValues(
Settings settings, String key, String languageId) {
return getSettingsValues(settings, key, languageId, true);
}
@Override
public String[] getSettingsValues(
Settings settings, String key, String languageId, boolean useDefault) {
String localizedKey = getLocalizedName(key, languageId);
String[] values = settings.getValues(localizedKey, new String[0]);
if (useDefault && ArrayUtil.isEmpty(values)) {
values = settings.getValues(
_getDefaultLocalizedName(key), new String[0]);
if (ArrayUtil.isEmpty(values)) {
values = settings.getValues(key, new String[0]);
}
}
return values;
}
@Override
public String getXml(LocalizedValuesMap localizedValuesMap, String key) {
XMLStreamWriter xmlStreamWriter = null;
try {
UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
unsyncStringWriter);
xmlStreamWriter.writeStartDocument();
xmlStreamWriter.writeStartElement("root");
Set<Locale> availableLocales = LanguageUtil.getAvailableLocales();
xmlStreamWriter.writeAttribute(
"available-locales", StringUtil.merge(availableLocales));
Locale defaultLocale = LocaleUtil.getSiteDefault();
xmlStreamWriter.writeAttribute(
"default-locale", defaultLocale.toString());
for (Locale locale : availableLocales) {
String value = localizedValuesMap.get(locale);
if (value != null) {
xmlStreamWriter.writeStartElement(key);
xmlStreamWriter.writeAttribute(
"language-id", locale.toString());
xmlStreamWriter.writeCharacters(value);
xmlStreamWriter.writeEndElement();
}
}
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndDocument();
return unsyncStringWriter.toString();
}
catch (XMLStreamException xmlse) {
throw new RuntimeException(xmlse);
}
finally {
_close(xmlStreamWriter);
}
}
@Override
public String getXml(
Map<String, String> map, String defaultLanguageId, String key) {
UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
XMLStreamWriter xmlStreamWriter = null;
try {
xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
unsyncStringWriter);
xmlStreamWriter.writeStartDocument();
xmlStreamWriter.writeStartElement(_ROOT);
xmlStreamWriter.writeAttribute(
_AVAILABLE_LOCALES, StringUtil.merge(map.keySet()));
xmlStreamWriter.writeAttribute(_DEFAULT_LOCALE, defaultLanguageId);
for (Map.Entry<String, String> entry : map.entrySet()) {
String languageId = entry.getKey();
String value = entry.getValue();
xmlStreamWriter.writeStartElement(key);
xmlStreamWriter.writeAttribute(_LANGUAGE_ID, languageId);
xmlStreamWriter.writeCharacters(
XMLUtil.stripInvalidChars(value));
xmlStreamWriter.writeEndElement();
}
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndDocument();
return unsyncStringWriter.toString();
}
catch (Exception ioe) {
_log.error(ioe, ioe);
}
finally {
if (xmlStreamWriter != null) {
try {
xmlStreamWriter.close();
}
catch (XMLStreamException xmlse) {
_log.error(xmlse, xmlse);
}
}
}
return StringPool.BLANK;
}
@Override
public String removeLocalization(
String xml, String key, String requestedLanguageId) {
return removeLocalization(xml, key, requestedLanguageId, false);
}
@Override
public String removeLocalization(
String xml, String key, String requestedLanguageId, boolean cdata) {
return removeLocalization(xml, key, requestedLanguageId, cdata, true);
}
@Override
public String removeLocalization(
String xml, String key, String requestedLanguageId, boolean cdata,
boolean localized) {
if (Validator.isNull(xml)) {
return StringPool.BLANK;
}
if (!Validator.isXml(xml)) {
return xml;
}
xml = _sanitizeXML(xml);
String systemDefaultLanguageId = LocaleUtil.toLanguageId(
LocaleUtil.getSiteDefault());
XMLStreamReader xmlStreamReader = null;
XMLStreamWriter xmlStreamWriter = null;
ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
ClassLoader contextClassLoader =
ClassLoaderUtil.getContextClassLoader();
try {
if (contextClassLoader != portalClassLoader) {
ClassLoaderUtil.setContextClassLoader(portalClassLoader);
}
XMLInputFactory xmlInputFactory =
SecureXMLFactoryProviderUtil.newXMLInputFactory();
xmlStreamReader = xmlInputFactory.createXMLStreamReader(
new UnsyncStringReader(xml));
String availableLocales = StringPool.BLANK;
String defaultLanguageId = StringPool.BLANK;
// Read root node
if (xmlStreamReader.hasNext()) {
xmlStreamReader.nextTag();
availableLocales = xmlStreamReader.getAttributeValue(
null, _AVAILABLE_LOCALES);
defaultLanguageId = xmlStreamReader.getAttributeValue(
null, _DEFAULT_LOCALE);
if (Validator.isNull(defaultLanguageId)) {
defaultLanguageId = systemDefaultLanguageId;
}
}
if ((availableLocales != null) &&
availableLocales.contains(requestedLanguageId)) {
availableLocales = StringUtil.removeFromList(
availableLocales, requestedLanguageId);
UnsyncStringWriter unsyncStringWriter =
new UnsyncStringWriter();
XMLOutputFactory xmlOutputFactory =
XMLOutputFactory.newInstance();
xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
unsyncStringWriter);
xmlStreamWriter.writeStartDocument();
xmlStreamWriter.writeStartElement(_ROOT);
if (localized) {
xmlStreamWriter.writeAttribute(
_AVAILABLE_LOCALES, availableLocales);
xmlStreamWriter.writeAttribute(
_DEFAULT_LOCALE, defaultLanguageId);
}
_copyNonExempt(
xmlStreamReader, xmlStreamWriter, requestedLanguageId,
defaultLanguageId, cdata);
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndDocument();
xmlStreamWriter.close();
xmlStreamWriter = null;
xml = unsyncStringWriter.toString();
}
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(e, e);
}
}
finally {
if (contextClassLoader != portalClassLoader) {
ClassLoaderUtil.setContextClassLoader(contextClassLoader);
}
if (xmlStreamReader != null) {
try {
xmlStreamReader.close();
}
catch (Exception e) {
}
}
if (xmlStreamWriter != null) {
try {
xmlStreamWriter.close();
}
catch (Exception e) {
}
}
}
return xml;
}
@Override
public void setLocalizedPreferencesValues(
PortletRequest portletRequest, PortletPreferences preferences,
String parameter)
throws Exception {
Map<Locale, String> map = getLocalizationMap(portletRequest, parameter);
for (Map.Entry<Locale, String> entry : map.entrySet()) {
String languageId = LocaleUtil.toLanguageId(entry.getKey());
String value = entry.getValue();
setPreferencesValue(preferences, parameter, languageId, value);
}
}
@Override
public void setPreferencesValue(
PortletPreferences preferences, String key, String languageId,
String value)
throws Exception {
preferences.setValue(getLocalizedName(key, languageId), value);
}
@Override
public void setPreferencesValues(
PortletPreferences preferences, String key, String languageId,
String[] values)
throws Exception {
preferences.setValues(getLocalizedName(key, languageId), values);
}
@Override
public String updateLocalization(
Map<Locale, String> localizationMap, String xml, String key,
String defaultLanguageId) {
for (Locale locale : LanguageUtil.getAvailableLocales()) {
String value = localizationMap.get(locale);
String languageId = LocaleUtil.toLanguageId(locale);
if (Validator.isNotNull(value)) {
xml = updateLocalization(
xml, key, value, languageId, defaultLanguageId);
}
else {
xml = removeLocalization(xml, key, languageId);
}
}
return xml;
}
@Override
public String updateLocalization(String xml, String key, String value) {
String defaultLanguageId = LocaleUtil.toLanguageId(
LocaleUtil.getSiteDefault());
return updateLocalization(
xml, key, value, defaultLanguageId, defaultLanguageId);
}
@Override
public String updateLocalization(
String xml, String key, String value, String requestedLanguageId) {
String defaultLanguageId = LocaleUtil.toLanguageId(
LocaleUtil.getSiteDefault());
return updateLocalization(
xml, key, value, requestedLanguageId, defaultLanguageId);
}
@Override
public String updateLocalization(
String xml, String key, String value, String requestedLanguageId,
String defaultLanguageId) {
return updateLocalization(
xml, key, value, requestedLanguageId, defaultLanguageId, false);
}
@Override
public String updateLocalization(
String xml, String key, String value, String requestedLanguageId,
String defaultLanguageId, boolean cdata) {
return updateLocalization(
xml, key, value, requestedLanguageId, defaultLanguageId, cdata,
true);
}
@Override
public String updateLocalization(
String xml, String key, String value, String requestedLanguageId,
String defaultLanguageId, boolean cdata, boolean localized) {
xml = _sanitizeXML(xml);
XMLStreamReader xmlStreamReader = null;
XMLStreamWriter xmlStreamWriter = null;
ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
ClassLoader contextClassLoader =
ClassLoaderUtil.getContextClassLoader();
try {
if (contextClassLoader != portalClassLoader) {
ClassLoaderUtil.setContextClassLoader(portalClassLoader);
}
XMLInputFactory xmlInputFactory =
SecureXMLFactoryProviderUtil.newXMLInputFactory();
xmlStreamReader = xmlInputFactory.createXMLStreamReader(
new UnsyncStringReader(xml));
String availableLocales = StringPool.BLANK;
// Read root node
if (xmlStreamReader.hasNext()) {
xmlStreamReader.nextTag();
availableLocales = xmlStreamReader.getAttributeValue(
null, _AVAILABLE_LOCALES);
if (Validator.isNull(availableLocales)) {
availableLocales = defaultLanguageId;
}
if (!availableLocales.contains(requestedLanguageId)) {
availableLocales = StringUtil.add(
availableLocales, requestedLanguageId,
StringPool.COMMA);
}
}
UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
unsyncStringWriter);
xmlStreamWriter.writeStartDocument();
xmlStreamWriter.writeStartElement(_ROOT);
if (localized) {
xmlStreamWriter.writeAttribute(
_AVAILABLE_LOCALES, availableLocales);
xmlStreamWriter.writeAttribute(
_DEFAULT_LOCALE, defaultLanguageId);
}
_copyNonExempt(
xmlStreamReader, xmlStreamWriter, requestedLanguageId,
defaultLanguageId, cdata);
xmlStreamWriter.writeStartElement(key);
if (localized) {
xmlStreamWriter.writeAttribute(
_LANGUAGE_ID, requestedLanguageId);
}
String safeValue = XMLUtil.stripInvalidChars(value);
if (cdata) {
xmlStreamWriter.writeCData(safeValue);
}
else {
xmlStreamWriter.writeCharacters(safeValue);
}
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndDocument();
xmlStreamWriter.close();
xmlStreamWriter = null;
xml = unsyncStringWriter.toString();
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(e, e);
}
}
finally {
if (contextClassLoader != portalClassLoader) {
ClassLoaderUtil.setContextClassLoader(contextClassLoader);
}
if (xmlStreamReader != null) {
try {
xmlStreamReader.close();
}
catch (Exception e) {
}
}
if (xmlStreamWriter != null) {
try {
xmlStreamWriter.close();
}
catch (Exception e) {
}
}
}
return xml;
}
private void _close(XMLStreamWriter xmlStreamWriter) {
if (xmlStreamWriter != null) {
try {
xmlStreamWriter.close();
}
catch (XMLStreamException xmlse) {
}
}
}
private void _copyNonExempt(
XMLStreamReader xmlStreamReader, XMLStreamWriter xmlStreamWriter,
String exemptLanguageId, String defaultLanguageId, boolean cdata)
throws XMLStreamException {
while (xmlStreamReader.hasNext()) {
int event = xmlStreamReader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
String languageId = xmlStreamReader.getAttributeValue(
null, _LANGUAGE_ID);
if (Validator.isNull(languageId)) {
languageId = defaultLanguageId;
}
if (!languageId.equals(exemptLanguageId)) {
xmlStreamWriter.writeStartElement(
xmlStreamReader.getLocalName());
xmlStreamWriter.writeAttribute(_LANGUAGE_ID, languageId);
String text = xmlStreamReader.getElementText();
if (cdata) {
xmlStreamWriter.writeCData(text);
}
else {
xmlStreamWriter.writeCharacters(text);
}
xmlStreamWriter.writeEndElement();
}
}
else if (event == XMLStreamConstants.END_DOCUMENT) {
break;
}
}
}
private String _getCachedValue(
String xml, String requestedLanguageId, boolean useDefault) {
String value = null;
Map<Tuple, String> valueMap = _cache.get(xml);
if (valueMap != null) {
Tuple subkey = new Tuple(useDefault, requestedLanguageId);
value = valueMap.get(subkey);
}
return value;
}
private String _getDefaultLocalizedName(String name) {
String defaultLanguageId = LocaleUtil.toLanguageId(
LocaleUtil.getSiteDefault());
return getLocalizedName(name, defaultLanguageId);
}
private String _getLocalization(
String bundleName, Locale locale, ClassLoader classLoader, String key,
String defaultValue) {
ResourceBundle resourceBundle = ResourceBundleUtil.getBundle(
bundleName, locale, classLoader);
String value = null;
if (resourceBundle.containsKey(key)) {
try {
value = ResourceBundleUtil.getString(resourceBundle, key);
value = new String(
value.getBytes(StringPool.ISO_8859_1), StringPool.UTF8);
}
catch (Exception e) {
}
}
if (Validator.isNotNull(value)) {
value = LanguageResources.fixValue(value);
}
else {
value = LanguageUtil.get(locale, key, defaultValue);
}
return value;
}
private String _getRootAttributeValue(
Document document, String name, String defaultValue) {
Element rootElement = document.getRootElement();
return rootElement.attributeValue(name, defaultValue);
}
private String _getRootAttributeValue(
String xml, String name, String defaultValue) {
if (!Validator.isXml(xml)) {
return defaultValue;
}
String value = null;
XMLStreamReader xmlStreamReader = null;
ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
ClassLoader contextClassLoader =
ClassLoaderUtil.getContextClassLoader();
try {
if (contextClassLoader != portalClassLoader) {
ClassLoaderUtil.setContextClassLoader(portalClassLoader);
}
XMLInputFactory xmlInputFactory =
SecureXMLFactoryProviderUtil.newXMLInputFactory();
xmlStreamReader = xmlInputFactory.createXMLStreamReader(
new UnsyncStringReader(xml));
if (xmlStreamReader.hasNext()) {
xmlStreamReader.nextTag();
value = xmlStreamReader.getAttributeValue(null, name);
}
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(e, e);
}
}
finally {
if (contextClassLoader != portalClassLoader) {
ClassLoaderUtil.setContextClassLoader(contextClassLoader);
}
if (xmlStreamReader != null) {
try {
xmlStreamReader.close();
}
catch (Exception e) {
}
}
}
if (Validator.isNull(value)) {
value = defaultValue;
}
return value;
}
private String _sanitizeXML(String xml) {
if (Validator.isNull(xml) || !xml.contains("<root")) {
xml = _EMPTY_ROOT_NODE;
}
return xml;
}
private void _setCachedValue(
String xml, String requestedLanguageId, boolean useDefault,
String value) {
if (Validator.isNotNull(xml) && !xml.equals(_EMPTY_ROOT_NODE)) {
synchronized (_cache) {
Map<Tuple, String> map = _cache.get(xml);
if (map == null) {
map = new HashMap<>();
}
Tuple subkey = new Tuple(useDefault, requestedLanguageId);
map.put(subkey, value);
_cache.put(xml, map);
}
}
}
private static final String _AVAILABLE_LOCALES = "available-locales";
private static final String _DEFAULT_LOCALE = "default-locale";
private static final String _EMPTY_ROOT_NODE = "<root />";
private static final String _LANGUAGE_ID = "language-id";
private static final String _ROOT = "root";
private static final Log _log = LogFactoryUtil.getLog(
LocalizationImpl.class);
private final Map<String, Map<Tuple, String>> _cache = new ReferenceMap(
ReferenceMap.SOFT, ReferenceMap.HARD);
}