mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

kenneth_suter
17.23.2007 5fa20ea2d54d21a781d07995e27113b4c3bbc953
New tests for messaging plumbing to replace old ones:

- Format string cannot end with '.' (QUICKSETUP and ADMIN_TOOLS excluded)
- Categories cannot span multiple files and files cannot define messages in multiple categories

Addional methods for MessageDescriptorRegistry to access descriptors by defining class

Corrected some offending format strings

Corrected message property file boilerplates and help comments
27 files modified
426 ■■■■■ changed files
opends/build.xml 8 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/access_control.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/admin.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/admin_tool.properties 47 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/backend.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/config.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/core.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/extension.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/jeb.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/log.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/plugin.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/protocol.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/quicksetup.properties 45 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/replication.properties 23 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/schema.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/sync.properties 6 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/task.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/third_party.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/tools.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/user_defined.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/util.properties 6 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/utility.properties 9 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/version.properties 7 ●●●● patch | view | raw | blame | history
opends/src/messages/src/org/opends/messages/Category.java 5 ●●●●● patch | view | raw | blame | history
opends/src/messages/src/org/opends/messages/MessageDescriptor.java 10 ●●●●● patch | view | raw | blame | history
opends/src/messages/src/org/opends/messages/MessageDescriptorRegistry.java 53 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/messages/MessageDescriptorRegistryTest.java 102 ●●●●● patch | view | raw | blame | history
opends/build.xml
@@ -707,6 +707,10 @@
      <fileset dir="${msg.prop.dir}"/>
    </copy>
    <!-- copy the message descriptor registry file -->
    <copy todir="${classes.dir}/org/opends/messages"
          file="${msg.javagen.dir}/org/opends/messages/descriptors.reg" />
    <!-- Generate the OpenDS.jar file -->
    <jar jarfile="${pdir}/lib/${SHORT_NAME}.jar"
         basedir="${classes.dir}"
@@ -801,6 +805,10 @@
      <fileset dir="${msg.prop.dir}"/>
    </copy>
    <!-- copy the message descriptor registry file -->
    <copy todir="${classes.dir}/org/opends/messages"
          file="${msg.javagen.dir}/org/opends/messages/descriptors.reg" />
    <jar jarfile="${pdir}/lib/${SHORT_NAME}.jar"
         basedir="${classes.dir}" 
         excludes="${ads.classes.dir}, ${quicksetup.globalcompile.classes.dir}"    
opends/src/messages/messages/access_control.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/admin.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/admin_tool.properties
@@ -1,6 +1,51 @@
global.category=QUICKSETUP
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License").  You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at
# trunk/opends/resource/legal-notices/OpenDS.LICENSE
# or https://OpenDS.dev.java.net/OpenDS.LICENSE.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at
# trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
# add the following below this CDDL HEADER, with the fields enclosed
# by brackets "[]" replaced with your own identifying information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
# Global directives
#
global.category=ADMIN_TOOL
global.ordinal=-1
#
# Format string definitions
#
# Keys must be formatted as follows:
#
# [SEVERITY]_[DESCRIPTION]
#
# where:
#
# SEVERITY is one of:
# [INFO, MILD_WARN, SEVERE_WARN, MILD_ERR, SEVERE_ERR, FATAL_ERR, DEBUG, NOTICE]
#
# DESCRIPTION is an upper case string providing a hint as to the context of
# the message in upper case with the underscore ('_') character serving as
# word separator
#
INFO_ADDRESS_PORT_COLUMN=Address:Port
INFO_ADMINISTRATIVE_USERS_LABEL=Administrative Users:
INFO_AGE_OF_OLDEST_MISSING_CHANGE_COLUMN=<html>Age of Oldest<br>Missing \
opends/src/messages/messages/backend.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/config.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/core.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/extension.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/jeb.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/log.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/plugin.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/protocol.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/quicksetup.properties
@@ -1,6 +1,51 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License").  You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at
# trunk/opends/resource/legal-notices/OpenDS.LICENSE
# or https://OpenDS.dev.java.net/OpenDS.LICENSE.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at
# trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
# add the following below this CDDL HEADER, with the fields enclosed
# by brackets "[]" replaced with your own identifying information:
#      Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
# Global directives
#
global.category=QUICKSETUP
global.ordinal=-1
#
# Format string definitions
#
# Keys must be formatted as follows:
#
# [SEVERITY]_[DESCRIPTION]
#
# where:
#
# SEVERITY is one of:
# [INFO, MILD_WARN, SEVERE_WARN, MILD_ERR, SEVERE_ERR, FATAL_ERR, DEBUG, NOTICE]
#
# DESCRIPTION is an upper case string providing a hint as to the context of
# the message in upper case with the underscore ('_') character serving as
# word separator
#
INFO_ADMINISTRATOR_ALREADY_REGISTERED=Administrator already registered.
INFO_ADS_EXCEPTION=An unexpected error occurred managing the registration \
 information.%nThe error is: %s
