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

ctissot
26.29.2008 7ebdf3ce2a518582334a7a167a98555885bcc065
Fix for 3259: No messages support in example plugin

Changes by file:

. resource/admin/example-plugin/ExamplePlugin.java
- support for messages
- fix for PluginResult.Startup refactoring

. resource/admin/example-plugin/example_plugin.properties
- 3 messages used in the example plugin (english/default)

. resource/admin/example-plugin/example_plugin_fr.properties
- 3 messages used in the example plugin (french)

. resource/admin/example-plugin/build.xml
- automatic generation of messages from properties files located in
resource/messages while keeping package name.
(eg. resource/messages/my/example/example_plugin.properties will
generate a message class with package name "my.example")

. resource/Messages.java.stub
- forced underlying properties files to be located in /messages within
jars file (eg MY_JAR_FILE:/messages/example_plugin.properties)
- support for messages available from extensions' classloaders

. src/messages/src/org/opends/messages/Message.java
- typo in javadoc

. build.xml
- added message template used by generator in the build-tools.jar
- added the "resource/messages" directory at the root of the example
plugin
- added example properties files in the example plugin zipfile

. src/build-tools/org/opends/build/tools/GenerateMessageFile.java
- stopped assuming messages are targeted in package name
org.opends.messages
- template for message class generation now retrieved from the
build-tools.jar when generating messages for extensions
- for user messages, set destination files automatically based on the
source full filename and apply basic pattern
(eg. source=resource/messages/my/example/example_plugin.properties
sets destination to
src-generated/my/example/ExamplePluginMessage.java)
2 files added
6 files modified
393 ■■■■■ changed files
opendj-sdk/opends/build.xml 14 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/resource/Messages.java.stub 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/resource/admin/example-plugin/ExamplePlugin.java 24 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/resource/admin/example-plugin/build.xml 62 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/resource/admin/example-plugin/example_plugin.properties 53 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/resource/admin/example-plugin/example_plugin_fr.properties 53 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/build-tools/org/opends/build/tools/GenerateMessageFile.java 181 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/messages/src/org/opends/messages/Message.java 2 ●●● patch | view | raw | blame | history
opendj-sdk/opends/build.xml
@@ -140,10 +140,11 @@
  <property name="configguide.resource.dir" location="resource/admin/config-guide" />
  <!-- Properties for generating messages. -->
  <property name="msg.prop.dir"    location="src/messages/messages" />
  <property name="msg.javagen.dir" location="src/messages/generated" />
  <property name="msg.dir"         location="src/messages" />
  <property name="msg.prop.dir"    location="${msg.dir}/messages" />
  <property name="msg.javagen.dir" location="${msg.dir}/generated" />
  <property name="msg.package.dir" location="${classes.dir}/messages" />
  <property name="msg.src.dir"     location="src/messages/src" />
  <property name="msg.src.dir"     location="${msg.dir}/src" />
  <!-- Properties for SNMP extension. -->
  <property name="snmp.mib.dir"      location="src/snmp/resource/mib" />
@@ -2031,6 +2032,8 @@
    <mkdir dir="${buildtools.classes.dir}" />
    <copy file="${resource.dir}/Messages.java.stub" todir="${buildtools.classes.dir}/org/opends/build/tools/resource"/>
    <javac srcdir="${src.dir}:${msg.src.dir}" destdir="${buildtools.classes.dir}"
           sourcepath=""
           includes="org/opends/messages/Severity.java,
@@ -2221,6 +2224,7 @@
    <mkdir dir="${plugin.temp.dir}/example-plugin/resource/admin" />
    <mkdir dir="${plugin.temp.dir}/example-plugin/resource/config" />
    <mkdir dir="${plugin.temp.dir}/example-plugin/resource/schema" />
    <mkdir dir="${plugin.temp.dir}/example-plugin/resource/messages" />
    <copy todir="${plugin.temp.dir}/example-plugin/src">
      <fileset dir="${admin.defn.dir}" includes="**/*.xml" />
    </copy>
@@ -2234,7 +2238,9 @@
    <copy todir="${plugin.temp.dir}/example-plugin/src/com/example/opends">
      <fileset dir="${admin.rules.dir}/example-plugin" includes="*.java,*.xml" excludes="build.xml" />
    </copy>
    <copy todir="${plugin.temp.dir}/example-plugin/lib" file="${build.dir}/build-tools/build-tools.jar" />
    <copy todir="${plugin.temp.dir}/example-plugin/resource/messages/com/example/opends/messages" file="${admin.rules.dir}/example-plugin/example_plugin.properties" />
    <copy todir="${plugin.temp.dir}/example-plugin/resource/messages/com/example/opends/messages" file="${admin.rules.dir}/example-plugin/example_plugin_fr.properties" />
    <!-- Package up the plugin in the OpenDS package folder. -->
    <zip destfile="${pdir}/example-plugin.zip">
      <zipfileset dir="${plugin.temp.dir}" filemode="644" dirmode="755" />
