J avolution v5.5 (J2SE 1.6+)

javolution.lang
Class Configurable<T>

java.lang.Object
  extended by javolution.lang.Configurable<T>

public class Configurable<T>
extends java.lang.Object

This class facilitates separation of concerns between the configuration logic and the application code.

Does your class need to know or has to assume that the configuration is coming from system properties ??

The response is obviously NO!

Let's compare the following examples:

      class Document {
          private static final Font DEFAULT_FONT
              = Font.decode(System.getProperty("DEFAULT_FONT") != null ?
                  System.getProperty("DEFAULT_FONT") : "Arial-BOLD-18");
          ...
      }
With the following (using this class):
      class Document {
          public static final Configurable<Font> DEFAULT_FONT
              = new Configurable<Font>(new Font("Arial", Font.BOLD, 18));
          ...
      }
Not only the second example is cleaner, but the actual configuration data can come from anywhere, for example from the OSGI Configuration Admin package (org.osgi.service.cm). Low level code does not need to know.

Configurable instances have the same textual representation as their current values. For example:

       public static final Configurable<String> AIRPORT_TABLE
            = new Configurable<String>("Airports");
       ...
       String sql = "SELECT * FROM " + AIRPORT_TABLE
           // AIRPORT_TABLE.get() is superfluous
           + " WHERE State = '" + state  + "'";

