dflorey 2004/12/18 07:08:50 Modified: i18n/src/java/org/apache/commons/i18n LocalizedBundle.java MessageManager.java Added: i18n/src/java/org/apache/commons/i18n XMLMessageProvider.java MessageProvider.java ResourceBundleMessageProvider.java Log: Added support for pluggable MessageProviders and added ResourceBundleMessageProvider to enable migration from resource bundle based applications to i18n. Revision Changes Path 1.2 +41 -3 jakarta-commons-sandbox/i18n/src/java/org/apache/commons/i18n/LocalizedBundle.java Index: LocalizedBundle.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/i18n/src/java/org/apache/commons/i18n/LocalizedBundle.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- LocalizedBundle.java 4 Oct 2004 13:41:09 -0000 1.1 +++ LocalizedBundle.java 18 Dec 2004 15:08:49 -0000 1.2 @@ -25,6 +25,13 @@ import java.util.Locale; +/** + * @author Daniel Florey + * + * The LocalizedBundle class represents a bundle of localized messages that + * belong together. + * + */ public class LocalizedBundle { public final static String ID = "id"; public final static String ARGUMENTS = "arguments"; @@ -32,28 +39,59 @@ protected String id; protected Object[] arguments; + /** + * @param messageId The messageId refers the corresponding bundle in the file containing + * the localized messages. The format of the message file depends on the implementation of the + * MessageManager. + */ public LocalizedBundle(String messageId) { this.id = messageId; this.arguments = new Object[0]; } + /** + * @param messageId The messageId refers the corresponding bundle in the file containing + * the localized messages. The format of the message file depends on the implementation of the + * MessageManager. + * @param arguments An array of objects containing argument for the messages. These arguments + * are used to insert dynamic values into the localized messages. + */ public LocalizedBundle(String messageId, Object[] arguments) { this.id = messageId; this.arguments = arguments; } + /** + * @return returns the id of this bundle + */ public String getId() { return id; } + /** + * @return returns the arguments associated with this message bundle + */ public Object[] getArguments() { return arguments; } + /** + * @param key the key of the specific message entry in the message bundle + * @param locale the locale for that this message should be rendered + * @return returns the localized text + * @throws MessageNotFoundException if an entry with the given key can not be found + * in this bundle + */ public String getText(String key, Locale locale) throws MessageNotFoundException { return MessageManager.getText(id, key, arguments, locale); } + /** + * @param key the key of the specific message entry in the message bundle + * @param locale the locale for that this message should be rendered + * @param defaultText the text to be returned if no entry was found for the given key + * @return returns the localized text + */ public String getText(String key, String defaultText, Locale locale) { return MessageManager.getText(id, key, arguments, locale, defaultText); } 1.3 +45 -184 jakarta-commons-sandbox/i18n/src/java/org/apache/commons/i18n/MessageManager.java Index: MessageManager.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/i18n/src/java/org/apache/commons/i18n/MessageManager.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- MessageManager.java 16 Oct 2004 17:41:16 -0000 1.2 +++ MessageManager.java 18 Dec 2004 15:08:49 -0000 1.3 @@ -1,201 +1,62 @@ /* - * $Header$ - * $Revision$ - * $Date$ - * - * ==================================================================== - * - * Copyright 2004 The Apache Software Foundation - * - * 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. - * - */ +* +* ==================================================================== +* +* Copyright 2004 The Apache Software Foundation +* +* 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.apache.commons.i18n; -import java.io.InputStream; -import java.text.MessageFormat; -import java.util.Collection; -import java.util.HashMap; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.Locale; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.commons.i18n.MessageNotFoundException; -import org.apache.commons.xmlio.in.DefaultSimpleImportHandler; -import org.apache.commons.xmlio.in.SimpleImporter; -import org.apache.commons.xmlio.in.SimplePath; -import org.xml.sax.InputSource; -import org.xml.sax.helpers.AttributesImpl; +/** + * @author Daniel Florey + * + */ public class MessageManager { - private static Logger logger = Logger.getLogger(MessageManager.class.getName()); - - private static Map installedMessages = new HashMap(); - private static Map messages = new HashMap(); - - public static String getText(String id, String entry, Object[] arguments, Locale locale, String defaultText) { - Message message = findMessage(id, locale); - try { - return format(message.getEntry(entry), arguments); - } catch ( MessageNotFoundException exception ) { - return defaultText; - } - } - - public static String getText(String id, String entry, Object[] arguments, Locale locale) throws MessageNotFoundException { - Message message = findMessage(id, locale); - return format(message.getEntry(entry), arguments); - } - - public static Map getEntries(String id, Locale locale) throws MessageNotFoundException { - Message message = findMessage(id, locale); - return message.getEntries(); - } - - public static void install(String id, InputStream inputStream) { - logger.log(Level.FINE, "Installing messages '"+id+"'"); - try { - Map applicationMessages = new HashMap(); - SimpleImporter importer = new SimpleImporter(); - importer.setIncludeLeadingCDataIntoStartElementCallback(true); - ConfigurationHandler handler = new ConfigurationHandler(); - importer.addSimpleImportHandler(handler); - importer.parse(new InputSource(inputStream)); - Map parsedMessages = handler.getMessages(); - applicationMessages.putAll(parsedMessages); - messages.putAll(applicationMessages); - installedMessages.put(id, applicationMessages.keySet()); - } catch (Exception exception) { - logger.log(Level.SEVERE, "Error while parsing messages", exception); - } - } - - public static void uninstall(String id) { - logger.log(Level.FINE, "Uninstalling messages '"+id+"'"); - Collection messageKeys = (Collection)installedMessages.get(id); - for ( Iterator i = messageKeys.iterator(); i.hasNext(); ) { - String messageKey = (String)i.next(); - messages.remove(messageKey); - logger.log(Level.FINE, "Removing message with key '"+messageKey+"'"); - } - installedMessages.remove(id); - } + private static List messageProviders = new ArrayList(); - public static void update(String id, InputStream inputStream) { - uninstall(id); - install(id, inputStream); + static { + messageProviders.add(new XMLMessageProvider()); + messageProviders.add(new ResourceBundleMessageProvider()); } - - private static String format(String formatString, Object[] arguments) { - if (formatString == null) return null; - return MessageFormat.format(formatString, arguments); - } - - private static Message findMessage(String id, Locale locale) { - Message message = lookupMessage(id, locale); - if (message == null) { - message = lookupMessage(id, Locale.getDefault()); - } - if (message == null ) throw new MessageNotFoundException("Message with id "+id+" not found"); - return message; - } - - private static Message lookupMessage(String id, Locale locale) { - StringBuffer keyBuffer = new StringBuffer(64); - keyBuffer.append(id); - if (locale.getLanguage() != null) keyBuffer.append("_" + locale.getLanguage()); - if (locale.getCountry() != null) keyBuffer.append("_" + locale.getCountry()); - if (locale.getVariant() != null) keyBuffer.append("_" + locale.getVariant()); - String key = keyBuffer.toString(); - if (messages.containsKey(key)) return (Message)messages.get(key); - while (key.lastIndexOf('_') > 0) { - key = key.substring(0, key.lastIndexOf('_')); - if (messages.containsKey(key)) return (Message)messages.get(key); - } - return null; + + public static void addMessageProvider(MessageProvider messageProvider) { + messageProviders.add(messageProvider); } - - static class ConfigurationHandler extends DefaultSimpleImportHandler { - private Map messages = new HashMap(); - private String id; - private Message message; - - public void startElement(SimplePath path, String name, AttributesImpl attributes, String leadingCDdata) { - if (path.matches("message")) { - id = attributes.getValue("id"); - } else if (path.matches("message/locale")) { - message = new Message(id); - message.setLanguage(attributes.getValue("language")); - message.setCountry(attributes.getValue("country")); - message.setVariant(attributes.getValue("variant")); - } else if (path.matches("message/locale/entry")) { - String key = attributes.getValue("key"); - message.addEntry(key, leadingCDdata); - } - } - - public void endElement(SimplePath path, String name) { - if (path.matches("message/locale")) { - messages.put(message.getKey(), message); + + public static String getText(String id, String entry, Object[] arguments, Locale locale) throws MessageNotFoundException { + MessageNotFoundException exception = null; + for ( Iterator i = messageProviders.iterator(); i.hasNext(); ) { + try { + return ((MessageProvider)i.next()).getText(id, entry, arguments, locale); + } catch ( MessageNotFoundException e ) { + exception = e; } } - - Map getMessages() { - return messages; - } + throw exception; } - static class Message { - private String id, language, country, variant; - private Map entries = new HashMap(); - - public Message(String id) { - this.id = id; - } - - public void addEntry(String key, String value) { - entries.put(key, value); - } - - public String getEntry(String key) { - return (String)entries.get(key); - } - - public Map getEntries() { - return entries; - } - - public void setLanguage(String language) { - this.language = language; - } - - public void setCountry(String country) { - this.country = country; - } - - public void setVariant(String variant) { - this.variant = variant; - } - - public String getKey() { - StringBuffer key = new StringBuffer(64); - key.append(id); - if (language != null) key.append("_" + language); - if (country != null) key.append("_" + country); - if (variant != null) key.append("_" + variant); - return key.toString(); + public static String getText(String id, String entry, Object[] arguments, Locale locale, String defaultText) { + try { + return getText(id, entry, arguments, locale); + } catch ( MessageNotFoundException e ) { + return defaultText; } } } 1.1 jakarta-commons-sandbox/i18n/src/java/org/apache/commons/i18n/XMLMessageProvider.java Index: XMLMessageProvider.java =================================================================== /* * * ==================================================================== * * Copyright 2004 The Apache Software Foundation * * 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.apache.commons.i18n; import java.io.InputStream; import java.text.MessageFormat; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.xmlio.in.DefaultSimpleImportHandler; import org.apache.commons.xmlio.in.SimpleImporter; import org.apache.commons.xmlio.in.SimplePath; import org.xml.sax.InputSource; import org.xml.sax.helpers.AttributesImpl; /** * @author Daniel Florey * */ public class XMLMessageProvider implements MessageProvider { private static Logger logger = Logger.getLogger(XMLMessageProvider.class.getName()); private static Map installedMessages = new HashMap(); private static Map messages = new HashMap(); public String getText(String id, String entry, Object[] arguments, Locale locale) throws MessageNotFoundException { Message message = findMessage(id, locale); return MessageFormat.format(message.getEntry(entry), arguments); } public Map getEntries(String id, Locale locale) throws MessageNotFoundException { Message message = findMessage(id, locale); return message.getEntries(); } public static void install(String id, InputStream inputStream) { logger.log(Level.FINE, "Installing messages '"+id+"'"); try { Map applicationMessages = new HashMap(); SimpleImporter importer = new SimpleImporter(); importer.setIncludeLeadingCDataIntoStartElementCallback(true); ConfigurationHandler handler = new ConfigurationHandler(); importer.addSimpleImportHandler(handler); importer.parse(new InputSource(inputStream)); Map parsedMessages = handler.getMessages(); applicationMessages.putAll(parsedMessages); messages.putAll(applicationMessages); installedMessages.put(id, applicationMessages.keySet()); } catch (Exception exception) { logger.log(Level.SEVERE, "Error while parsing messages", exception); } } public static void uninstall(String id) { logger.log(Level.FINE, "Uninstalling messages '"+id+"'"); Collection messageKeys = (Collection)installedMessages.get(id); for ( Iterator i = messageKeys.iterator(); i.hasNext(); ) { String messageKey = (String)i.next(); messages.remove(messageKey); logger.log(Level.FINE, "Removing message with key '"+messageKey+"'"); } installedMessages.remove(id); } public static void update(String id, InputStream inputStream) { uninstall(id); install(id, inputStream); } private static Message findMessage(String id, Locale locale) { Message message = lookupMessage(id, locale); if (message == null) { message = lookupMessage(id, Locale.getDefault()); } if (message == null ) throw new MessageNotFoundException("Message with id "+id+" not found"); return message; } private static Message lookupMessage(String id, Locale locale) { StringBuffer keyBuffer = new StringBuffer(64); keyBuffer.append(id); if (locale.getLanguage() != null) keyBuffer.append("_" + locale.getLanguage()); if (locale.getCountry() != null) keyBuffer.append("_" + locale.getCountry()); if (locale.getVariant() != null) keyBuffer.append("_" + locale.getVariant()); String key = keyBuffer.toString(); if (messages.containsKey(key)) return (Message)messages.get(key); while (key.lastIndexOf('_') > 0) { key = key.substring(0, key.lastIndexOf('_')); if (messages.containsKey(key)) return (Message)messages.get(key); } return null; } static class ConfigurationHandler extends DefaultSimpleImportHandler { private Map messages = new HashMap(); private String id; private Message message; public void startElement(SimplePath path, String name, AttributesImpl attributes, String leadingCDdata) { if (path.matches("message")) { id = attributes.getValue("id"); } else if (path.matches("message/locale")) { message = new Message(id); message.setLanguage(attributes.getValue("language")); message.setCountry(attributes.getValue("country")); message.setVariant(attributes.getValue("variant")); } else if (path.matches("message/locale/entry")) { String key = attributes.getValue("key"); message.addEntry(key, leadingCDdata); } } public void endElement(SimplePath path, String name) { if (path.matches("message/locale")) { messages.put(message.getKey(), message); } } Map getMessages() { return messages; } } static class Message { private String id, language, country, variant; private Map entries = new HashMap(); public Message(String id) { this.id = id; } public void addEntry(String key, String value) { entries.put(key, value); } public String getEntry(String key) { return (String)entries.get(key); } public Map getEntries() { return entries; } public void setLanguage(String language) { this.language = language; } public void setCountry(String country) { this.country = country; } public void setVariant(String variant) { this.variant = variant; } public String getKey() { StringBuffer key = new StringBuffer(64); key.append(id); if (language != null) key.append("_" + language); if (country != null) key.append("_" + country); if (variant != null) key.append("_" + variant); return key.toString(); } } } 1.1 jakarta-commons-sandbox/i18n/src/java/org/apache/commons/i18n/MessageProvider.java Index: MessageProvider.java =================================================================== /* * $Header: /home/cvs/jakarta-commons-sandbox/i18n/src/java/org/apache/commons/i18n/MessageProvider.java,v 1.1 2004/12/18 15:08:49 dflorey Exp $ * $Revision: 1.1 $ * $Date: 2004/12/18 15:08:49 $ * * ==================================================================== * * Copyright 2004 The Apache Software Foundation * * 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.apache.commons.i18n; import java.util.Locale; public interface MessageProvider { public String getText(String id, String entry, Object[] arguments, Locale locale) throws MessageNotFoundException; } 1.1 jakarta-commons-sandbox/i18n/src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java Index: ResourceBundleMessageProvider.java =================================================================== /* * * ==================================================================== * * Copyright 2004 The Apache Software Foundation * * 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.apache.commons.i18n; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.logging.Level; import java.util.logging.Logger; /** * @author Daniel Florey * */ public class ResourceBundleMessageProvider implements MessageProvider { private static Logger logger = Logger.getLogger(ResourceBundleMessageProvider.class.getName()); private static List installedResourceBundles = new ArrayList(); public String getText(String id, String entry, Object[] arguments, Locale locale) throws MessageNotFoundException { String text = null; for ( Iterator i = installedResourceBundles.iterator(); i.hasNext(); ) { String baseName = (String)i.next(); try { ResourceBundle resourceBundle = ResourceBundle.getBundle(baseName, locale); try { text = resourceBundle.getString(id+"."+entry); return MessageFormat.format(text, arguments); } catch ( ClassCastException e ) { // ignore all entries that are not of type String } catch ( MissingResourceException e ) { // skip resource bundle if it is not containing the desired entry } } catch ( MissingResourceException e ) { logger.log(Level.WARNING, "Could not find resource bundle with base name '"+baseName+"', uninstalling it..."); uninstall(baseName); } } throw new MessageNotFoundException("Message with id "+id+" not found"); } public static void install(String baseName) { logger.log(Level.FINE, "Installing bundle with base name '"+baseName+"'"); installedResourceBundles.add(baseName); } public static void uninstall(String baseName) { logger.log(Level.FINE, "Uninstalling bundle with base name '"+baseName+"'"); installedResourceBundles.remove(baseName); } public static void update(String baseName) { uninstall(baseName); install(baseName); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]