javolution.lang
Class Configurable<T>
java.lang.Object
javolution.lang.Configurable<T>
public abstract 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 DEFAULT_FONT
= new Configurable(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 AIRPORT_TABLE
= new Configurable("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 implements Comparator, Serializable {
public static final Configurable REHASH_SYSTEM_HASHCODE
= new Configurable(isPoorSystemHash()) {}; // Test system hashcode.
...
public abstract class ConcurrentContext extends Context {
public static final Configurable MAXIMUM_CONCURRENCY
= new Configurable(Runtime.getRuntime().availableProcessors() - 1) {};
// No algorithm parallelization on single-processor machines.
...
public abstract class XMLInputFactory {
public static final Configurable> CLASS
= new Configurable>(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("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" name="com.foo.MyXMLInputFactory"/>
</Configurable>
</Configuration>
- Version:
- 5.4, November 2, 2009
- Author:
- Jean-Marie Dautelle
Constructor Summary |
Configurable(T defaultValue)
Creates a new configurable having the specified default value. |
Method Summary |
static
|
configure(Configurable<T> cfg,
T newValue)
Sets the run-time value of the specified configurable. |
T |
get()
Returns the current value for this configurable. |
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.
// Load configurables from system properties.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE> java.lang.String</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../javolution/lang/Configurable.html#toString()">toString</A></B>()</CODE>
<BR>
Returns the string representation of the value of this configurable.</TD>
</TR>
</TABLE>
<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
<TH ALIGN="left"><B>Methods inherited from class java.lang.Object</B></TH>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait</CODE></TD>
</TR>
</TABLE>
<P>
<!-- ========= CONSTRUCTOR DETAIL ======== -->
<A NAME="constructor_detail"><!-- --></A>
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
<B>Constructor Detail</B></FONT></TH>
</TR>
</TABLE>
<A NAME="Configurable(java.lang.Object)"><!-- --></A><A NAME="Configurable(T)"><!-- --></A><H3>
Configurable</H3>
<PRE>
public <B>Configurable</B>(<A HREF="../../javolution/lang/Configurable.html" title="type parameter in Configurable">T</A> defaultValue)</PRE>
<DL>
<DD>Creates a new configurable having the specified default value.
<P>
<DL>
<DT><B>Parameters:</B><DD><CODE>defaultValue</CODE> - the default value.
<DT><B>Throws:</B>
<DD><CODE>java.lang.IllegalArgumentException</CODE> - if <code>defaultValue</code> is
<code>null</code>.</DL>
</DL>
<!-- ============ METHOD DETAIL ========== -->
<A NAME="method_detail"><!-- --></A>
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
<B>Method Detail</B></FONT></TH>
</TR>
</TABLE>
<A NAME="get()"><!-- --></A><H3>
get</H3>
<PRE>
public <A HREF="../../javolution/lang/Configurable.html" title="type parameter in Configurable">T</A> <B>get</B>()</PRE>
<DL>
<DD>Returns the current value for this configurable.
<P>
<DD><DL>
<DT><B>Returns:</B><DD>the current value (always different from <code>null</code>).</DL>
</DD>
</DL>
<HR>
<A NAME="getDefault()"><!-- --></A><H3>
getDefault</H3>
<PRE>
public <A HREF="../../javolution/lang/Configurable.html" title="type parameter in Configurable">T</A> <B>getDefault</B>()</PRE>
<DL>
<DD>Returns the default value for this configurable.
<P>
<DD><DL>
<DT><B>Returns:</B><DD>the default value (always different from <code>null</code>).</DL>
</DD>
</DL>
<HR>
<A NAME="notifyChange(java.lang.Object,java.lang.Object)"><!-- --></A><A NAME="notifyChange(T, T)"><!-- --></A><H3>
notifyChange</H3>
<PRE>
protected void <B>notifyChange</B>(<A HREF="../../javolution/lang/Configurable.html" title="type parameter in Configurable">T</A> oldValue,
<A HREF="../../javolution/lang/Configurable.html" title="type parameter in Configurable">T</A> newValue)
throws java.lang.UnsupportedOperationException</PRE>
<DL>
<DD>Notifies this configurable that its runtime value is going to be changed.
The default implementation does nothing.
<P>
<DD><DL>
<DT><B>Parameters:</B><DD><CODE>oldValue</CODE> - the previous value.<DD><CODE>newValue</CODE> - the new value.
<DT><B>Throws:</B>
<DD><CODE>java.lang.UnsupportedOperationException</CODE> - if dynamic reconfiguration of
this configurable is not allowed (regardless of the security
context).</DL>
</DD>
</DL>
<HR>
<A NAME="toString()"><!-- --></A><H3>
toString</H3>
<PRE>
public java.lang.String <B>toString</B>()</PRE>
<DL>
<DD>Returns the string representation of the value of this configurable.
<P>
<DD><DL>
<DT><B>Overrides:</B><DD><CODE>toString</CODE> in class <CODE>java.lang.Object</CODE></DL>
</DD>
<DD><DL>
<DT><B>Returns:</B><DD><code>String.valueOf(this.get())</code></DL>
</DD>
</DL>
<HR>
<A NAME="getName()"><!-- --></A><H3>
getName</H3>
<PRE>
public java.lang.String <B>getName</B>()</PRE>
<DL>
<DD>Returns the field name of this configurable (for example <code>
"javolution.context.ConcurrentContext#MAXIMUM_CONCURRENCY"</code>)
for <A HREF="../../javolution/context/ConcurrentContext.html#MAXIMUM_CONCURRENCY"><CODE>ConcurrentContext.MAXIMUM_CONCURRENCY</CODE></A>.
<P>
<DD><DL>
<DT><B>Returns:</B><DD>this configurable name or <code>null</code> if the name
of this configurable is unknown (e.g. J2ME).</DL>
</DD>
</DL>
<HR>
<A NAME="getInstance(java.lang.String)"><!-- --></A><H3>
getInstance</H3>
<PRE>
public static <A HREF="../../javolution/lang/Configurable.html" title="class in javolution.lang">Configurable</A> <B>getInstance</B>(java.lang.String name)</PRE>
<DL>
<DD>Returns the configurable instance having the specified name.
For example:[code]
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 (e.g..
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.
// 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.
- Throws:
java.lang.UnsupportedOperationException - on J2ME
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" name="com.foo.MyXMLInputFactory"/>
</Configurable>
</Configuration>
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.
Copyright © 2005 - 2009 Javolution.
|