/* * Copyright 2002-2005 the original author or authors. * * 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 org.springframework.web.context; import java.util.Date; import java.util.Locale; import org.springframework.context.AbstractApplicationContextTests; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.MessageSource; import org.springframework.context.NoSuchMessageException; import org.springframework.context.support.AbstractMessageSource; import org.springframework.mock.web.MockServletContext; import org.springframework.ui.context.Theme; import org.springframework.ui.context.ThemeSource; import org.springframework.web.context.support.StaticWebApplicationContext; import org.springframework.web.context.support.XmlWebApplicationContext; import org.springframework.web.servlet.theme.AbstractThemeResolver; /** * Creates a WebApplicationContext that points to a "web.xml" file that * contains the entry for what file to use for the applicationContext * (file "org/springframework/web/context/WEB-INF/applicationContext.xml"). * That file then has an entry for a bean called "messageSource". * Whatever the basename property is set to for this bean is what the name of * a properties file in the classpath must be (in our case the name is * "messages" - note no package names). * Thus the catalog filename will be in the root of where the classes are compiled * to and will be called "messages_XX_YY.properties" where "XX" and "YY" are the * language and country codes known by the ResourceBundle class. * * <p>NOTE: The main method of this class is the "createWebApplicationContext(...)" method, * and it was copied from org.springframework.web.context.XmlWebApplicationContextTests. * * @author Rod Johnson * @author Jean-Pierre Pawlak */ public class ResourceBundleMessageSourceTests extends AbstractApplicationContextTests { /** * We use ticket WAR root for file structure. * We don't attempt to read web.xml. */ public static final String WAR_ROOT = "/org/springframework/web/context"; private ConfigurableWebApplicationContext root; private MessageSource themeMsgSource; protected ConfigurableApplicationContext createContext() throws Exception { root = new XmlWebApplicationContext(); MockServletContext sc = new MockServletContext(); root.setServletContext(sc); root.setConfigLocations(new String[] {"/org/springframework/web/context/WEB-INF/applicationContext.xml"}); root.refresh(); ConfigurableWebApplicationContext wac = new XmlWebApplicationContext(); wac.setParent(root); wac.setServletContext(sc); wac.setNamespace("test-servlet"); wac.setConfigLocations(new String[] {"/org/springframework/web/context/WEB-INF/test-servlet.xml"}); wac.refresh(); Theme theme = ((ThemeSource) wac).getTheme(AbstractThemeResolver.ORIGINAL_DEFAULT_THEME_NAME); assertNotNull(theme); assertTrue("Theme name has to be the default theme name", AbstractThemeResolver.ORIGINAL_DEFAULT_THEME_NAME.equals(theme.getName())); themeMsgSource = theme.getMessageSource(); assertNotNull(themeMsgSource); return wac; } public void testCount() { assertTrue("should have 14 beans, not " + this.applicationContext.getBeanDefinitionCount(), this.applicationContext.getBeanDefinitionCount() == 14); } /** * Overridden as we can't trust superclass method. * @see org.springframework.context.AbstractApplicationContextTests#testEvents() */ public void testEvents() throws Exception { // Do nothing } public void testRootMessageSourceWithUseCodeAsDefaultMessage() throws NoSuchMessageException { AbstractMessageSource messageSource = (AbstractMessageSource) root.getBean("messageSource"); messageSource.setUseCodeAsDefaultMessage(true); assertEquals("message1", applicationContext.getMessage("code1", null, Locale.getDefault())); assertEquals("message2", applicationContext.getMessage("code2", null, Locale.getDefault())); try { applicationContext.getMessage("code0", null, Locale.getDefault()); fail("looking for code0 should throw a NoSuchMessageException"); } catch (NoSuchMessageException ex) { // that's how it should be } } /** * @see org.springframework.context.support.AbstractMessageSource for more details. * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/messagesXXX.properties" files. */ public void testGetMessageWithDefaultPassedInAndFoundInMsgCatalog() { assertTrue("valid msg from resourcebundle with default msg passed in returned default msg. Expected msg from catalog.", getApplicationContext().getMessage("message.format.example2", null, "This is a default msg if not found in msg.cat.", Locale.US ) .equals("This is a test message in the message catalog with no args.")); // getApplicationContext().getTheme("theme").getMessageSource().getMessage() } /** * @see org.springframework.context.support.AbstractMessageSource for more details. * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/messagesXXX.properties" files. */ public void testGetMessageWithDefaultPassedInAndNotFoundInMsgCatalog() { assertTrue("bogus msg from resourcebundle with default msg passed in returned default msg", getApplicationContext().getMessage("bogus.message", null, "This is a default msg if not found in msg.cat.", Locale.UK ) .equals("This is a default msg if not found in msg.cat.")); } /** * The underlying implementation uses a hashMap to cache messageFormats * once a message has been asked for. This test is an attempt to * make sure the cache is being used properly. * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/messagesXXX.properties" files. * @see org.springframework.context.support.AbstractMessageSource for more details. */ public void testGetMessageWithMessageAlreadyLookedFor() throws Exception { Object[] arguments = { new Integer(7), new Date(System.currentTimeMillis()), "a disturbance in the Force" }; // The first time searching, we don't care about for this test getApplicationContext().getMessage("message.format.example1", arguments, Locale.US); // Now msg better be as expected assertTrue("2nd search within MsgFormat cache returned expected message for Locale.US", getApplicationContext().getMessage("message.format.example1", arguments, Locale.US ) .indexOf("there was \"a disturbance in the Force\" on planet 7.") != -1); Object[] newArguments = { new Integer(8), new Date(System.currentTimeMillis()), "a disturbance in the Force" }; // Now msg better be as expected even with different args assertTrue("2nd search within MsgFormat cache with different args returned expected message for Locale.US", getApplicationContext().getMessage("message.format.example1", newArguments, Locale.US ) .indexOf("there was \"a disturbance in the Force\" on planet 8.") != -1); } /** * @see org.springframework.context.support.AbstractMessageSource for more details. * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/messagesXXX.properties" files. * Example taken from the javadocs for the java.text.MessageFormat class */ public void testGetMessageWithNoDefaultPassedInAndFoundInMsgCatalog() throws Exception { Object[] arguments = { new Integer(7), new Date(System.currentTimeMillis()), "a disturbance in the Force" }; /* Try with Locale.US Since the msg has a time value in it, we will use String.indexOf(...) to just look for a substring without the time. This is because it is possible that by the time we store a time variable in this method and the time the ResourceBundleMessageSource resolves the msg the minutes of the time might not be the same. */ assertTrue("msg from resourcebundle for Locale.US substituting args for placeholders is as expected", getApplicationContext().getMessage("message.format.example1", arguments, Locale.US ) .indexOf("there was \"a disturbance in the Force\" on planet 7.") != -1); // Try with Locale.UK assertTrue("msg from resourcebundle for Locale.UK substituting args for placeholders is as expected", getApplicationContext().getMessage("message.format.example1", arguments, Locale.UK ) .indexOf("there was \"a disturbance in the Force\" on station number 7.") != -1); // Try with Locale.US - different test msg that requires no args assertTrue("msg from resourcebundle that requires no args for Locale.US is as expected", getApplicationContext().getMessage("message.format.example2", null, Locale.US) .equals("This is a test message in the message catalog with no args.")); } /** * @see org.springframework.context.support.AbstractMessageSource for more details. * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/messagesXXX.properties" files. */ public void testGetMessageWithNoDefaultPassedInAndNotFoundInMsgCatalog() { // Expecting an exception try { getApplicationContext().getMessage("bogus.message", null, Locale.UK); fail("bogus msg from resourcebundle without default msg should have thrown exception"); } catch (NoSuchMessageException tExcept) { assertTrue("bogus msg from resourcebundle without default msg threw expected exception", true); } } public void testGetMultipleBasenamesForMessageSource() throws NoSuchMessageException { assertEquals("message1", getApplicationContext().getMessage("code1", null, Locale.UK)); assertEquals("message2", getApplicationContext().getMessage("code2", null, Locale.UK)); assertEquals("message3", getApplicationContext().getMessage("code3", null, Locale.UK)); } /** * @see org.springframework.context.support.AbstractMessageSource for more details. * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/themeXXX.properties" files. */ public void testGetMessageWithDefaultPassedInAndFoundInThemeCatalog() { // Try with Locale.US String msg = getThemeMessage("theme.example1", null, "This is a default theme msg if not found in theme cat.", Locale.US); assertTrue("valid msg from theme resourcebundle with default msg passed in returned default msg. Expected msg from catalog. Received: " + msg, msg.equals("This is a test message in the theme message catalog.")); // Try with Locale.UK msg = getThemeMessage("theme.example1", null, "This is a default theme msg if not found in theme cat.", Locale.UK); assertTrue("valid msg from theme resourcebundle with default msg passed in returned default msg. Expected msg from catalog.", msg.equals("This is a test message in the theme message catalog with no args.")); } /** * @see org.springframework.context.support.AbstractMessageSource for more details. * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/themeXXX.properties" files. */ public void testGetMessageWithDefaultPassedInAndNotFoundInThemeCatalog() { assertTrue("bogus msg from theme resourcebundle with default msg passed in returned default msg", getThemeMessage("bogus.message", null, "This is a default msg if not found in theme cat.", Locale.UK ) .equals("This is a default msg if not found in theme cat.")); } public void testThemeSourceNesting() throws NoSuchMessageException { String overriddenMsg = getThemeMessage("theme.example2", null, null, Locale.UK); MessageSource ms = ((ThemeSource) root).getTheme(AbstractThemeResolver.ORIGINAL_DEFAULT_THEME_NAME).getMessageSource(); String originalMsg = ms.getMessage("theme.example2", null, Locale.UK); assertTrue("correct overridden msg", "test-message2".equals(overriddenMsg)); assertTrue("correct original msg", "message2".equals(originalMsg)); } public void testThemeSourceNestingWithParentDefault() throws NoSuchMessageException { StaticWebApplicationContext leaf = new StaticWebApplicationContext(); leaf.setParent(getApplicationContext()); leaf.refresh(); assertNotNull("theme still found", leaf.getTheme("theme")); MessageSource ms = leaf.getTheme("theme").getMessageSource(); String msg = ms.getMessage("theme.example2", null, null, Locale.UK); assertEquals("correct overridden msg", "test-message2", msg); } private String getThemeMessage(String code, Object args[], String defaultMessage, Locale locale) { return themeMsgSource.getMessage(code, args, defaultMessage, locale); } }