opendj-sdk/opends/resource/Messages.java.stub
@@ -44,7 +44,7 @@
public final class ${CLASS_NAME} {
  /** Base property for resource bundle containing messages */
  private static final String BASE = "${BASE}";
  private static final String BASE = "messages/${BASE}";
  private static ClassLoader webstartClassLoader;
@@ -96,7 +96,7 @@
    }
    else
    {
      cl = null;
      cl = ${CLASS_NAME}.class.getClassLoader();
    }
    return cl;
  }
opendj-sdk/opends/resource/admin/example-plugin/ExamplePlugin.java
@@ -32,7 +32,7 @@
import java.util.Set;
import org.opends.server.api.plugin.PluginType;
import org.opends.server.api.plugin.StartupPluginResult;
import org.opends.server.api.plugin.PluginResult;
import org.opends.server.api.plugin.DirectoryServerPlugin;
import org.opends.server.config.ConfigException;
import org.opends.server.types.ConfigChangeResult;
@@ -46,6 +46,8 @@
import com.example.opends.server.ExamplePluginCfg;
import static com.example.opends.messages.ExamplePluginMessages.*;
/**
 * The example plugin implementation class. This plugin will output
 * the configured message to the error log during server start up.
@@ -95,8 +97,8 @@
        // This is fine.
        break;
      default:
        throw new ConfigException(Message.raw("Invalid plugin type " + t
            + " for the example plugin."));
        Message message = ERR_INITIALIZE_PLUGIN.get(String.valueOf(t));
        throw new ConfigException(message);
      }
    }
@@ -119,11 +121,11 @@
   * @return  The result of the startup plugin processing.
   */
  @Override
  public StartupPluginResult doStartup() {
  public PluginResult.Startup doStartup() {
    // Log the provided message.
    logError(Message.raw(Category.CONFIG, Severity.NOTICE,
        "Example plugin message '" + config.getMessage() + "'."));
    return StartupPluginResult.SUCCESS;
    Message message = NOTE_DO_STARTUP.get(String.valueOf(config.getMessage()));
    logError(message);
    return PluginResult.Startup.continueStartup();
  }
@@ -143,10 +145,10 @@
    // Log a message to say that the configuration has changed. This
    // isn't necessary, but we'll do it just to show that the change
    // has taken effect.
    logError(Message.raw(Category.CONFIG, Severity.NOTICE,
        "Example plugin message has been changed from '"
            + this.config.getMessage() + "' to '"
            + config.getMessage() + "'"));
    Message message = NOTE_APPLY_CONFIGURATION_CHANGE.get(
                                      String.valueOf(this.config.getMessage()),
                                      String.valueOf(config.getMessage()));
    logError(message);
    // Update the configuration.
    this.config = config;
opendj-sdk/opends/resource/admin/example-plugin/build.xml
@@ -30,6 +30,9 @@
    This is the build script for an OpenDS Directory Server extension.
  </description>
  <!-- Import extra tasks from ant-contrib (for, if-then-else, ...) -->
  <taskdef resource="net/sf/antcontrib/antlib.xml"/>
  <!-- CONFIGURE: The name of the extension's Jar file. -->
  <property name="pkg.name" value="example-plugin" />
@@ -43,15 +46,19 @@
  <property name="build.dir" location="build" />
  <property name="src.dir" location="src" />
  <property name="src.gen.dir" location="src-generated" />
  <!-- alias variable as needed by the ant task that generates messages -->
  <property name="msg.javagen.dir" location="${src.gen.dir}" />
  <property name="lib.dir" location="lib" />
  <property name="ext.dir" location="ext" />
  <property name="resource.dir" location="resource" />
  <property name="admin.dir" location="${resource.dir}/admin" />
  <property name="config.dir" location="${resource.dir}/config" />
  <property name="schema.dir" location="${resource.dir}/schema" />
  <property name="msg.dir"    location="${resource.dir}/messages" />
  <property name="classes.dir" location="${build.dir}/classes" />
  <property name="javadoc.dir" location="${build.dir}/javadoc" />
  <property name="package.dir" location="${build.dir}/package" />
  <property name="message.dir" location="${build.dir}/message" />
  <property name="jar.file" value="${pkg.name}.jar" />
  <!-- Location of OpenDS components - should not need changing. -->
@@ -84,7 +91,7 @@
  </target>
  <!-- Compile the Directory Server extension source files. -->
  <target name="compile" depends="init,compileadmin" description="Compile the Directory Server extension source files.">
  <target name="compile" depends="init,compileadmin,generate-messages" description="Compile the Directory Server extension source files.">
    <mkdir dir="${classes.dir}" />
    <javac srcdir="${src.dir}:${src.gen.dir}" destdir="${classes.dir}" optimize="true" excludes="**/package-info.java" debug="on" debuglevel="lines,source" source="1.5" target="1.5" deprecation="true" fork="true" memoryInitialSize="${MEM}" memoryMaximumSize="${MEM}">
      <compilerarg value="-Xlint:all" />
@@ -251,4 +258,57 @@
      <schema namespace="http://www.opends.org/admin-cli" file="${admin.dir}/admin-cli.xsd" />
    </schemavalidate>
  </target>
  <!-- Generate messages from all .properties files located in the message directory and declared in a package-->
  <target name="generate-messages" description="Generate messages for extension.">
    <if>
      <available file="${msg.dir}" type="dir" property="message.dir.is-present"/>
      <then>
        <!-- list of files properties -->
        <path id="messages.properties">
          <!-- Note: a package is required and properties file at the root of the
           !         message directory will be ignored
           ! -->
          <fileset dir="${msg.dir}" includes="*/**/*.properties" />
        </path>
        <property name="msg.dir.list" refid="messages.properties" />
        <!-- includes lib/*.jar into classpath (actually build-tools.jar) -->
        <path id="msg.classpath">
          <fileset dir="${lib.dir}">
            <include name="*.jar" />
          </fileset>
        </path>
        <property name="build-tools.jar" refid="msg.classpath" />
        <typedef name="genmsg"
                 classname="org.opends.build.tools.GenerateMessageFile"
                 classpathref="msg.classpath">
        </typedef>
        <!-- set property if the list is not empty -->
        <if>
          <length string="${msg.dir.list}" when="greater" length="0" />
          <then>
            <!-- Generate the message catalogs for all messages located
             !   in the messages directory
             ! -->
            <mkdir dir="${classes.dir}/messages" />
            <for param="file" delimiter=":" list="${msg.dir.list}">
              <sequential>
                <genmsg sourceProps="@{file}" />
                <copy file="@{file}" todir="${classes.dir}/messages"/>
              </sequential>
            </for>
          </then>
          <else>
            <echo message="No messages found: ${message.dir} is empty" />
          </else>
        </if>
      </then>
      <else>
        <echo message="No messages found: ${msg.dir} is missing" />
      </else>
    </if>
  </target>
</project>
opendj-sdk/opends/resource/admin/example-plugin/example_plugin.properties
New file
@@ -0,0 +1,53 @@
# 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
#
#      Copyright 2006-2008 Sun Microsystems, Inc.
#
# Global directives
#
global.category=USER_DEFINED
#
# Format string definitions
#
# Keys must be formatted as follows:
#
# [SEVERITY]_[DESCRIPTION]_[ORDINAL]
#
# 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
#
# ORDINAL is an integer unique among other ordinals in this file
#
SEVERE_ERR_INITIALIZE_PLUGIN_1="Invalid plugin type %s for the example plugin.
NOTICE_DO_STARTUP_2=Example plugin message '%s'.
NOTICE_APPLY_CONFIGURATION_CHANGE_3="Example plugin message has been changed \
from '%s' to '%s'.
opendj-sdk/opends/resource/admin/example-plugin/example_plugin_fr.properties
New file
@@ -0,0 +1,53 @@
# 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
#
#      Copyright 2006-2008 Sun Microsystems, Inc.
#
# Global directives
#
global.category=USER_DEFINED
#
# Format string definitions
#
# Keys must be formatted as follows:
#
# [SEVERITY]_[DESCRIPTION]_[ORDINAL]
#
# 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
#
# ORDINAL is an integer unique among other ordinals in this file
#
SEVERE_ERR_INITIALIZE_PLUGIN_1="Type de plugin invalide %s pour le plugin d'exemple.
NOTICE_DO_STARTUP_2=Message du plugin d'exemple '%s'.
NOTICE_APPLY_CONFIGURATION_CHANGE_3="Le message du plugin d'exemple a été modifié \
de '%s' en '%s'.
opendj-sdk/opends/src/build-tools/org/opends/build/tools/GenerateMessageFile.java
@@ -39,7 +39,9 @@
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.DataOutputStream;
@@ -50,6 +52,7 @@
import java.util.UnknownFormatConversionException;
import java.util.Calendar;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.HashSet;
@@ -71,8 +74,14 @@
  static private final String MESSAGES_FILE_STUB =
          "resource/Messages.java.stub";
  static private final String REGISTRY_FILE_NAME =
          "src/messages/generated/org/opends/messages/descriptors.reg";
  /*
   * The registry filename is the result of the concatenation of the
   * location of where the source are generated, the package name and the
   * DESCRIPTORS_REG value.
   */
  static private String REGISTRY_FILE_NAME;
  static private final String DESCRIPTORS_REG = "descriptors.reg";
  /**
   * Used to set a category for all messages in the property file.
@@ -155,6 +164,31 @@
            .toString();
  }
  /*
   * ISO_LANGUAGES contains all official supported languages for i18n
   */
  private static final List<String> ISO_LANGUAGES =
                                        Arrays.asList(Locale.getISOLanguages());
  /*
   * ISO_COUNTRIES contains all official supported countries for i18n
   */
  private static final List<String> ISO_COUNTRIES =
                                        Arrays.asList(Locale.getISOCountries());
  /*
   * A Pattern instance that matches "<label>_<language>_<country>.properties"
   * where <label> can be anything including '_'
   *       <language> a two characters code contained in the ISO_LANGUAGES list
   *       <country> a two characters code contained in the ISO_COUNTRIES list
   */
  private static final Pattern LANGUAGE_COUNTRY_MATCHER =
                       Pattern.compile("(.*)_([a-z]{2})_([A-Z]{2}).properties");
  /*
   * A Pattern instance that matches "<label>_<language>.properties"
   * where <label> and <language> have same definition as above.
   */
  private static final Pattern LANGUAGE_MATCHER =
                       Pattern.compile("(.*)_([a-z]{2}).properties");
  /**
   * Representation of a format specifier (for example %s).
@@ -450,6 +484,51 @@
   */
  public void setDestJava(File dest) {
    this.dest = dest;
    /*
     * Set the descriptors.reg pathname to the same directory as the one used
     * to generate files and ensure all messages are generated in one place.
     */
    String projectBase = null;
    try {
      projectBase = getProject().getBaseDir().getCanonicalPath();
    } catch( java.io.IOException e) {
      throw new BuildException("Error processing " + dest +
            ": unable to retrieve project's directory of ant's project (" +
            e + ")");
    }
    String registry = dest.getAbsolutePath();
    // strip project directory prefix and replace properties filename with
    // $DESCRIPTORS_REG
    registry = registry.substring(projectBase.length()+1,
                                 registry.lastIndexOf(File.separator)+1)
                       .concat(DESCRIPTORS_REG);
    if ( REGISTRY_FILE_NAME == null ) {
      REGISTRY_FILE_NAME = registry;
    } else {
      if ( ! REGISTRY_FILE_NAME.equals(registry) ) {
        // multiple messages are generated in several packages
        StringBuilder sb = new StringBuilder();
        // full pathname of $REGISTRY_FILE_NAME
        sb.append(projectBase)
          .append(File.separator)
          .append(REGISTRY_FILE_NAME);
        // change from generated directory to properties files directory
        sb.replace(0,
                   getProject().getProperty("msg.javagen.dir").length(),
                   getProject().getProperty("msg.dir"));
        // replace properties filename with source filename
        sb.replace(sb.lastIndexOf(File.separator)+1,
                   sb.length(),
                   source.getName());
        throw new BuildException("Error processing " + dest +
              ": all messages must be located in the same package thus " +
              "name of the source file should be " + sb);
      }
    }
  }
  /**
@@ -466,6 +545,63 @@
   */
  @Override
  public void execute() throws BuildException {
    if ( this.dest == null ) {
      // this is an example-plugin call:
      // - check the source file is not a localization
      // - guess the destination filename from source filename
      String sourcefilename = source.getAbsolutePath();
      int filenameIndex = sourcefilename.lastIndexOf(File.separator)+1;
      String pathname = sourcefilename.substring(0, filenameIndex);
      String filename = sourcefilename.substring(filenameIndex);
      /*
       * Make sure only <label>.properties are generated thus avoiding to
       * generate messages for localized properties files.
       */
      Matcher matcher = LANGUAGE_COUNTRY_MATCHER.matcher(filename);
      if ( matcher.find() ) {
        if ( ISO_LANGUAGES.contains(matcher.group(2))
          && ISO_COUNTRIES.contains(matcher.group(3)) ) {
          // do not generate message for <label>_<language>_<country>.properties
          return;
        }
      }
      matcher = LANGUAGE_MATCHER.matcher(filename);
      if ( matcher.find() ) {
        if ( ISO_LANGUAGES.contains(matcher.group(2)) ) {
          // do not generate message for <label>_<language>.properties
          return;
        }
      }
      // filename without ".properties"
      filename = filename.substring(0, filename.length()-11);
      // change to src-generated directory keeping package name
      pathname = pathname.replace(getProject().getProperty("msg.dir"),
                                  getProject().getProperty("msg.javagen.dir"));
      // append characters from filename to pathname starting with an uppercase
      // letter, ignoring '_' and uppering all characters prefixed with "_"
      StringBuilder sb = new StringBuilder(pathname);
      boolean upperCaseNextChar = true;
      for(char c : filename.toCharArray()) {
        if ( c == '_' ) {
          upperCaseNextChar = true;
          continue;
        }
        if ( upperCaseNextChar ) {
          sb.append(Character.toUpperCase(c));
          upperCaseNextChar = false;
        } else {
          sb.append(c);
        }
      }
      sb.append("Messages.java");
      setDestJava(new File(sb.toString()));
    }
    BufferedReader stubReader = null;
    PrintWriter destWriter = null;
    try {
@@ -492,8 +628,8 @@
        log("Generating " + dest.getName() + " from " + source.getName());
      }
      stubReader = new BufferedReader(new InputStreamReader(
          new FileInputStream(getStubFile()), "UTF-8"));
      stubReader = new BufferedReader(new InputStreamReader(getStubFile(),
                                                            "UTF-8"));
      destWriter = new PrintWriter(dest, "UTF-8");
      String stubLine;
      Properties properties = new Properties();
@@ -700,16 +836,16 @@
  private String getBase() {
    String srcPath = unixifyPath(source.getAbsolutePath());
    String base = srcPath.substring(srcPath.lastIndexOf("messages/"));
    if (base.endsWith(".properties")) {
      base = base.substring(0, base.length() - ".properties".length());
    }
    String base = srcPath.substring(srcPath.lastIndexOf("/") + 1,
                                    srcPath.length() - ".properties".length());
    return base;
  }
  private String getPackage() {
    String destPath = unixifyPath(dest.getAbsolutePath());
    String c = destPath.substring(destPath.indexOf("org/opends"));
    String msgJavaGenDir = unixifyPath(
                                   getProject().getProperty("msg.javagen.dir"));
    String c = destPath.substring(msgJavaGenDir.length()+1);
    c = c.replace('/', '.');
    c = c.substring(0, c.lastIndexOf(".")); // strip .java
    c = c.substring(0, c.lastIndexOf(".")); // strip class name
@@ -815,8 +951,31 @@
    return path.replace("\\", "/");
  }
  private File getStubFile() {
    return new File(getProjectBase(), MESSAGES_FILE_STUB);
  /*
   * Returns the stub file ("resource/Messages.java.stub") from the appropriate
   * location: ant or jar file.
   */
  private InputStream getStubFile() {
    InputStream result = null;
    File stub = new File(getProjectBase(), MESSAGES_FILE_STUB);
    if ( stub.exists() ) {
      // this is the OpenDS's ant project calling
      // Stub is located at OPENDS_ROOT/resource/Messages.java.stub
      try {
        result = new FileInputStream(stub);
      } catch (FileNotFoundException e) {
        // should neven happen
        throw new BuildException("Unable to load template " +
              MESSAGES_FILE_STUB + ":  " + e.getMessage());
      }
    } else {
      // this is the example plugin's ant project calling
      // Stub is located at build-tools.jar:resource/Messages.java.stub
      result = getClass().getResourceAsStream(MESSAGES_FILE_STUB);
    }
    return result;
  }
  /**
opendj-sdk/opends/src/messages/src/org/opends/messages/Message.java
@@ -64,7 +64,7 @@
   * Creates an uninternationalized message that will render itself
   * the same way regardless of the locale requested in
   * <code>toString(Locale)</code>.  The message will have a
   * category of <code>Categore.USER_DEFINED</code> and a severity
   * category of <code>Category.USER_DEFINED</code> and a severity
   * of <code>Severity.INFORMATION</code>
   *
   * Note that the types for <code>args</code> must be consistent with any