Unlike system properties (or any static mapping), configuration parameters may not be known until run-time or may change dynamically. They may depend upon the current run-time platform, the number of cpus, etc. Configuration parameters may also be retrieved from external resources such as databases, XML files, external servers, system properties, etc.

      public abstract class FastComparator<T> implements Comparator<T>, Serializable  {
          public static final Configurable<Boolean> REHASH_SYSTEM_HASHCODE
              = new Configurable<Boolean>(isPoorSystemHash()); // Test system hashcode.
      ...
      public abstract class ConcurrentContext extends Context {
          public static final Configurable<Integer> MAXIMUM_CONCURRENCY
              = new Configurable<Integer>(Runtime.getRuntime().availableProcessors() - 1) {};
                  // No algorithm parallelization on single-processor machines.
     ...
     public abstract class XMLInputFactory {
          public static final Configurable<Class<? extends XMLInputFactory>> CLASS
              = new Configurable<Class<? extends XMLInputFactory>>(XMLInputFactory.Default.class);
                  // Default class implementation is a private class.
     ...
     

Dynamic configuration is allowed/disallowed based upon the current {SecurityContext}. Configurables are automatically notified of any changes in their configuration values.

Unlike system properties, configurable can be used in applets or unsigned webstart applications.

Here is an example of configuration of a web application from a property file:

      public class Configuration implements ServletContextListener {
          public void contextInitialized(ServletContextEvent sce) {
              try {
                  ServletContext ctx = sce.getServletContext();
               
                  // Loads properties.
                  Properties properties = new Properties();
                  properties.load(ctx.getResourceAsStream("WEB-INF/config/configuration.properties"));
               
                  // Reads properties superceeding default values.
                  Configurable.read(properties);
                  
              } catch (Exception ex) {
                  LogContext.error(ex);
              }
          }
      }
This listener is registered in the web.xml file:
      <web-app>
          <listener>
              <listener-class>mypackage.Configuration</listener-class>
           </listener>
      </web-app>
The property file contains the full names of the configurable static fields and the textual representation of their new values:
      # File configuration.properties
      javolution.util.FastComparator#REHASH_SYSTEM_HASHCODE = true
      javolution.context.ConcurrentContext#MAXIMUM_CONCURRENCY = 0
      javolution.xml.stream.XMLInputFactory#CLASS = com.foo.bar.XMLInputFactoryImpl
      

Here is an example of reconfiguration from a xml file:

      FileInputStream xml = new FileInputStream("D:/configuration.xml");
      Configurable.read(xml);
and the configuration file:
      <?xml version="1.0" encoding="UTF-8" ?>
      <Configuration>
          <Configurable name="javolution.util.FastComparator#REHASH_SYSTEM_HASHCODE">
              <Value class="java.lang.Boolean" value="true"/>
          </Configurable>
          <Configurable name="javolution.context.ConcurrentContext#MAXIMUM_CONCURRENCY">
               <Value class="java.lang.Integer" value="0"/>
          </Configurable>
          <Configurable name="javolution.xml.stream.XMLInputFactory#CLASS">
               <Value class="java.lang.Class" value="com.foo.MyXMLInputFactory"/>
          </Configurable>
      </Configuration>

Version:
5.5, April 20, 2010
Author:
Jean-Marie Dautelle

Constructor Summary
Configurable(T defaultValue)
          Creates a new configurable having the specified default value.
 
Method Summary
static
<T> void
configure(Configurable<T> cfg, T newValue)
          Sets the run-time value of the specified configurable.
 T get()
          Returns the current value for this configurable.
 java.lang.Class getContainer()
          Returns the container class of this configurable (the class where this configurable is defined as a public static field.
 T getDefault()
          Returns the default value for this configurable.
static Configurable getInstance(java.lang.String name)
          Returns the configurable instance having the specified name.
 java.lang.String getName()
          Returns the field name of this configurable (for example "javolution.context.ConcurrentContext#MAXIMUM_CONCURRENCY") for ConcurrentContext.MAXIMUM_CONCURRENCY.
protected  void notifyChange(T oldValue, T newValue)
          Notifies this configurable that its runtime value is going to be changed.
static void read(java.io.InputStream inputStream)
          Convenience method to read configurable values from the specified XML stream.
static void read(java.util.Properties properties)
          Convenience method to read the specified properties and reconfigure accordingly.
 java.lang.String toString()
          Returns the string representation of the value of this configurable.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

Configurable

public Configurable(T defaultValue)
Creates a new configurable having the specified default value.

Parameters:
defaultValue - the default value.
Throws:
java.lang.IllegalArgumentException - if defaultValue is null.
Method Detail

get

public T get()
Returns the current value for this configurable.

Returns:
the current value (always different from null).

getDefault

public T getDefault()
Returns the default value for this configurable.

Returns:
the default value (always different from null).

getContainer

public java.lang.Class getContainer()
Returns the container class of this configurable (the class where this configurable is defined as a public static field.

Returns:
the container class or null if unknown (e.g. J2ME).

getName

public java.lang.String getName()
Returns the field name of this configurable (for example "javolution.context.ConcurrentContext#MAXIMUM_CONCURRENCY") for ConcurrentContext.MAXIMUM_CONCURRENCY.

Returns:
this configurable name or null if the name of this configurable is unknown (e.g. J2ME).

notifyChange

protected void notifyChange(T oldValue,
                            T newValue)
                     throws java.lang.UnsupportedOperationException
Notifies this configurable that its runtime value is going to be changed. The default implementation does nothing.

Parameters:
oldValue - the previous value.
newValue - the new value.
Throws:
java.lang.UnsupportedOperationException - if dynamic reconfiguration of this configurable is not allowed (regardless of the security context).

toString

public java.lang.String toString()
Returns the string representation of the value of this configurable.

Overrides:
toString in class java.lang.Object
Returns:
String.valueOf(this.get())

getInstance

public static Configurable getInstance(java.lang.String name)
Returns the configurable instance having the specified name. For example:
     Configurable cfg = Configurable.getInstance("javolution.context.ConcurrentContext#MAXIMUM_CONCURRENCY")
 
returns ConcurrentContext.MAXIMUM_CONCURRENCY.

Note: OSGI based framework should ensure that class loaders of configurable instances are known to the Reflection utility class.

Parameters:
name - the name of the configurable to retrieve.
Returns:
the corresponding configurable or null if it cannot be found.

configure

public static <T> void configure(Configurable<T> cfg,
                                 T newValue)
                      throws java.lang.SecurityException
Sets the run-time value of the specified configurable. If the configurable value is different from the previous one, then notifyChange(T, T) is called. This method raises a SecurityException if the specified configurable cannot be reconfigured.

Parameters:
cfg - the configurable being configured.
newValue - the new run-time value.
Throws:
java.lang.IllegalArgumentException - if value is null.
java.lang.SecurityException - if the specified configurable cannot be modified.

read

public static void read(java.util.Properties properties)
Convenience method to read the specified properties and reconfigure accordingly. For example:
     // Load configurables from system properties.
     Configurable.read(System.getProperties());
Configurables are identified by their field names. The textual representation of their value is defined by TextFormat.getInstance(Class) text format}. For example:
      javolution.util.FastComparator#REHASH_SYSTEM_HASHCODE = true
      javolution.context.ConcurrentContext#MAXIMUM_CONCURRENCY = 0
      javolution.xml.stream.XMLInputFactory#CLASS = com.foo.bar.XMLInputFactoryImpl
 
Conversion of String values to actual object is performed using TextFormat.getInstance(Class).

Note: OSGI based framework should ensure that class loaders of configurable instances are known to the Reflection utility class.

Parameters:
properties - the properties.

read

public static void read(java.io.InputStream inputStream)
Convenience method to read configurable values from the specified XML stream. This method uses Javolution XML facility to perform the deserialization. Here is an example of XML configuration file.
 <?xml version="1.0" encoding="UTF-8" ?>
 <Configuration>
     <Configurable name="javolution.util.FastComparator#REHASH_SYSTEM_HASHCODE">
          <Value class="java.lang.Boolean" value="true"/>
     </Configurable>
     <Configurable name="javolution.context.ConcurrentContext#MAXIMUM_CONCURRENCY">
          <Value class="java.lang.Integer" value="0"/>
     </Configurable>
     <Configurable name="javolution.xml.stream.XMLInputFactory#CLASS">
          <Value class="java.lang.Class" value="com.foo.MyXMLInputFactory"/>
     </Configurable>
 </Configuration>
It can be read directly with the following code:
 FileInputStream xml = new FileInputStream("D:/configuration.xml");
 Configurable.read(xml);

Note: OSGI based framework should ensure that class loaders of configurable instances are known to the Reflection utility.

Parameters:
inputStream - the input stream holding the xml configuration.

J avolution v5.5 (J2SE 1.6+)

Copyright © 2005 - 2009 Javolution.