opends/src/messages/messages/replication.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
@@ -85,7 +80,7 @@
NOTICE_EXCEPTION_STARTING_SESSION_20=Caught Exception during initial \
 communication with replication server :
NOTICE_CANNOT_RECOVER_CHANGES_21=Error when searching old changes from the \
 database.
 database
NOTICE_COULD_NOT_FIND_CHANGELOG_WITH_MY_CHANGES_22=Could not find a \
 replication server that has seen all the local changes. Going to replay \
 changes
@@ -95,23 +90,23 @@
SEVERE_ERR_EXCEPTION_DECODING_OPERATION_25=Error trying to replay %s, \
 operation could not be decoded :
FATAL_ERR_CHANGELOG_SHUTDOWN_DATABASE_ERROR_26=Error Trying to use the \
 underlying database. The Changelog Service is going to shut down.
 underlying database. The Changelog Service is going to shut down
SEVERE_ERR_IGNORE_BAD_DN_IN_DATABASE_IDENTIFIER_27=A badly formatted DN was \
 found in the list of database known By this changelog service :%s. This \
 Identifier will be ignored.
 Identifier will be ignored
SEVERE_ERR_ERROR_CLOSING_CHANGELOG_ENV_28=Error closing the changelog \
 database :
SEVERE_ERR_EXCEPTION_CHANGELOG_TRIM_FLUSH_29=Error during the changelog \
 database trimming or flush process. The Changelog service is going to \
 shutdown.
 shutdown
SEVERE_ERR_CHANGELOG_CONNECTION_ERROR_30=Error during Changelog service \
 message processing . Connection from %s is rejected.
 message processing . Connection from %s is rejected
SEVERE_ERR_UNKNOWN_MESSAGE_31=%s has sent an unknown message. Closing the \
 connection.
 connection
SEVERE_ERR_WRITER_UNEXPECTED_EXCEPTION_32=An unexpected error happened \
 handling connection with %s.  This connection is going to be closed.
 handling connection with %s.  This connection is going to be closed
SEVERE_ERR_CHANGELOG_ERROR_SENDING_ACK_33=An unexpected error occurred  while \
 sending an ack to %s.  This connection is going to be closed and reopened.
 sending an ack to %s.  This connection is going to be closed and reopened
SEVERE_ERR_EXCEPTION_RECEIVING_REPLICATION_MESSAGE_34=An Exception was caught \
 while receiving replication message : %s
MILD_ERR_LOOP_REPLAYING_OPERATION_35=A loop was detected while replaying \
opends/src/messages/messages/schema.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/sync.properties
@@ -21,12 +21,6 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
opends/src/messages/messages/task.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/third_party.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/tools.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/user_defined.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/messages/util.properties
@@ -21,12 +21,6 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
opends/src/messages/messages/utility.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
@@ -134,7 +129,7 @@
 record entry. Invalid value "%s" for the changetype specified. Expecting one \
 of the following values "%s"
SEVERE_ERR_LDIF_INVALID_MODIFY_ATTRIBUTE_VAL_31=Error in the LDIF change \
 record entry. Invalid value for the "%s" attribute specified.
 record entry. Invalid value for the "%s" attribute specified
SEVERE_ERR_SCHEMANAME_EMPTY_VALUE_32=The provided value could not be parsed \
 to determine whether it contained a valid schema element name or OID because \
 it was null or empty
