Java tutorial
/* * Copyright (c) 2007 NTT DATA Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jp.terasoluna.fw.message; import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.support.AbstractMessageSource; /** * DAO??????? * ????????? * * <p> * ??DB???DB?? * ??????? * ???????????? * ???? * </p> * <strong></strong><br> * ??????MessageSource * ??????????DB??? * DAO???????<br> * <br> * <strong></strong><br> * Bean????<br> * DAO???DBMessageResourceDAO???<br> * * <pre> * <bean id = "messageSource" * class = "jp.terasoluna.fw.message.DataSourceMessageSource"> * <property name = "DBMessageResourceDAO"> * <ref bean = "dBMessageResourceDAO"></ref> * </property> * </bean> * </pre> * * <strong></strong><br> * <bean>??id?"messageSource" ????MessageSource * ?????<br> * <bean>?<property>???DAO??<br> * <br> * * <br> * ?<br> * ??????????? * ???????????????????? * ??<br> * ?????VM???? * <br> * ?????setDefaultLocale? * ???????? <br> * <br> * <strong></strong><br> * Bean????<br> * ja?)???<br> * <br> * * <pre> * <bean id = "messageSource" * class = "jp.terasoluna.fw.message.DataSourceMessageSource"> * <property name = "DBMessageResourceDAO"> * <ref bean = "dBMessageResourceDAO"></ref> * </property> * <property name = "defaultLocale"> * <value>ja</value> * </property> * </bean> * </pre> * * <strong></strong><br> * <bean>?<properities>??name?defaultLocale?? * value?????? * * @see jp.terasoluna.fw.message.DBMessage * @see jp.terasoluna.fw.message.DBMessageQuery * @see jp.terasoluna.fw.message.DBMessageResourceDAO * @see jp.terasoluna.fw.message.DBMessageResourceDAOImpl * * */ public class DataSourceMessageSource extends AbstractMessageSource implements InitializingBean { /** * ?????? * <br> * Map <Code, Map <Locale, MessageFormat>> */ protected final Map<String, Map<Locale, MessageFormat>> cachedMessageFormats = new HashMap<String, Map<Locale, MessageFormat>>(); /** * ?????? * <br/> Map <Locale, Properties> */ protected Map<Locale, Properties> cachedMergedProperties = new HashMap<Locale, Properties>(); /** * */ private static Log log = LogFactory.getLog(DataSourceMessageSource.class); /** * ???????? * ????????? ???? * ????JVM??????? */ protected Locale defaultLocale = new Locale(Locale.getDefault().getLanguage()); /** * ??DAO */ protected DBMessageResourceDAO dbMessageResourceDAO = null; /** * ???????VM? * ??VM???????????? * * @see #getMessageInternal * @see java.util.Locale#getDefault * * @param defaultLocale * ? */ public void setDefaultLocale(Locale defaultLocale) { this.defaultLocale = defaultLocale; } /** * DBMessageResourceDAO? * * @param dbMessageResourceDAO * ????DAO */ public synchronized void setDbMessageResourceDAO(DBMessageResourceDAO dbMessageResourceDAO) { this.dbMessageResourceDAO = dbMessageResourceDAO; } /** * Web??<br> * ??? * ????????? * * @see #cachedMergedProperties * */ @Override public void afterPropertiesSet() { if (log.isDebugEnabled()) { log.debug("afterPropertiesSet"); } readMessagesFromDataSource(); } /** * ? * ????????DB?? * ?DB?????????????? * ????? */ public synchronized void reloadDataSourceMessage() { readMessagesFromDataSource(); } /** * DAO?????? * ??????????? * ?????????<br> * ?????? * ???? */ protected synchronized void readMessagesFromDataSource() { if (log.isDebugEnabled()) { log.debug("readMessageFromDataSource"); } cachedMergedProperties.clear(); cachedMessageFormats.clear(); // DAO??? List<DBMessage> messages = dbMessageResourceDAO.findDBMessages(); //??null?????? //?? for (DBMessage message : messages) { if (message.code != null && message.message != null) { mapMessage(message); } } if (log.isDebugEnabled()) { log.debug("get MessageResource from DAO."); } } /** * ????? * ???????? * * @param message * ???DBMessage */ protected void mapMessage(DBMessage message) { // ???? // ?? Locale locale = createLocale(message); // ?????? Properties messages = getMessages(locale); // ???????? messages.setProperty(message.getCode(), message.getMessage()); if (log.isDebugEnabled()) { log.debug("add Message[" + message.getMessage() + "] (code[" + message.getCode() + "], locale[" + locale + "])"); } } /** * Locale??<br> * ????Locale?? * ???????????? * ???Locale?? * * @param message * * @return * ??????Locale * * @throws IllegalArgumentException * ????? * ???????????? * ?? */ protected Locale createLocale(DBMessage message) { if (message.getLanguage() == null) { if (defaultLocale != null) { return defaultLocale; } if (log.isErrorEnabled()) { log.error("Can't resolve Locale.Define Locale" + " in MessageSource or Defaultlocale."); } throw new IllegalArgumentException( "Can't resolve Locale." + "Define Locale in MessageSource or Defaultlocale."); } if (message.getCountry() == null) { return new Locale(message.getLanguage()); } if (message.getVariant() == null) { return new Locale(message.getLanguage(), message.getCountry()); } return new Locale(message.getLanguage(), message.getCountry(), message.getVariant()); } /** * ?????? ??? * ???????????null???? * * @param locale * ? * * @return ????? ? * ??????? */ protected Properties getMessages(Locale locale) { // ??????? Properties messages = cachedMergedProperties.get(locale); // ????????????? // ?????cachedMergedProperties??? if (messages == null) { messages = new Properties(); cachedMergedProperties.put(locale, messages); } return messages; } /** * ????????? * ????? * AbstractMessageSource????? * * @param code * * @param locale * ? * * @return */ @Override protected synchronized String resolveCodeWithoutArguments(String code, Locale locale) { String msg = internalResolveCodeWithoutArguments(code, locale); if (msg == null) { if (log.isDebugEnabled()) { log.debug("could not resolve [" + code + "] for locale [" + locale + "]"); } } return msg; } /** * ??? ????? * ????????????? * ??? * ???????????? * ??? * * @param code * * @param locale * ? * * @return */ protected String internalResolveCodeWithoutArguments(String code, Locale locale) { // ????msg??? String msg = getMessages(locale).getProperty(code); // ????????? if (msg != null) { return msg; } // ????????????? // ??? // ??? List<Locale> locales = getAlternativeLocales(locale); // ??????????? // ???? for (int i = 0; i < locales.size(); i++) { msg = getMessages(locales.get(i)).getProperty(code); if (msg != null) { return msg; } } // ??????????null?? return null; } /** * ???? ?? * ???????? * locale?????? * locale?????? * ??????? * ????? * ???? * * @param locale * * * @return ??? */ protected List<Locale> getAlternativeLocales(Locale locale) { List<Locale> locales = new ArrayList<Locale>(); // ????? if (locale.getVariant().length() > 0) { // Locale(language,country,"") locales.add(new Locale(locale.getLanguage(), locale.getCountry())); } // ???? if (locale.getCountry().length() > 0) { // Locale(language,"","") locales.add(new Locale(locale.getLanguage())); } // ????? if (defaultLocale != null && !locale.equals(defaultLocale)) { if (defaultLocale.getVariant().length() > 0) { // Locale(language,country,"") locales.add(defaultLocale); } if (defaultLocale.getCountry().length() > 0) { // Locale(language,country,"") locales.add(new Locale(defaultLocale.getLanguage(), defaultLocale.getCountry())); } // ???? if (defaultLocale.getLanguage().length() > 0) { // Locale(language,"","") locales.add(new Locale(defaultLocale.getLanguage())); } } return locales; } /** * ??????? * ???? * ???AbstractMessageSource? * ???? * * @param code * * @param locale * ? * * @return */ @Override protected synchronized MessageFormat resolveCode(String code, Locale locale) { // ????messageFormat? // ?? MessageFormat messageFormat = getMessageFormat(code, locale); // ????????? if (messageFormat != null) { if (log.isDebugEnabled()) { log.debug("resolved [" + code + "] for locale [" + locale + "] => [" + messageFormat + "]"); } return messageFormat; } // ????????????? // ??? // ??? List<Locale> locales = getAlternativeLocales(locale); // ????????? // ?????? for (int i = 0; i < locales.size(); i++) { messageFormat = getMessageFormat(code, locales.get(i)); if (messageFormat != null) { if (log.isDebugEnabled()) { log.debug("resolved [" + code + "] for locale [" + locale + "] => [" + messageFormat + "]"); } return messageFormat; } } if (messageFormat == null) { if (log.isDebugEnabled()) { log.debug("could not resolve [" + code + "] for locale [" + locale + "]"); } } // ?????????null?? return null; } /** * ??????? * ? * * @param code * * @param locale * ? * * @return ?? */ protected MessageFormat getMessageFormat(String code, Locale locale) { // ????? Map<Locale, MessageFormat> localeMap = this.cachedMessageFormats.get(code); // ??????? // ???? if (localeMap != null) { MessageFormat result = localeMap.get(locale); if (result != null) { return result; } } String msg = getMessages(locale).getProperty(code); // ??? if (msg != null) { // ??????????? // ?? if (localeMap == null) { localeMap = new HashMap<Locale, MessageFormat>(); this.cachedMessageFormats.put(code, localeMap); } // ??? MessageFormat result = createMessageFormat(msg, locale); localeMap.put(locale, result); return result; } // ?????????null?? return null; } }