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.util.Assert; 026 027/** 028 * Helper class that allows for accessing a Spring 029 * {@link org.springframework.context.MessageSource} as a {@link java.util.ResourceBundle}. 030 * Used for example to expose a Spring MessageSource to JSTL web views. 031 * 032 * @author Juergen Hoeller 033 * @since 27.02.2003 034 * @see org.springframework.context.MessageSource 035 * @see java.util.ResourceBundle 036 * @see org.springframework.web.servlet.support.JstlUtils#exposeLocalizationContext 037 */ 038public class MessageSourceResourceBundle extends ResourceBundle { 039 040 private final MessageSource messageSource; 041 042 private final Locale locale; 043 044 045 /** 046 * Create a new MessageSourceResourceBundle for the given MessageSource and Locale. 047 * @param source the MessageSource to retrieve messages from 048 * @param locale the Locale to retrieve messages for 049 */ 050 public MessageSourceResourceBundle(MessageSource source, Locale locale) { 051 Assert.notNull(source, "MessageSource must not be null"); 052 this.messageSource = source; 053 this.locale = locale; 054 } 055 056 /** 057 * Create a new MessageSourceResourceBundle for the given MessageSource and Locale. 058 * @param source the MessageSource to retrieve messages from 059 * @param locale the Locale to retrieve messages for 060 * @param parent the parent ResourceBundle to delegate to if no local message found 061 */ 062 public MessageSourceResourceBundle(MessageSource source, Locale locale, ResourceBundle parent) { 063 this(source, locale); 064 setParent(parent); 065 } 066 067 068 /** 069 * This implementation resolves the code in the MessageSource. 070 * Returns {@code null} if the message could not be resolved. 071 */ 072 @Override 073 protected Object handleGetObject(String key) { 074 try { 075 return this.messageSource.getMessage(key, null, this.locale); 076 } 077 catch (NoSuchMessageException ex) { 078 return null; 079 } 080 } 081 082 /** 083 * This implementation checks whether the target MessageSource can resolve 084 * a message for the given key, translating {@code NoSuchMessageException} 085 * accordingly. In contrast to ResourceBundle's default implementation in 086 * JDK 1.6, this does not rely on the capability to enumerate message keys. 087 */ 088 @Override 089 public boolean containsKey(String key) { 090 try { 091 this.messageSource.getMessage(key, null, this.locale); 092 return true; 093 } 094 catch (NoSuchMessageException ex) { 095 return false; 096 } 097 } 098 099 /** 100 * This implementation throws {@code UnsupportedOperationException}, 101 * as a MessageSource does not allow for enumerating the defined message codes. 102 */ 103 @Override 104 public Enumeration<String> getKeys() { 105 throw new UnsupportedOperationException("MessageSourceResourceBundle does not support enumerating its keys"); 106 } 107 108 /** 109 * This implementation exposes the specified Locale for introspection 110 * through the standard {@code ResourceBundle.getLocale()} method. 111 */ 112 @Override 113 public Locale getLocale() { 114 return this.locale; 115 } 116 117}