opends/src/messages/messages/version.properties
@@ -21,12 +21,7 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
opends/src/messages/src/org/opends/messages/Category.java
@@ -134,9 +134,10 @@
  QUICKSETUP(0x01000000),
  /**
   * The category used for messages associated with the status panel.
   * The category used for messages associated with the tool like the
   * offline installer and unintaller.
   */
  STATUS_PANEL(0x01100000),
  ADMIN_TOOL(0x01100000),
  /**
   * The category that will be used for messages associated with
opends/src/messages/src/org/opends/messages/MessageDescriptor.java
@@ -872,6 +872,16 @@
  /**
   * Obtains the format string for constructing the string
   * value of this message according to the default
   * locale.
   * @return format string
   */
  String getFormatString() {
    return getFormatString(Locale.getDefault());
  }
  /**
   * Obtains the format string for constructing the string
   * value of this message according to the requested
   * locale.
   * @param locale for the returned format string
opends/src/messages/src/org/opends/messages/MessageDescriptorRegistry.java
@@ -29,6 +29,11 @@
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.util.List;
import java.util.LinkedList;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
@@ -36,17 +41,27 @@
import java.lang.reflect.Field;
/**
 * Serves as a registry for messages providing access to
 * descriptors by ID.
 * Serves as a registry for messages providing access to message descriptors
 * by ID and class in which they are defined.  Classes containing message
 * descriptors are stored in the text file "descriptors.reg" which is
 * generated during the OpenDS build process.
 */
