package org.ovirt.engine.core.utils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import org.apache.commons.lang.text.StrSubstitutor; import org.ovirt.engine.core.common.interfaces.ErrorTranslator; import org.ovirt.engine.core.compat.LogCompat; import org.ovirt.engine.core.compat.LogFactoryCompat; import org.ovirt.engine.core.compat.StringHelper; public final class ErrorTranslatorImpl implements ErrorTranslator { private static final long ONE_HOUR = 60 * 60 * 1000L; private List<String> messageSources; private Locale standardLocale; private Map<String, String> standardMessages; private ReapedMap<Locale, Map<String, String>> messagesByLocale; // Will assume these are property files, not ResxFiles. public ErrorTranslatorImpl(String... errorFileNames) { messageSources = asList(errorFileNames); standardLocale = Locale.getDefault(); standardMessages = retrieveByLocale(standardLocale); messagesByLocale = new ReapedMap<Locale, Map<String, String>>(ONE_HOUR, true); } private synchronized Map<String, String> getMessages(Locale locale) { Map<String, String> messages = null; if (standardLocale.equals(locale)) { messages = standardMessages; } else { if ((messages = messagesByLocale.get(locale)) == null) { messages = retrieveByLocale(locale); messagesByLocale.put(locale, messages); messagesByLocale.reapable(locale); } } return messages; } private Map<String, String> retrieveByLocale(Locale locale) { Map<String, String> messages = new HashMap<String, String>(); for (String messageSource : messageSources) { retrieveByLocale(locale, messageSource, messages); } return messages; } private Map<String, String> retrieveByLocale(Locale locale, String messageSource, Map<String, String> messages) { try { ResourceBundle bundle = ResourceBundle.getBundle(messageSource, locale); for (String key : bundle.keySet()) { if (!messages.containsKey(key)) { messages.put(key, bundle.getString(key)); } else { log.warnFormat("Code {0} appears more then once in string table.", key); } } } catch (RuntimeException e) { log.errorFormat("File: {0} could not be loaded: {1}", messageSource, e.toString()); } return messages; } /* * (non-Javadoc) * * @see org.ovirt.engine.core.utils.ErrorTranslator#TranslateErrorText(java.util.List, boolean) */ public final List<String> TranslateErrorText(List<String> errorMsg, boolean changeIfNotFound) { return translate(errorMsg, changeIfNotFound, Locale.getDefault()); } private final List<String> translate(List<String> errorMsg, boolean changeIfNotFound, Locale locale) { List<String> translatedMessages = doTranslation(errorMsg, changeIfNotFound, locale); return ResolveMessages(translatedMessages); } /* * (non-Javadoc) * * @see org.ovirt.engine.core.utils.ErrorTranslator#TranslateErrorText(java.util.List) */ public List<String> TranslateErrorText(List<String> errorMsg) { return translate(errorMsg, true, Locale.getDefault()); } /* * (non-Javadoc) * * @see org.ovirt.engine.core.utils.ErrorTranslator#TranslateErrorText(java.util.List) */ public List<String> TranslateErrorText(List<String> errorMsg, Locale locale) { return translate(errorMsg, true, locale); } /* * (non-Javadoc) * * @see org.ovirt.engine.core.utils.ErrorTranslator#TranslateMessages(java.util.List, boolean) */ public final List<String> TranslateMessages(List<String> errorMsg, boolean changeIfNotFound) { return doTranslation(errorMsg, changeIfNotFound, Locale.getDefault()); } public final List<String> doTranslation(List<String> errorMsg, boolean changeIfNotFound, Locale locale) { java.util.ArrayList<String> translatedMessages = new java.util.ArrayList<String>(); if (errorMsg != null && errorMsg.size() > 0) { for (String curError : errorMsg) { translatedMessages.add(translate(curError, changeIfNotFound, locale)); } } return translatedMessages; } /* * (non-Javadoc) * * @see org.ovirt.engine.core.utils.ErrorTranslator#IsDynamicVariable(java.lang.String ) */ public final boolean IsDynamicVariable(String strMessage) { return strMessage.startsWith("$"); } /* * (non-Javadoc) * * @see org.ovirt.engine.core.utils.ErrorTranslator#TranslateErrorTextSingle(java. lang.String, boolean) */ public final String TranslateErrorTextSingle(String errorMsg, boolean changeIfNotFound) { return translate(errorMsg, changeIfNotFound, Locale.getDefault()); } /* * (non-Javadoc) * * @see org.ovirt.engine.core.utils.ErrorTranslator#TranslateErrorTextSingle(java. lang.String, boolean) */ public String TranslateErrorTextSingle(String errorMsg, Locale locale) { return translate(errorMsg, true, locale); } private final String translate(String errorMsg, boolean changeIfNotFound, Locale locale) { String ret = ""; Map<String, String> messages = getMessages(locale); if (messages != null && messages.containsKey(errorMsg)) { ret = messages.get(errorMsg); } else { if (!(errorMsg == null || errorMsg.isEmpty())) { if ((IsDynamicVariable(errorMsg)) || (!changeIfNotFound)) { ret = errorMsg; } else // just a message that doesn't have a value in the resource: { String[] splitted = errorMsg.toLowerCase().split("[_]", -1); ret = StringHelper.join(" ", splitted); } } } return ret; } /* * (non-Javadoc) * * @see org.ovirt.engine.core.utils.ErrorTranslator#TranslateErrorTextSingle(java. lang.String) */ public final String TranslateErrorTextSingle(String errorMsg) { return TranslateErrorTextSingle(errorMsg, true); } /* * (non-Javadoc) * * @see org.ovirt.engine.core.utils.ErrorTranslator#ResolveMessages(java.util.List) */ public final List<String> ResolveMessages(List<String> translatedMessages) { java.util.ArrayList<String> translatedErrors = new java.util.ArrayList<String>(); java.util.HashMap<String, String> variables = new java.util.HashMap<String, String>(); for (String currentMessage : translatedMessages) { if (currentMessage.startsWith("$")) { AddVariable(currentMessage, variables); } else { translatedErrors.add(currentMessage); } } /** * Place to global variable adding */ java.util.ArrayList<String> returnValue = new java.util.ArrayList<String>(); for (String error : translatedErrors) { returnValue.add(resolveMessage(error, variables)); } return returnValue; } private void AddVariable(String variable, java.util.HashMap<String, String> variables) { int firstSpace = variable.indexOf(' '); if (firstSpace != -1 && firstSpace < variable.length()) { String key = variable.substring(1, firstSpace); String value = variable.substring(firstSpace + 1); if (!variables.containsKey(key)) { variables.put(key, value); } } } private String resolveMessage(String message, java.util.HashMap<String, String> variables) { StrSubstitutor sub = new StrSubstitutor(variables); return sub.replace(message); } private static List<String> asList(String[] names) { List<String> ret = new ArrayList<String>(); for (int i = 0; i < names.length; i++) { ret.add(trim(names[i])); } return ret; } private static String trim(String name) { return name != null && name.endsWith(".properties") ? name.substring(0, name.lastIndexOf(".properties")) : name; } private static LogCompat log = LogFactoryCompat.getLog(ErrorTranslatorImpl.class); }