You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by df...@apache.org on 2005/07/24 14:53:33 UTC
svn commit: r224613 - in /jakarta/commons/sandbox/i18n/trunk: ./
src/examples/ src/examples/org/apache/i18n/examples/
src/java/org/apache/commons/i18n/ src/test/org/apache/commons/i18n/ xdocs/
Author: dflorey
Date: Sun Jul 24 05:53:05 2005
New Revision: 224613
URL: http://svn.apache.org/viewcvs?rev=224613&view=rev
Log:
Apply patch from Mattias Jiderhamn to resolve remaining issues
Added:
jakarta/commons/sandbox/i18n/trunk/src/examples/i18n-jdbc.properties
jakarta/commons/sandbox/i18n/trunk/src/examples/org/apache/i18n/examples/QualifiedJdbcExample.java
jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/I18nUtils.java
jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/JdbcMessageProvider.java
jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/I18nUtilsTest.java
jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/JdbcMessageProviderTest.java
Modified:
jakarta/commons/sandbox/i18n/trunk/project.properties
jakarta/commons/sandbox/i18n/trunk/project.xml
jakarta/commons/sandbox/i18n/trunk/src/examples/org/apache/i18n/examples/LocalizedExceptionExample.java
jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedError.java
jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedException.java
jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedRuntimeException.java
jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/MessageManager.java
jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/MessageProvider.java
jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java
jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/XMLMessageProvider.java
jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/MessageManagerTest.java
jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/MockProviderTestBase.java
jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java
jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/XMLMessageProviderTest.java
jakarta/commons/sandbox/i18n/trunk/xdocs/examples.xml
Modified: jakarta/commons/sandbox/i18n/trunk/project.properties
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/project.properties?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/project.properties (original)
+++ jakarta/commons/sandbox/i18n/trunk/project.properties Sun Jul 24 05:53:05 2005
@@ -28,3 +28,8 @@
# M A V E N J A R O V E R R I D E
# ------------------------------------------------------------------------
maven.jar.override = on
+
+
+# Set target to Java 1.4, since JCoverage does not work with Java 1.5
+maven.compile.source=1.4
+maven.compile.target=1.4
\ No newline at end of file
Modified: jakarta/commons/sandbox/i18n/trunk/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/project.xml?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/project.xml (original)
+++ jakarta/commons/sandbox/i18n/trunk/project.xml Sun Jul 24 05:53:05 2005
@@ -74,6 +74,23 @@
</contributors>
<dependencies>
+ <!-- Please note, these depenencies are needed for unit tests only! -->
+ <dependency>
+ <id>hsqldb</id>
+ <version>1.7.3.3</version>
+ </dependency>
+ <dependency>
+ <id>commons-dbcp</id>
+ <version>1.2.1</version>
+ </dependency>
+ <dependency>
+ <id>commons-pool</id>
+ <version>1.2</version>
+ </dependency>
+ <dependency>
+ <id>commons-collections</id>
+ <version>2.1.1</version>
+ </dependency>
</dependencies>
<build>
Added: jakarta/commons/sandbox/i18n/trunk/src/examples/i18n-jdbc.properties
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/examples/i18n-jdbc.properties?rev=224613&view=auto
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/examples/i18n-jdbc.properties (added)
+++ jakarta/commons/sandbox/i18n/trunk/src/examples/i18n-jdbc.properties Sun Jul 24 05:53:05 2005
@@ -0,0 +1,7 @@
+jdbc.connect.driver=org.hsqldb.jdbcDriver
+jdbc.connect.url=jdbc:hsqldb:.
+jdbc.connect.login=sa
+jdbc.connect.password=
+jdbc.sql.table=messages
+jdbc.sql.locale.column=language
+jdbc.sql.key.column=id
\ No newline at end of file
Modified: jakarta/commons/sandbox/i18n/trunk/src/examples/org/apache/i18n/examples/LocalizedExceptionExample.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/examples/org/apache/i18n/examples/LocalizedExceptionExample.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/examples/org/apache/i18n/examples/LocalizedExceptionExample.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/examples/org/apache/i18n/examples/LocalizedExceptionExample.java Sun Jul 24 05:53:05 2005
@@ -25,6 +25,7 @@
import org.apache.commons.i18n.LocalizedException;
import org.apache.commons.i18n.XMLMessageProvider;
+import org.apache.commons.i18n.MessageManager;
import org.apache.commons.i18n.bundles.ErrorBundle;
/**
@@ -37,9 +38,9 @@
public static void main(String[] args) {
// Install the file providing the required messages for this example
- XMLMessageProvider.install("org.apache.commons-i18n.examples", Thread
- .currentThread().getContextClassLoader().getResourceAsStream(
- "exampleMessages.xml"));
+ MessageManager.addMessageProvider("org.apache.commons-i18n.examples",
+ new XMLMessageProvider(Thread.currentThread().getContextClassLoader().getResourceAsStream(
+ "exampleMessages.xml")));
// Simulate the locale of the current user in a multi-user environment
// such as a web application
Added: jakarta/commons/sandbox/i18n/trunk/src/examples/org/apache/i18n/examples/QualifiedJdbcExample.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/examples/org/apache/i18n/examples/QualifiedJdbcExample.java?rev=224613&view=auto
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/examples/org/apache/i18n/examples/QualifiedJdbcExample.java (added)
+++ jakarta/commons/sandbox/i18n/trunk/src/examples/org/apache/i18n/examples/QualifiedJdbcExample.java Sun Jul 24 05:53:05 2005
@@ -0,0 +1,155 @@
+/*
+ *
+ * ====================================================================
+ *
+ * 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.i18n.examples;
+
+import org.apache.commons.i18n.MessageManager;
+import org.apache.commons.i18n.JdbcMessageProvider;
+import org.apache.commons.i18n.LocalizedRuntimeException;
+import org.apache.commons.i18n.bundles.TextBundle;
+import org.apache.commons.i18n.bundles.ErrorBundle;
+
+import java.sql.Connection;
+import java.sql.Statement;
+import java.sql.SQLException;
+import java.sql.DriverManager;
+import java.util.Locale;
+import java.util.Properties;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * This example shows
+ * a) how to use qualified message providers, instead of searching through all available providers.
+ * b) how to use i18n for messages stored in databases. For the sake of the example, we will create
+ * an in memory database holding the i18n messages using HSQLDB.
+ * @author Mattias Jiderhamn
+ * @see <a href="http://hsqldb.org/">HSQLDB</a>
+ */
+public class QualifiedJdbcExample {
+ public static void main(String[] args) throws Exception {
+ /////////////////////////////////////////////////////
+ // Prepare example
+ /////////////////////////////////////////////////////
+
+ // Set up in-memory data for the sake of the example
+ prepareTables();
+
+ /////////////////////////////////////////////////////
+ // Example of initialization
+ /////////////////////////////////////////////////////
+
+ // We can initialize JDBC message provider using a properties file
+ Properties props = new Properties();
+ props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("i18n-jdbc.properties"));
+ MessageManager.addMessageProvider("messages", new JdbcMessageProvider(props));
+
+ // We can also initialize JDBC message provider by providing connection (or DataSource)
+ Connection conn = getNewConnection();
+ MessageManager.addMessageProvider("errors", new JdbcMessageProvider(conn, "errors", "id", "language"));
+ conn.close();
+
+ /////////////////////////////////////////////////////
+ // Example of usage
+ /////////////////////////////////////////////////////
+
+ // Simulate the locale of the current user in a multi-user environment
+ // such as a web application
+ Locale currentUsersLocale = new Locale("sv"); // Assume Swedish
+
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+
+ // Get i18n text qualifying the message source (i.e. the MessageProvider) to use; messages
+ TextBundle textBundle = new TextBundle("messages", "enterFirstName");
+ System.out.println(textBundle.getText(currentUsersLocale) + ":");
+ String firstName = reader.readLine();
+
+ textBundle = new TextBundle("messages", "enterLastName");
+ System.out.println(textBundle.getText(currentUsersLocale) + ":");
+ String lastName = reader.readLine();
+
+ validateNames(firstName, lastName);
+ }
+ catch(LocalizedRuntimeException lrex) {
+ // Retrieve the detailed localized error message
+ ErrorBundle errorMessage = lrex.getErrorMessage();
+
+ // Print summary and details using the current users locale
+ System.out.println("-- " + errorMessage.getSummary(currentUsersLocale) + " --");
+ System.out.println(errorMessage.getDetails(currentUsersLocale));
+ }
+ }
+
+ private static void validateNames(String firstname, String lastname) {
+ if(firstname.equals(lastname))
+ throw new LocalizedRuntimeException(new ErrorBundle("errors", "identicalNames"));
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Utility methods for the example
+ ///////////////////////////////////////////////////////////////////////
+
+ /**
+ * Create connection to in-memory HSQLDB database
+ * @return
+ * @throws ClassNotFoundException
+ * @throws SQLException
+ */
+ private static Connection getNewConnection() throws ClassNotFoundException, SQLException {
+ Class.forName("org.hsqldb.jdbcDriver"); // Load HSQLDB database driver
+ return DriverManager.getConnection("jdbc:hsqldb:.", "sa", ""); // Connect to in-memory database
+ }
+
+ /**
+ * Create tables and insert messages
+ */
+ private static void prepareTables() throws ClassNotFoundException, SQLException {
+ Connection conn = getNewConnection();
+ Statement stmt = conn.createStatement();
+ stmt.execute(
+ "CREATE TABLE messages ( " +
+ " 'id' VARCHAR(30), " +
+ " 'language' VARCHAR(2), " +
+ " 'text' VARCHAR(100)" +
+ ")");
+ stmt.execute("INSERT INTO messages VALUES ('enterFirstName', 'en', 'Please enter your first name')");
+ stmt.execute("INSERT INTO messages VALUES ('enterLastName', 'en', 'Please enter your last name')");
+ stmt.execute("INSERT INTO messages VALUES ('enterFirstName', 'sv', 'Vänligen ange ditt förnamn')");
+ stmt.execute("INSERT INTO messages VALUES ('enterLastName', 'sv', 'Vänligen ange ditt efternamn')");
+ stmt.execute(
+ "CREATE TABLE errors ( " +
+ " 'id' VARCHAR(30), " +
+ " 'language' VARCHAR(2), " +
+ " 'summary' VARCHAR(100), " +
+ " 'details' VARCHAR(100) " +
+ ")");
+ stmt.execute("INSERT INTO errors VALUES (" +
+ " 'identicalNames', 'en', " +
+ " 'Error! Identical names.', 'You entered the same name as both first name and last name'" +
+ ")");
+ stmt.execute("INSERT INTO errors VALUES (" +
+ " 'identicalNames', 'sv', " +
+ " 'Fel! Identiska namn.', 'Du angav samma namn som både förnamn och efternamn'" +
+ ")");
+ stmt.close();
+ conn.close();
+ }
+}
\ No newline at end of file
Added: jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/I18nUtils.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/I18nUtils.java?rev=224613&view=auto
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/I18nUtils.java (added)
+++ jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/I18nUtils.java Sun Jul 24 05:53:05 2005
@@ -0,0 +1,51 @@
+/*
+*
+* ====================================================================
+*
+* 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;
+import java.util.ResourceBundle;
+
+/**
+ * This class holds utility methods useful when working with i18n.
+ * @author Mattias Jiderhamn
+ */
+public class I18nUtils {
+
+ static final String INTERNAL_MESSAGE_NOT_FOUND = "Internal I18n error: Message not found";
+ static final String MESSAGE_NOT_FOUND = "messageNotFound";
+ static final String NO_MESSAGE_ENTRIES_FOUND = "noMessageEntriesFound";
+ static final String MESSAGE_ENTRY_NOT_FOUND = "messageEntryNotFound";
+ static final String RESOURCE_BUNDLE_NOT_FOUND = "resourceBundleNotFound";
+ public static final String MESSAGE_PARSING_ERROR = "messageParsingError";
+
+ public static final ResourceBundle INTERNAL_MESSAGES = ResourceBundle.getBundle("i18n-messages", Locale.getDefault());
+
+ private I18nUtils() {
+ }
+
+ public static Locale getParentLocale (Locale locale) {
+ if(locale.getVariant().length() != 0)
+ return new Locale(locale.getLanguage(), locale.getCountry());
+ else if(locale.getCountry().length() != 0)
+ return new Locale(locale.getLanguage());
+ else // Locale with only language have no parent
+ return null;
+ }
+}
\ No newline at end of file
Added: jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/JdbcMessageProvider.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/JdbcMessageProvider.java?rev=224613&view=auto
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/JdbcMessageProvider.java (added)
+++ jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/JdbcMessageProvider.java Sun Jul 24 05:53:05 2005
@@ -0,0 +1,183 @@
+package org.apache.commons.i18n;
+
+import javax.sql.DataSource;
+import java.util.*;
+import java.sql.*;
+
+/**
+ * @author Mattias Jiderhamn
+ */
+public class JdbcMessageProvider implements MessageProvider {
+ /**
+ * This Map has locale or language as key, and a Map with the different
+ * messages as value.
+ */
+ private final Map locales = new HashMap();
+
+ private String idColumn;
+
+ private String languageColumn;
+
+ public JdbcMessageProvider(Connection conn, String table, String idColumn, String languageColumn)
+ throws SQLException {
+ this.idColumn = idColumn;
+ this.languageColumn = languageColumn;
+ init(conn, table);
+ }
+
+ public JdbcMessageProvider(DataSource ds, String table, String idColumn, String languageColumn)
+ throws SQLException {
+ this.idColumn = idColumn;
+ this.languageColumn = languageColumn;
+ Connection conn = null;
+ try {
+ conn = ds.getConnection();
+ init(conn, table);
+ }
+ finally {
+ if(conn != null)
+ conn.close();
+ }
+ }
+
+ /**
+ * Create JDBC MessageProvider from properties in a Map, such
+ * as a java.util.Properties object. The following are the properties in use, which
+ * are the same as for JDBCResources of Jakarta Commons Resources
+ * jdbc.connect.driver = org.gjt.mm.mysql.Driver
+ * jdbc.connect.url = jdbc:mysql://localhost/resources
+ * jdbc.connect.login = resourcesTest
+ * jdbc.connect.password = resourcesTest
+ *
+ * jdbc.sql.table = resources
+ * jdbc.sql.locale.column = locale
+ * jdbc.sql.key.column = msgKey
+ */
+ public JdbcMessageProvider(Map properties) throws ClassNotFoundException, SQLException {
+ String driver = (String)properties.get("jdbc.connect.driver");
+ String url = (String)properties.get("jdbc.connect.url");
+ String user = (String)properties.get("jdbc.connect.login");
+ String pass = (String)properties.get("jdbc.connect.password");
+
+ String table = (String)properties.get("jdbc.sql.table");
+ this.idColumn = (String)properties.get("jdbc.sql.key.column");
+ this.languageColumn = (String)properties.get("jdbc.sql.locale.column");
+
+ Class.forName(driver);
+ Connection conn = null;
+ try {
+ conn = DriverManager.getConnection(url, user, pass);
+ init(conn, table);
+ }
+ finally {
+ if(conn != null)
+ conn.close();
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Methods for initialization
+ ///////////////////////////////////////////////////////////////////////
+
+ private void init(Connection conn, String table) throws SQLException {
+ Statement stmt = null;
+ ResultSet rs = null;
+ try {
+ stmt = conn.createStatement();
+ rs = stmt.executeQuery("SELECT * FROM " + table);
+ String[] valueColumns = getValueColumns(rs);
+ while(rs.next()) {
+ String id = rs.getString(idColumn);
+ Locale locale = getLocale(rs);
+ Map entries = new HashMap();
+ for(int i = 0; i < valueColumns.length; i++) {
+ entries.put(valueColumns[i], rs.getString(valueColumns[i]));
+ }
+ Map localeMap = (Map)locales.get(locale);
+ if(localeMap == null) { // If first record for this Locale
+ localeMap = new HashMap();
+ locales.put(locale, localeMap);
+ }
+ localeMap.put(id, entries);
+ }
+ }
+ finally {
+ if(stmt != null)
+ stmt.close();
+ if(rs != null)
+ rs.close();
+ }
+ }
+
+ /**
+ * Get a String of all the column names, except the ID column and the
+ * language column.
+ * @param rs A <code>ResultSet</code> ready for reading meta data.
+ * @return A String array with the text value column names.
+ * @throws SQLException If an SQL error occurs.
+ */
+ protected String[] getValueColumns(ResultSet rs) throws SQLException {
+ List output = new LinkedList();
+ ResultSetMetaData metadata = rs.getMetaData();
+ int count = metadata.getColumnCount();
+ for(int i = 0; i < count; i++) {
+ String columnName = metadata.getColumnName(i+1); // (Count from 1)
+ if(! idColumn.equals(columnName) && ! languageColumn.equals(columnName) )
+ output.add(columnName);
+ }
+ return (String[])output.toArray(new String[0]);
+ }
+
+ /**
+ * Get <code>Locale</code> for the current record in the ResultSet. May be overridden
+ * by subclasses to allow for proprietary interpretation of language data.
+ * The default implementation assumes the column with the name provided as languageColumn
+ * for the constructor contains the ISO-639 code.
+ * @return The <code>Locale</code> of the current <code>ResultSet</code> record.
+ */
+ protected Locale getLocale(ResultSet rs) throws SQLException {
+ return new Locale(rs.getString(languageColumn).toLowerCase());
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Methods to implement MessageProvider
+ ///////////////////////////////////////////////////////////////////////
+
+ public String getText(String id, String entry, Locale locale) {
+ // TODO: Add Logging
+ Map entries = getEntries(id, locale);
+ if(entries != null) {
+ // TODO: Consider whether we need to recurse up if entries does not contain requested entry
+ return (String)entries.get(entry);
+ }
+ else
+ return null;
+ }
+
+ public Map getEntries(String id, Locale locale) {
+ Map entries = findEntriesRecursively(id,locale);
+ if(entries == null) // If not found by using specified locale, try to use default
+ entries = findEntriesRecursively(id,Locale.getDefault());
+ return entries;
+ }
+
+ /**
+ * Find entries by looking at the parent locale (language, country, variant ->
+ * language, country -> language) until entry is found. If entry not found for topmost
+ * Locale (language only), null is returned.
+ */
+ private Map findEntriesRecursively(String id, Locale locale) {
+ Map localeIds = (Map)locales.get(locale);
+ if(localeIds != null) {
+ Map entries = (Map)localeIds.get(id);
+ if(entries != null)
+ return entries;
+ }
+ Locale parentLocale = I18nUtils.getParentLocale(locale);
+ if(parentLocale == null)
+ return null;
+ else
+ return findEntriesRecursively(id, parentLocale); // Recursive call
+ }
+
+}
Modified: jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedError.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedError.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedError.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedError.java Sun Jul 24 05:53:05 2005
@@ -52,7 +52,7 @@
super(errorMessage.getSummary(
Locale.getDefault(),
MessageFormat.format(
- MessageManager.INTERNAL_MESSAGES.getString(MessageManager.MESSAGE_ENTRY_NOT_FOUND),
+ I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.MESSAGE_ENTRY_NOT_FOUND),
new String[] { errorMessage.getId(), ErrorBundle.SUMMARY })));
this.errorMessage = errorMessage;
}
Modified: jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedException.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedException.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedException.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedException.java Sun Jul 24 05:53:05 2005
@@ -51,7 +51,7 @@
super(errorMessage.getSummary(
Locale.getDefault(),
MessageFormat.format(
- MessageManager.INTERNAL_MESSAGES.getString(MessageManager.MESSAGE_ENTRY_NOT_FOUND),
+ I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.MESSAGE_ENTRY_NOT_FOUND),
new String[] { errorMessage.getId(), ErrorBundle.SUMMARY })));
this.errorMessage = errorMessage;
}
Modified: jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedRuntimeException.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedRuntimeException.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedRuntimeException.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/LocalizedRuntimeException.java Sun Jul 24 05:53:05 2005
@@ -50,7 +50,7 @@
super(errorMessage.getSummary(
Locale.getDefault(),
MessageFormat.format(
- MessageManager.INTERNAL_MESSAGES.getString(MessageManager.MESSAGE_ENTRY_NOT_FOUND),
+ I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.MESSAGE_ENTRY_NOT_FOUND),
new String[] { errorMessage.getId(), ErrorBundle.SUMMARY })));
this.errorMessage = errorMessage;
}
Modified: jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/MessageManager.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/MessageManager.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/MessageManager.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/MessageManager.java Sun Jul 24 05:53:05 2005
@@ -46,16 +46,7 @@
*
*/
public class MessageManager {
- static final String INTERNAL_MESSAGE_NOT_FOUND = "Internal I18n error: Message not found";
-
- static final String MESSAGE_NOT_FOUND = "messageNotFound";
- static final String NO_MESSAGE_ENTRIES_FOUND = "noMessageEntriesFound";
- static final String MESSAGE_ENTRY_NOT_FOUND = "messageEntryNotFound";
- static final String RESOURCE_BUNDLE_NOT_FOUND = "resourceBundleNotFound";
- public static final String MESSAGE_PARSING_ERROR = "messageParsingError";
- public static final ResourceBundle INTERNAL_MESSAGES = ResourceBundle.getBundle("i18n-messages", Locale.getDefault());
-
private static Map messageProviders = new LinkedHashMap();
/**
@@ -115,17 +106,16 @@
Locale locale) throws MessageNotFoundException {
if(messageProviders.isEmpty())
throw new MessageNotFoundException("No MessageProvider registered");
- MessageNotFoundException exception = null;
for (Iterator i = messageProviders.values().iterator(); i.hasNext();) {
- try {
- String text = ((MessageProvider) i.next()).getText(id, entry,
- locale);
- return MessageFormat.format(text, arguments);
- } catch (MessageNotFoundException e) {
- exception = e;
- }
+ String text = ((MessageProvider) i.next()).getText(id, entry,
+ locale);
+ if(text != null)
+ return (arguments != null && arguments.length > 0) ?
+ MessageFormat.format(text, arguments) : text;
}
- throw exception;
+ throw new MessageNotFoundException(MessageFormat.format(
+ I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.MESSAGE_ENTRY_NOT_FOUND),
+ new String[] { id, entry }));
}
/**
@@ -153,7 +143,8 @@
try {
return getText(id, entry, arguments, locale);
} catch (MessageNotFoundException e) {
- return MessageFormat.format(defaultText, arguments);
+ return (arguments != null && arguments.length > 0) ?
+ MessageFormat.format(defaultText, arguments) : defaultText;
}
}
@@ -182,7 +173,13 @@
if(provider == null)
throw new MessageNotFoundException("Provider '" + providerId + "' not installed");
String text = provider.getText(id, entry, locale);
- return MessageFormat.format(text, arguments);
+ if(text != null)
+ return (arguments != null && arguments.length > 0) ?
+ MessageFormat.format(text, arguments) : text;
+ else
+ throw new MessageNotFoundException(MessageFormat.format(
+ I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.MESSAGE_ENTRY_NOT_FOUND),
+ new String[] { id, entry }));
}
/**
@@ -211,7 +208,8 @@
try {
return getText(providerId, id, entry, arguments, locale);
} catch (MessageNotFoundException e) {
- return MessageFormat.format(defaultText, arguments);
+ return (arguments != null && arguments.length > 0) ?
+ MessageFormat.format(defaultText, arguments) : defaultText;
}
}
Modified: jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/MessageProvider.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/MessageProvider.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/MessageProvider.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/MessageProvider.java Sun Jul 24 05:53:05 2005
@@ -36,11 +36,12 @@
* @param id unique id that specifies a particular message
* @param entry specifies a particular entry in the specified message
* @param locale the locale for which this text should be provided
- * @return returns the localized message entry matching the given message id, entry key and locale
- * @throws MessageNotFoundException thrown if no message exists matching the given id or if
- * the specified message does not contain the desired entry
+ * @return returns the localized message entry matching the given message id, entry key and locale. If
+ * no match is found for the given locale, the parent locale is used, and finally the default. If the
+ * id is found but the entry is not, null is returned.
+ * @throws MessageNotFoundException thrown if no message exists matching the given id
*/
- public String getText(String id, String entry, Locale locale) throws MessageNotFoundException;
+ public String getText(String id, String entry, Locale locale);
/**
* @param id unique id that specifies a particular message
Modified: jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java Sun Jul 24 05:53:05 2005
@@ -39,8 +39,23 @@
private final String baseName;
- public ResourceBundleMessageProvider(String baseName) {
+ /**
+ *
+ * @throws MessageNotFoundException Thrown if the resource bundle does not exist.
+ */
+ public ResourceBundleMessageProvider(String baseName) throws MessageNotFoundException {
this.baseName = baseName;
+ // Test if resource exists
+ try {
+ ResourceBundle.getBundle(baseName);
+ }
+ catch ( MissingResourceException e ) {
+ String msg = MessageFormat.format(
+ I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.RESOURCE_BUNDLE_NOT_FOUND),
+ new String[]{baseName});
+ logger.log(Level.WARNING, msg);
+ throw new MessageNotFoundException(msg);
+ }
}
/* (non-Javadoc)
@@ -55,12 +70,10 @@
logger.log(
Level.WARNING,
MessageFormat.format(
- MessageManager.INTERNAL_MESSAGES.getString(MessageManager.RESOURCE_BUNDLE_NOT_FOUND),
- new String[] { baseName }));
+ I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.NO_MESSAGE_ENTRIES_FOUND),
+ new String[] { id }));
+ return null;
}
- throw new MessageNotFoundException(MessageFormat.format(
- MessageManager.INTERNAL_MESSAGES.getString(MessageManager.NO_MESSAGE_ENTRIES_FOUND),
- new String[] { id }));
}
/* (non-Javadoc)
@@ -69,64 +82,22 @@
public Map getEntries(String id, Locale locale) {
String messageIdentifier = id+".";
Map entries = null;
- try {
- ResourceBundle resourceBundle = ResourceBundle.getBundle(baseName, locale);
- Enumeration keys = resourceBundle.getKeys();
- while ( keys.hasMoreElements() ) {
- String key = (String)keys.nextElement();
- if ( key.startsWith(messageIdentifier) ) {
- if ( entries == null ) {
- entries = new HashMap();
- }
- entries.put(key.substring(messageIdentifier.length()), resourceBundle.getString(key));
+ ResourceBundle resourceBundle = ResourceBundle.getBundle(baseName, locale);
+ Enumeration keys = resourceBundle.getKeys();
+ while ( keys.hasMoreElements() ) {
+ String key = (String)keys.nextElement();
+ if ( key.startsWith(messageIdentifier) ) {
+ if ( entries == null ) {
+ entries = new HashMap();
}
+ entries.put(key.substring(messageIdentifier.length()), resourceBundle.getString(key));
}
- } catch ( MissingResourceException e ) {
- logger.log(
- Level.WARNING,
- MessageFormat.format(
- MessageManager.INTERNAL_MESSAGES.getString(MessageManager.RESOURCE_BUNDLE_NOT_FOUND),
- new String[] { baseName }));
- // TODO: Consider uninstalling
}
if ( entries == null ) {
throw new MessageNotFoundException(MessageFormat.format(
- MessageManager.INTERNAL_MESSAGES.getString(MessageManager.NO_MESSAGE_ENTRIES_FOUND),
+ I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.NO_MESSAGE_ENTRIES_FOUND),
new String[] { id }));
}
return entries;
- }
-
- /**
- * Installs a new resource bundle containing messages for a specific locale
- * with the given name.
- *
- * @param baseName the name of the resource bundle. This name will be used to
- * find the resource bundle by using the java mechanisms for loading resource bundles
- * and to uninstall or update the messages contained in the resource bundle.
- *
- */
- public static void install(String baseName) {
- MessageManager.addMessageProvider(baseName,
- new ResourceBundleMessageProvider(baseName));
- }
-
- /**
- * @param baseName unique identifier for the resource bundle to uninstall
- */
- public static void uninstall(String baseName) {
- MessageManager.removeMessageProvider(baseName); // TODO: Consider checkning type
- }
-
- /**
- * Update the resources specified by the given unique identifier.
- * As the messages defined in resource bundles are not cached by the
- * current implementation, calling this method has no effect.
- * This may change in future versions.
- * @param baseName unique identifier for the resource bundle to update
- */
- public static void update(String baseName) {
- uninstall(baseName);
- install(baseName);
}
}
Modified: jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/XMLMessageProvider.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/XMLMessageProvider.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/XMLMessageProvider.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/java/org/apache/commons/i18n/XMLMessageProvider.java Sun Jul 24 05:53:05 2005
@@ -43,12 +43,9 @@
private static SAXParserFactory factory = SAXParserFactory.newInstance();
- private final String id;
-
private Map messages = new HashMap();
- public XMLMessageProvider(String id, InputStream inputStream) {
- this.id = id;
+ public XMLMessageProvider(InputStream inputStream) {
try {
Map applicationMessages = new HashMap();
SAXParser parser = factory.newSAXParser();
@@ -58,10 +55,9 @@
applicationMessages.putAll(parsedMessages);
messages.putAll(applicationMessages);
} catch (Exception exception) {
- logger.log(Level.SEVERE,
- MessageFormat.format(
- MessageManager.INTERNAL_MESSAGES.getString(MessageManager.MESSAGE_PARSING_ERROR),
- new String[] { id }), exception);
+ // TODO: Fix message without ID
+ logger.log(Level.SEVERE,I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.MESSAGE_PARSING_ERROR),exception);
+ // TODO: Consider throwing exception
}
}
@@ -81,33 +77,6 @@
return message.getEntries();
}
- /**
- * Installs a bunch of messages provided by the given <code>InputStream</code> for all locales specifed
- * in the given source. The messages can be uninstalled or updated by using the given unique identifier.
- *
- * @param id the unique identifier for unistalling or updating the provided messages
- * @param inputStream providing the messages in the required XML format
- */
- public static void install(String id, InputStream inputStream) {
- MessageManager.addMessageProvider(id, new XMLMessageProvider(id, inputStream));
- }
-
- /**
- * @param id unique identifier for the messages to uninstall
- */
- public static void uninstall(String id) {
- MessageManager.removeMessageProvider(id);
- }
-
- /**
- * @param id unique identifier for the messages to update
- * @param inputStream providing the updated messages in the required XML format
- */
- public static void update(String id, InputStream inputStream) {
- uninstall(id);
- install(id, inputStream);
- }
-
private Message findMessage(String id, Locale locale) {
Message message = lookupMessage(id, locale);
if (message == null) {
@@ -115,17 +84,19 @@
}
if (message == null ) throw new MessageNotFoundException(
MessageFormat.format(
- MessageManager.INTERNAL_MESSAGES.getString(MessageManager.MESSAGE_NOT_FOUND),
- new String[] { id }));
+ I18nUtils.INTERNAL_MESSAGES.getString(I18nUtils.MESSAGE_NOT_FOUND),
+ new String[] { id }));
return message;
}
private Message lookupMessage(String id, Locale locale) {
String key = id + '_' + locale.toString();
if (messages.containsKey(key)) return (Message)messages.get(key);
- while (key.lastIndexOf('_') > 0) {
- key = key.substring(0, key.lastIndexOf('_'));
+ locale = I18nUtils.getParentLocale(locale);
+ while (locale != null) {
+ key = id + '_' + locale.toString();
if (messages.containsKey(key)) return (Message)messages.get(key);
+ locale = I18nUtils.getParentLocale(locale);
}
return null;
}
Added: jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/I18nUtilsTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/I18nUtilsTest.java?rev=224613&view=auto
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/I18nUtilsTest.java (added)
+++ jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/I18nUtilsTest.java Sun Jul 24 05:53:05 2005
@@ -0,0 +1,45 @@
+/*
+*
+* ====================================================================
+*
+* 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 junit.framework.TestCase;
+
+import java.util.Locale;
+
+/**
+ * @author Mattias Jiderhamn
+ */
+public class I18nUtilsTest extends TestCase {
+ public void testGetParentLocale() {
+ assertEquals("Language, country and variant",
+ new Locale("en", "GB"),
+ I18nUtils.getParentLocale(new Locale("en", "GB", "scottish")));
+
+ assertEquals("Language and country",
+ Locale.ENGLISH,
+ I18nUtils.getParentLocale(new Locale("en", "GB")));
+
+ assertEquals("Language and variant",
+ Locale.ENGLISH,
+ I18nUtils.getParentLocale(new Locale("en", "", "scottish")));
+
+ assertNull("Language only", I18nUtils.getParentLocale(Locale.ENGLISH));
+ }
+}
Added: jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/JdbcMessageProviderTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/JdbcMessageProviderTest.java?rev=224613&view=auto
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/JdbcMessageProviderTest.java (added)
+++ jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/JdbcMessageProviderTest.java Sun Jul 24 05:53:05 2005
@@ -0,0 +1,170 @@
+package org.apache.commons.i18n;
+
+import junit.framework.TestCase;
+
+import java.sql.DriverManager;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.dbcp.BasicDataSource;
+
+/**
+ * @author Mattias Jiderhamn
+ */
+public class JdbcMessageProviderTest extends TestCase {
+
+ private static Connection getNewConnection() throws SQLException {
+ return DriverManager.getConnection("jdbc:hsqldb:.", "sa", ""); // Connect to in-memory database
+ }
+
+ public void setUp() throws Exception {
+ /* Make sure en_US is the default Locale for tests */
+ Locale.setDefault(Locale.US);
+
+ Class.forName("org.hsqldb.jdbcDriver"); // Load HSQLDB database driver
+ Connection conn = getNewConnection();
+ Statement stmt = conn.createStatement();
+ stmt.execute(
+ "CREATE TABLE messages ( " +
+ " 'id' VARCHAR(30), " +
+ " 'language' VARCHAR(2), " +
+ " 'title' VARCHAR(100), " +
+ " 'text' VARCHAR(100)" +
+ ")");
+ stmt.execute(
+ "INSERT INTO messages VALUES (" +
+ " 'helloWorld', 'en', " +
+ " 'Hello World', 'I wish you a merry christmas!'" +
+ ")"
+ );
+ stmt.execute(
+ "INSERT INTO messages VALUES (" +
+ " 'helloWorld', 'de', " +
+ " 'Hallo Welt', 'Ich wünsche Dir alles Gute und ein frohes Fest!'" +
+ ")"
+ );
+ stmt.close();
+ conn.close();
+ }
+
+ public void tearDown() throws Exception {
+ Connection conn = getNewConnection();
+ conn.createStatement().execute(
+ "DROP TABLE messages"
+ );
+ conn.close();
+ }
+
+ public void testConstructors() throws Exception {
+ // Connection constructor
+ Connection conn = DriverManager.getConnection("jdbc:hsqldb:.", "sa", ""); // Connect to in-memory database
+ JdbcMessageProvider jdbcMessageProvider = new JdbcMessageProvider(conn, "messages", "id", "language");
+ conn.close();
+ assertEquals("Hello World", jdbcMessageProvider.getText("helloWorld", "title", Locale.ENGLISH));
+
+ // DataSource constructor
+ BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setUrl("jdbc:hsqldb:.");
+ dataSource.setUsername("sa");
+ dataSource.setPassword("");
+ jdbcMessageProvider = new JdbcMessageProvider(dataSource, "messages", "id", "language");
+ assertEquals("Hello World", jdbcMessageProvider.getText("helloWorld", "title", Locale.ENGLISH));
+
+ // Map/Properties constructor
+ Properties props = new Properties();
+ props.setProperty("jdbc.connect.driver", "org.hsqldb.jdbcDriver");
+ props.setProperty("jdbc.connect.url", "jdbc:hsqldb:.");
+ props.setProperty("jdbc.connect.login", "sa");
+ props.setProperty("jdbc.connect.password", "");
+
+ props.setProperty("jdbc.sql.table", "messages");
+ props.setProperty("jdbc.sql.key.column", "id");
+ props.setProperty("jdbc.sql.locale.column", "language");
+ jdbcMessageProvider = new JdbcMessageProvider(props);
+ assertEquals("Hello World", jdbcMessageProvider.getText("helloWorld", "title", Locale.ENGLISH));
+
+ // Test install
+ MessageManager.addMessageProvider("messages", jdbcMessageProvider);
+ assertEquals("Hello World", MessageManager.getText("helloWorld", "title", null, Locale.ENGLISH));
+ }
+
+ public void testGetText() throws Exception {
+ Connection conn = DriverManager.getConnection("jdbc:hsqldb:.", "sa", ""); // Connect to in-memory database
+ JdbcMessageProvider jdbcMessageProvider = new JdbcMessageProvider(conn, "messages", "id", "language");
+ conn.close();
+
+ // Explicit default locale
+ assertEquals("Hello World", jdbcMessageProvider.getText("helloWorld", "title", Locale.ENGLISH));
+ assertEquals("I wish you a merry christmas!", jdbcMessageProvider.getText("helloWorld", "text", Locale.ENGLISH));
+
+ // Default locale with country
+ assertEquals("Hello World", jdbcMessageProvider.getText("helloWorld", "title", Locale.US));
+ assertEquals("I wish you a merry christmas!", jdbcMessageProvider.getText("helloWorld", "text", Locale.US));
+
+ // Default locale with country and variant
+ Locale scottish = new Locale("en", "", "scottish");
+ assertEquals("Hello World", jdbcMessageProvider.getText("helloWorld", "title", scottish));
+ assertEquals("I wish you a merry christmas!", jdbcMessageProvider.getText("helloWorld", "text", scottish));
+
+ assertEquals("Hallo Welt", jdbcMessageProvider.getText("helloWorld", "title", Locale.GERMAN));
+ assertEquals("Ich wünsche Dir alles Gute und ein frohes Fest!", jdbcMessageProvider.getText("helloWorld", "text", Locale.GERMAN));
+
+ // Default locale with country
+ assertEquals("Hallo Welt", jdbcMessageProvider.getText("helloWorld", "title", Locale.GERMANY));
+ assertEquals("Ich wünsche Dir alles Gute und ein frohes Fest!", jdbcMessageProvider.getText("helloWorld", "text", Locale.GERMANY));
+
+ // Test use of defaule
+ assertEquals("Hello World", jdbcMessageProvider.getText("helloWorld", "title", Locale.JAPANESE));
+ assertEquals("I wish you a merry christmas!", jdbcMessageProvider.getText("helloWorld", "text", Locale.JAPANESE));
+
+ // Test non-existent
+ assertNull(jdbcMessageProvider.getText("helloWorld", "foobar", Locale.ENGLISH));
+ assertNull(jdbcMessageProvider.getText("foo", "bar", Locale.ENGLISH));
+ }
+
+ public void testGetEntries() throws Exception {
+ Connection conn = DriverManager.getConnection("jdbc:hsqldb:.", "sa", ""); // Connect to in-memory database
+ JdbcMessageProvider jdbcMessageProvider = new JdbcMessageProvider(conn, "messages", "id", "language");
+ conn.close();
+
+ // Explicit default locale
+ Map entries = jdbcMessageProvider.getEntries("helloWorld", Locale.ENGLISH);
+ assertEquals("No of entries", 2, entries.size());
+ assertEquals("Hello World", (String)entries.get("title"));
+ assertEquals("I wish you a merry christmas!", (String)entries.get("text"));
+
+ // Default locale with country
+ entries = jdbcMessageProvider.getEntries("helloWorld", Locale.US);
+ assertEquals("No of entries", 2, entries.size());
+ assertEquals("Hello World", (String)entries.get("title"));
+ assertEquals("I wish you a merry christmas!", (String)entries.get("text"));
+
+ // Default locale with country and variant
+ Locale scottish = new Locale("en", "", "scottish");
+ entries = jdbcMessageProvider.getEntries("helloWorld", scottish);
+ assertEquals("No of entries", 2, entries.size());
+ assertEquals("Hello World", (String)entries.get("title"));
+ assertEquals("I wish you a merry christmas!", (String)entries.get("text"));
+
+ entries = jdbcMessageProvider.getEntries("helloWorld", Locale.GERMAN);
+ assertEquals("No of entries", 2, entries.size());
+ assertEquals("Hallo Welt", (String)entries.get("title"));
+ assertEquals("Ich wünsche Dir alles Gute und ein frohes Fest!", (String)entries.get("text"));
+
+ // Default locale with country
+ entries = jdbcMessageProvider.getEntries("helloWorld", Locale.GERMANY);
+ assertEquals("No of entries", 2, entries.size());
+ assertEquals("Hallo Welt", (String)entries.get("title"));
+ assertEquals("Ich wünsche Dir alles Gute und ein frohes Fest!", (String)entries.get("text"));
+
+ // Test use of defaule
+ entries = jdbcMessageProvider.getEntries("helloWorld", Locale.JAPANESE);
+ assertEquals("No of entries", 2, entries.size());
+ assertEquals("Hello World", (String)entries.get("title"));
+ assertEquals("I wish you a merry christmas!", (String)entries.get("text"));
+ }
+}
Modified: jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/MessageManagerTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/MessageManagerTest.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/MessageManagerTest.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/MessageManagerTest.java Sun Jul 24 05:53:05 2005
@@ -50,7 +50,9 @@
fail("Mock provider should throw Exception");
}
catch(MessageNotFoundException mnfex) {
- assertEquals("Error text", "Mock exception from getText()", mnfex.getMessage());
+ // TODO: What error message is most correct (here and elsewhere)?
+ // assertEquals("Error text", "No message entries found for bundle with key dummyId", mnfex.getMessage());
+ assertEquals("Error text", "Message bundle with key dummyId does not contain an entry with key dummyEntry", mnfex.getMessage());
}
addMockProvider(); // Add mock provider
@@ -97,6 +99,17 @@
assertEquals("Normal qualified lookup", "Source=mockProvider2 Id=id Entry=entry Locale=en_US",
MessageManager.getText("mockProvider2", "id", "entry", null, Locale.US));
+
+ // Named provider found, but fails to find message
+ addThrowingMockProvider(); // Add mock provider returning null for unknown entries
+ try {
+ MessageManager.getText("throwingMock", "dummyId", "dummyEntry", null, Locale.US);
+ fail("Unknown provider should throw Exception");
+ }
+ catch(MessageNotFoundException mnfex) {
+ assertEquals("Error text", "Message bundle with key dummyId does not contain an entry with key dummyEntry", mnfex.getMessage());
+ }
+
}
public void testGetEntries() {
Modified: jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/MockProviderTestBase.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/MockProviderTestBase.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/MockProviderTestBase.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/MockProviderTestBase.java Sun Jul 24 05:53:05 2005
@@ -70,7 +70,7 @@
protected void addThrowingMockProvider() {
MessageManager.addMessageProvider("throwingMock", new MessageProvider() {
public String getText(String id, String entry, Locale locale) throws MessageNotFoundException {
- throw new MessageNotFoundException("Mock exception from getText()");
+ return null;
}
public Map getEntries(String id, Locale locale) throws MessageNotFoundException {
Modified: jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java Sun Jul 24 05:53:05 2005
@@ -42,10 +42,7 @@
public void tearDown() {
/* Uninstall resource bundles after every test */
- ResourceBundleMessageProvider.uninstall("messageBundle");
- ResourceBundleMessageProvider.uninstall("messageBundle2");
- ResourceBundleMessageProvider.uninstall("nonExistentBundle");
- ResourceBundleMessageProvider.uninstall("org.apache.commons.i18n.MyListResourceBundle");
+ MessageManager.clearMessageProviders();
}
public void testInstallResourceBundle() {
@@ -59,15 +56,11 @@
assertEquals("No MessageProvider registered", mnfex.getMessage());
}
- ResourceBundleMessageProvider.install("messageBundle");
+ MessageManager.addMessageProvider("messageBundle", new ResourceBundleMessageProvider("messageBundle"));
assertEquals("Hallo Welt", testMessage.getTitle(Locale.GERMAN));
- ResourceBundleMessageProvider.update("messageBundle");
-
- assertEquals("OK after update", "Hallo Welt", testMessage.getTitle(Locale.GERMAN));
-
- ResourceBundleMessageProvider.uninstall("messageBundle");
+ MessageManager.removeMessageProvider("messageBundle");
try {
testMessage.getTitle(Locale.GERMAN);
@@ -95,34 +88,16 @@
assertEquals("Value from ListResourceBundle", "listResourceValue", listResourceBundleProvider.getText("helloWorld", "title", Locale.US));
assertEquals("Value from ListResourceBundle", "1", listResourceBundleProvider.getText("helloWorld", "text", Locale.US));
- try {
- rbmp.getText("nonExistentId", "nonExistentEntry", Locale.US);
- fail("ID does not exist, should throw exception");
- }
- catch(MessageNotFoundException mnfex) {
- assertEquals("No message entries found for bundle with key nonExistentId", mnfex.getMessage());
- }
+ assertNull(rbmp.getText("nonExistentId", "nonExistentEntry", Locale.US));
- try {
- rbmp.getText("helloWorld", "nonExistentEntry", Locale.US);
- fail("Entry does not exist, should throw exception");
- }
- catch(MessageNotFoundException mnfex) {
- assertEquals("No message entries found for bundle with key helloWorld", mnfex.getMessage());
- }
+ assertNull(rbmp.getText("helloWorld", "nonExistentEntry", Locale.US));
- // Test unexisting bundle which should throw MissingResourceException
- ResourceBundleMessageProvider.install("nonExistentBundle"); // Install non-existent bundle
- ResourceBundleMessageProvider.update("messageBundle"); // Place last in list
- rbmp.getText("helloWorld", "title", Locale.US); // Should not throw Exception
-
- ResourceBundleMessageProvider nonExistentBundleProvider = new ResourceBundleMessageProvider("nonExistentBundle");
try {
- nonExistentBundleProvider.getText("fooBar", "text", Locale.GERMAN);
+ new ResourceBundleMessageProvider("nonExistentBundle");
fail("Bundle does not exist and should cause error");
}
catch(MessageNotFoundException mnfex) {
- assertEquals("No message entries found for bundle with key fooBar", mnfex.getMessage());
+ assertEquals("Could not find resource bundle with base name nonExistentBundle, uninstalling it", mnfex.getMessage());
}
}
@@ -146,17 +121,21 @@
assertEquals("Fallback locale, text", "I wish you a merry christmas!", frenchEntries.get("text"));
assertEquals("This entry is not translated to any other languages", frenchEntries.get("notTranslated"));
-
- // Test unexisting bundle which should throw MissingResourceException
-// ResourceBundleMessageProvider.install("nonExistentBundle"); // Install non-existent bundle
-// ResourceBundleMessageProvider.update("messageBundle"); // Place last in list
- ResourceBundleMessageProvider nonExistentBundleProvider = new ResourceBundleMessageProvider("nonExistentBundle");
try {
- nonExistentBundleProvider.getEntries("fooBar", Locale.GERMAN);
+ ResourceBundleMessageProvider provider = new ResourceBundleMessageProvider("messageBundle");
+ provider.getEntries("fooBar", Locale.GERMAN);
fail("Bundle does not exist and should cause error");
}
catch(MessageNotFoundException mnfex) {
assertEquals("No message entries found for bundle with key fooBar", mnfex.getMessage());
+ }
+
+ try {
+ new ResourceBundleMessageProvider("nonExistentBundle");
+ fail("Bundle does not exist and should cause error");
+ }
+ catch(MessageNotFoundException mnfex) {
+ assertEquals("Could not find resource bundle with base name nonExistentBundle, uninstalling it", mnfex.getMessage());
}
}
}
Modified: jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/XMLMessageProviderTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/XMLMessageProviderTest.java?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/XMLMessageProviderTest.java (original)
+++ jakarta/commons/sandbox/i18n/trunk/src/test/org/apache/commons/i18n/XMLMessageProviderTest.java Sun Jul 24 05:53:05 2005
@@ -39,9 +39,7 @@
public void tearDown() {
/* Uninstall resource bundles after every test */
- XMLMessageProvider.uninstall("org.apache.commons-i18n.test");
- XMLMessageProvider.uninstall("org.apache.commons-i18n.error");
- XMLMessageProvider.uninstall("org.apache.commons-i18n.variants");
+ MessageManager.clearMessageProviders();
}
public void testInstallResourceBundle() {
@@ -55,17 +53,12 @@
assertEquals("No MessageProvider registered", mnfex.getMessage());
}
- XMLMessageProvider.install("org.apache.commons-i18n.test",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
+ MessageManager.addMessageProvider("org.apache.commons-i18n.test", new XMLMessageProvider(
+ Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")));
assertEquals("Hallo Welt", testMessage.getTitle(Locale.GERMAN));
- XMLMessageProvider.update("org.apache.commons-i18n.test",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
-
- assertEquals("OK after update", "Hallo Welt", testMessage.getTitle(Locale.GERMAN));
-
- XMLMessageProvider.uninstall("org.apache.commons-i18n.test");
+ MessageManager.removeMessageProvider("org.apache.commons-i18n.test");
try {
testMessage.getTitle(Locale.GERMAN);
@@ -76,14 +69,13 @@
}
// Try to parse non-XML file
- XMLMessageProvider.install("org.apache.commons-i18n.error",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("messageBundle.properties"));
+ new XMLMessageProvider(Thread.currentThread().getContextClassLoader().getResourceAsStream("messageBundle.properties"));
}
public void testGetText() {
// XMLMessageProvider.install("org.apache.commons-i18n.test",
// Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
- XMLMessageProvider xmlmp = new XMLMessageProvider("org.apache.commons-i18n.test",
+ XMLMessageProvider xmlmp = new XMLMessageProvider(
Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
assertEquals("Default locale", "hello world", xmlmp.getText("helloWorld", "title", Locale.US));
@@ -124,7 +116,7 @@
public void testGetTextVariants() {
// XMLMessageProvider.install("org.apache.commons-i18n.variants",
// Thread.currentThread().getContextClassLoader().getResourceAsStream("variantTestMessages.xml"));
- XMLMessageProvider xmlmp = new XMLMessageProvider("org.apache.commons-i18n.variants",
+ XMLMessageProvider xmlmp = new XMLMessageProvider(
Thread.currentThread().getContextClassLoader().getResourceAsStream("variantTestMessages.xml"));
assertEquals("hello world", xmlmp.getText("variants", "theKey", Locale.ENGLISH));
@@ -136,7 +128,7 @@
public void testGetEntries() {
// XMLMessageProvider.install("org.apache.commons-i18n.test",
// Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
- Map usEntries = new XMLMessageProvider("org.apache.commons-i18n.test",
+ Map usEntries = new XMLMessageProvider(
Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
getEntries("helloWorld", Locale.US);
assertEquals("Default locale, no of entries", 5, usEntries.size());
@@ -150,7 +142,7 @@
usEntries.get("details"));
assertEquals("This entry is not translated to any other languages (XML)", usEntries.get("notTranslated"));
- Map germanEntries = new XMLMessageProvider("org.apache.commons-i18n.test",
+ Map germanEntries = new XMLMessageProvider(
Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
getEntries("helloWorld", Locale.GERMAN);
assertEquals("No of entries", 4, germanEntries.size());
@@ -162,7 +154,7 @@
germanEntries.get("details"));
// assertEquals("This entry is not translated to any other languages", germanEntries.get("notTranslated"));
- Map japaneseEntries = new XMLMessageProvider("org.apache.commons-i18n.test",
+ Map japaneseEntries = new XMLMessageProvider(
Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
getEntries("helloWorld", Locale.JAPANESE);
assertEquals("Fallback locale, no of entries", 5, japaneseEntries.size());
Modified: jakarta/commons/sandbox/i18n/trunk/xdocs/examples.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/i18n/trunk/xdocs/examples.xml?rev=224613&r1=224612&r2=224613&view=diff
==============================================================================
--- jakarta/commons/sandbox/i18n/trunk/xdocs/examples.xml (original)
+++ jakarta/commons/sandbox/i18n/trunk/xdocs/examples.xml Sun Jul 24 05:53:05 2005
@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="ISO-8859-1"?>
<document>
@@ -26,9 +26,9 @@
public static void main(String[] args) {
// Install the file providing the required messages for this example
- XMLMessageProvider.install("org.apache.commons-i18n.examples", Thread
- .currentThread().getContextClassLoader().getResourceAsStream(
- "exampleMessages.xml"));
+ MessageManager.addMessageProvider("org.apache.commons-i18n.examples",
+ new XMLMessageProvider(Thread.currentThread().getContextClassLoader().getResourceAsStream(
+ "exampleMessages.xml")));
// Simulate the locale of the current user in a multi-user environment
// such as a web application
@@ -74,6 +74,127 @@
String userCausingTheException = "Daniel";
throw new LocalizedException(new ErrorBundle("theCauseOfThisException",
new String[]{userCausingTheException}));
+ }
+}
+</source>
+</section>
+
+<section name="Using JDBC provider and qualifying message source">
+<p>
+This example shows how to use qualified message providers, instead of searching
+through all available providers and how to use i18n for messages stored in databases.
+For the sake of the example, we will create an in memory database holding the i18n
+messages using HSQLDB.
+</p>
+<source>
+public class QualifiedJdbcExample {
+ public static void main(String[] args) throws Exception {
+ /////////////////////////////////////////////////////
+ // Prepare example
+ /////////////////////////////////////////////////////
+
+ // Set up in-memory data for the sake of the example
+ prepareTables();
+
+ /////////////////////////////////////////////////////
+ // Example of initialization
+ /////////////////////////////////////////////////////
+
+ // We can initialize JDBC message provider using a properties file
+ Properties props = new Properties();
+ props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("i18n-jdbc.properties"));
+ MessageManager.addMessageProvider("messages", new JdbcMessageProvider(props));
+
+ // We can also initialize JDBC message provider by providing connection (or DataSource)
+ Connection conn = getNewConnection();
+ MessageManager.addMessageProvider("errors", new JdbcMessageProvider(conn, "errors", "id", "language"));
+ conn.close();
+
+ /////////////////////////////////////////////////////
+ // Example of usage
+ /////////////////////////////////////////////////////
+
+ // Simulate the locale of the current user in a multi-user environment
+ // such as a web application
+ Locale currentUsersLocale = new Locale("sv"); // Assume Swedish
+
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+
+ // Get i18n text qualifying the message source (i.e. the MessageProvider) to use; messages
+ TextBundle textBundle = new TextBundle("messages", "enterFirstName");
+ System.out.println(textBundle.getText(currentUsersLocale) + ":");
+ String firstName = reader.readLine();
+
+ textBundle = new TextBundle("messages", "enterLastName");
+ System.out.println(textBundle.getText(currentUsersLocale) + ":");
+ String lastName = reader.readLine();
+
+ validateNames(firstName, lastName);
+ }
+ catch(LocalizedRuntimeException lrex) {
+ // Retrieve the detailed localized error message
+ ErrorBundle errorMessage = lrex.getErrorMessage();
+
+ // Print summary and details using the current users locale
+ System.out.println("-- " + errorMessage.getSummary(currentUsersLocale) + " --");
+ System.out.println(errorMessage.getDetails(currentUsersLocale));
+ }
+ }
+
+ private static void validateNames(String firstname, String lastname) {
+ if(firstname.equals(lastname))
+ throw new LocalizedRuntimeException(new ErrorBundle("errors", "identicalNames"));
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Utility methods for the example
+ ///////////////////////////////////////////////////////////////////////
+
+ /**
+ * Create connection to in-memory HSQLDB database
+ * @return
+ * @throws ClassNotFoundException
+ * @throws SQLException
+ */
+ private static Connection getNewConnection() throws ClassNotFoundException, SQLException {
+ Class.forName("org.hsqldb.jdbcDriver"); // Load HSQLDB database driver
+ return DriverManager.getConnection("jdbc:hsqldb:.", "sa", ""); // Connect to in-memory database
+ }
+
+ /**
+ * Create tables and insert messages
+ */
+ private static void prepareTables() throws ClassNotFoundException, SQLException {
+ Connection conn = getNewConnection();
+ Statement stmt = conn.createStatement();
+ stmt.execute(
+ "CREATE TABLE messages ( " +
+ " 'id' VARCHAR(30), " +
+ " 'language' VARCHAR(2), " +
+ " 'text' VARCHAR(100)" +
+ ")");
+ stmt.execute("INSERT INTO messages VALUES ('enterFirstName', 'en', 'Please enter your first name')");
+ stmt.execute("INSERT INTO messages VALUES ('enterLastName', 'en', 'Please enter your last name')");
+ stmt.execute("INSERT INTO messages VALUES ('enterFirstName', 'sv', 'Vänligen ange ditt förnamn')");
+ stmt.execute("INSERT INTO messages VALUES ('enterLastName', 'sv', 'Vänligen ange ditt efternamn')");
+ stmt.execute(
+ "CREATE TABLE errors ( " +
+ " 'id' VARCHAR(30), " +
+ " 'language' VARCHAR(2), " +
+ " 'summary' VARCHAR(100), " +
+ " 'details' VARCHAR(100) " +
+ ")");
+ stmt.execute("INSERT INTO errors VALUES (" +
+ " 'identicalNames', 'en', " +
+ " 'Error! Identical names.', 'You entered the same name as both first name and last name'" +
+ ")");
+ stmt.execute("INSERT INTO errors VALUES (" +
+ " 'identicalNames', 'sv', " +
+ " 'Fel! Identiska namn.', 'Du angav samma namn som både förnamn och efternamn'" +
+ ")");
+ stmt.close();
+ conn.close();
}
}
</source>
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org