public class MessageDescriptorRegistry {
  private static final String REGISTRY_FILE = "descriptors.reg";
  private static final Set<Class> REGISTERED_MESSAGE_CLASSES =
                  new HashSet<Class>();
  private static final Map<Integer, MessageDescriptor>
          ID_TO_DESCRIPTORS =
                  new HashMap<Integer,MessageDescriptor>();
  private static final Map<Class, List<MessageDescriptor>>
          CLASS_TO_DESCRIPTORS =
                  new HashMap<Class,List<MessageDescriptor>>();
  static {
    InputStream is = MessageDescriptor.class
            .getResourceAsStream(REGISTRY_FILE);
@@ -59,12 +74,16 @@
        Class descClass;
        try {
          descClass = Class.forName(descClassName);
          List<MessageDescriptor> mdList = new LinkedList<MessageDescriptor>();
          CLASS_TO_DESCRIPTORS.put(descClass,  mdList);
          REGISTERED_MESSAGE_CLASSES.add(descClass);
          Field[] fa = descClass.getFields();
          if (fa != null) {
            for (Field f : fa) {
              Class<?> c = f.getDeclaringClass();
              if (c.isAssignableFrom(MessageDescriptor.class)) {
              Class<?> c = f.getType();
              if (MessageDescriptor.class.isAssignableFrom(c)) {
                MessageDescriptor md = (MessageDescriptor)f.get(null);
                mdList.add(md);
                int id = md.getId();
                if (id != MessageDescriptor.NULL_ID) {
                  ID_TO_DESCRIPTORS.put(id, md);
@@ -88,6 +107,7 @@
  /**
   * Returns a message descriptor given its unique OpenDS system-wide ID.
   *
   * @param id integer value of the message to retreive
   * @return MessageDescriptor having the ID of <code>id</code>
   */
@@ -95,4 +115,29 @@
    return ID_TO_DESCRIPTORS.get(id);
  }
  /**
   * Given a registered class containing message descriptors, returns a
   * list of all message descriptors defined by that class.
   *
   * @param mdClass registered class containing message descriptors
   * @return unmodifiable list of message descriptors declared in
   *         <code>mdClass</code>
   */
  public static List<MessageDescriptor> getMessageDescriptorsForClass(
          Class mdClass)
  {
    return Collections.unmodifiableList(CLASS_TO_DESCRIPTORS.get(mdClass));
  }
  /**
   * Returns a set of classes registered as having message descriptor
   * declarations.
   *
   * @return list of classes
   */
  public static Set<Class> getRegisteredClasses() {
    return Collections.unmodifiableSet(REGISTERED_MESSAGE_CLASSES);
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/messages/MessageDescriptorRegistryTest.java
@@ -30,6 +30,17 @@
import static org.testng.Assert.*;
import org.testng.annotations.*;
import java.util.Set;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import java.util.Locale;
import java.util.EnumSet;
import java.util.Map;
import java.util.HashMap;
import java.lang.reflect.Field;
/**
 * MessageDescriptorRegistry Tester.
 *
@@ -46,8 +57,95 @@
  @Test(dataProvider = "message descriptors")
  public void testGetMessageDescriptor(MessageDescriptor md) {
    assertEquals(md,
            MessageDescriptorRegistry.getMessageDescriptor(md.getId()));
    MessageDescriptor md2 = MessageDescriptorRegistry.getMessageDescriptor(md.getId());
    assertEquals(md, md2);
  }
  @DataProvider(name = "message classes")
  public Object[][] getMessageClasses() {
    Set<Class> mdClasses = MessageDescriptorRegistry.getRegisteredClasses();
    List<Class> classesToTest = new ArrayList<Class>(mdClasses);
    // These newer message files don't comply
    classesToTest.remove(AdminToolMessages.class);
    classesToTest.remove(QuickSetupMessages.class);
    Object[][] ret = new Object[classesToTest.size()][1];
    for (int i = 0; i < ret.length; i++) {
      ret[i] = new Object[] { classesToTest.get(i) };
    }
    return ret;
  }
  /**
   * Tests that messages don't end with a period (.) excluding those that end
   * with an ellipsis (...)
   *
   * @param  messagesClass containing definitions of MessageDescriptor objects
   * @throws IllegalAccessException if there is a problem accessing the
   *         class through reflection
   */
  @Test(dataProvider = "message classes")
  public void testFormatStringsDontEndWithPeriod(Class messagesClass)
          throws IllegalAccessException
  {
    Field[] fa = messagesClass.getFields();
    if (fa != null) {
      for (Field f : fa) {
        Class<?> c = f.getType();
        if (MessageDescriptor.class.isAssignableFrom(c)) {
          MessageDescriptor md = (MessageDescriptor)f.get(null);
          String fmtString = md.getFormatString(Locale.getDefault());
          boolean bad = fmtString.endsWith(".") && !fmtString.endsWith("...");
          assertFalse(bad,
                  "Format string for message descriptor " + f.getName() +
                  " obtained through key " + md.getKey() +
                  " defined in class " + messagesClass.getName() +
                  " \'" + md.getFormatString(Locale.getDefault()) +
                  "\' ends with a '.'");
        }
      }
    }
  }
  /**
   * Tests that messages for each category are restricted to a single
   * messages file and that each file only contains messages from a
   * single category.
   */
  @Test
  public void testCategoriesDontSpanFiles() {
    Map<Category,Class> categoriesToClass = new HashMap<Category,Class>();
    Set categories = EnumSet.allOf(Category.class);
    Set<Class> msgClasses = MessageDescriptorRegistry.getRegisteredClasses();
    for (Class msgClass : msgClasses) {
      List<MessageDescriptor> mds =
              MessageDescriptorRegistry.getMessageDescriptorsForClass(msgClass);
      Category currentCategory = null;
      for (MessageDescriptor md : mds) {
        if (currentCategory == null) {
          currentCategory = md.getCategory();
          if (categories.contains(currentCategory)) {
            categories.remove(currentCategory);
            categoriesToClass.put(currentCategory, msgClass);
          } else {
            assertTrue(false,
                    "Message file " + msgClass + " defines descriptors " +
                    "for category " + currentCategory + " but message file " +
                    categoriesToClass.get(currentCategory) + " defines descriptors " +
                    "of " + currentCategory + ".  Descriptors for a particular " +
                    "category can only be defined in a single messages file.");
          }
        } else {
          boolean categoriesMatch = currentCategory.equals(md.getCategory());
          assertTrue(categoriesMatch,
                  "Message file " + msgClass + " contains descriptors from at least " +
                          "two different categories: descriptor of key " +
                          md.getFormatString() + " is of category " + md.getCategory() +
                          " but expected category was " + currentCategory);
        }
      }
    }
  }
}