001/* 002 * Copyright 2002-2013 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.context.support; 018 019import java.util.Enumeration; 020import java.util.Locale; 021import java.util.ResourceBundle; 022 023import org.springframework.context.MessageSource; 024import org.springframework.context.NoSuchMessageException; 025import org.springframework.lang.Nullable; 026import org.springframework.util.Assert; 027 028/** 029 * Helper class that allows for accessing a Spring 030 * {@link org.springframework.context.MessageSource} as a {@link java.util.ResourceBundle}. 031 * Used for example to expose a Spring MessageSource to JSTL web views. 032 * 033 * @author Juergen Hoeller 034 * @since 27.02.2003 035 * @see org.springframework.context.MessageSource 036 * @see java.util.ResourceBundle 037 * @see org.springframework.web.servlet.support.JstlUtils#exposeLocalizationContext 038 */ 039public class MessageSourceResourceBundle extends ResourceBundle { 040 041 private final MessageSource messageSource; 042 043 private final Locale locale; 044 045 046 /** 047 * Create a new MessageSourceResourceBundle for the given MessageSource and Locale. 048 * @param source the MessageSource to retrieve messages from 049 * @param locale the Locale to retrieve messages for 050 */ 051 public MessageSourceResourceBundle(MessageSource source, Locale locale) { 052 Assert.notNull(source, "MessageSource must not be null"); 053 this.messageSource = source; 054 this.locale = locale; 055 } 056 057 /** 058 * Create a new MessageSourceResourceBundle for the given MessageSource and Locale. 059 * @param source the MessageSource to retrieve messages from 060 * @param locale the Locale to retrieve messages for 061 * @param parent the parent ResourceBundle to delegate to if no local message found 062 */ 063 public MessageSourceResourceBundle(MessageSource source, Locale locale, ResourceBundle parent) { 064 this(source, locale); 065 setParent(parent); 066 } 067 068 069 /** 070 * This implementation resolves the code in the MessageSource. 071 * Returns {@code null} if the message could not be resolved. 072 */ 073 @Override 074 @Nullable 075 protected Object handleGetObject(String key) { 076 try { 077 return this.messageSource.getMessage(key, null, this.locale); 078 } 079 catch (NoSuchMessageException ex) { 080 return null; 081 } 082 } 083 084 /** 085 * This implementation checks whether the target MessageSource can resolve 086 * a message for the given key, translating {@code NoSuchMessageException} 087 * accordingly. In contrast to ResourceBundle's default implementation in 088 * JDK 1.6, this does not rely on the capability to enumerate message keys. 089 */ 090 @Override 091 public boolean containsKey(String key) { 092 try { 093 this.messageSource.getMessage(key, null, this.locale); 094 return true; 095 } 096 catch (NoSuchMessageException ex) { 097 return false; 098 } 099 } 100 101 /** 102 * This implementation throws {@code UnsupportedOperationException}, 103 * as a MessageSource does not allow for enumerating the defined message codes. 104 */ 105 @Override 106 public Enumeration<String> getKeys() { 107 throw new UnsupportedOperationException("MessageSourceResourceBundle does not support enumerating its keys"); 108 } 109 110 /** 111 * This implementation exposes the specified Locale for introspection 112 * through the standard {@code ResourceBundle.getLocale()} method. 113 */ 114 @Override 115 public Locale getLocale() { 116 return this.locale; 117 } 118 119}