peersim.config
Class Configuration

java.lang.Object
  extended by peersim.config.Configuration

public class Configuration
extends java.lang.Object

Fully static class to store configuration information. It defines a method, setConfig(Properties), to set configuration data. This method is called by the simulator engines as the very first thing they do. It can be called only once, after that the class becomes read only. All components can then access this configuration and utility methods to read property values based on their names.

The design of this class also hides the actual implementation of the configuration which can be Properties, XML, whatever. Currently only Properties is supported.

Apart from storing (name,value) pairs, this class also does some processing, and offers some utility functions. This extended functionality consists of the following: reading values with type checking, ordering of entries, pre-processing protocol names, parsing expressions, resolving underspecified classnames, and finally some basic debugging possibilities. We discuss these in the following.

Note that the configuration is initialized using a Properties object. The class of this object might implement some additional pre-processing on the file or provide an extended syntax for defining property files. See ParsedProperties for more details. This is the class that is currently used by simulation engines.

Typed reading of values

Properties can have arbitrary values of type String. This class offers a set of read methods that perform the appropriate conversion of the string value to the given type, eg long. They also allow for specifying default values in case the given property is not specified.

Resolving class names

The possibilities for the typed reading of a value includes interpreting the value as a class name. In this case an object will be constructed. It is described at method getInstance(String) how this is achieved exactly. What needs to be noted here is that the property value need not be a fully specified classname. It might contain only the short class name without the package specification. In this case, it is attempted to locate a class with that name in the classpath, and if a unique class is found, it will be used. This simplifies the configuration files and also allows to remove their dependence on the exact location of the class.

Components and their ordering

The idea of the configuration is that it mostly contains components and their descriptions (parameters). Although this class is blind to the semantics of these components, it offers some low level functionality that helps dealing with them. This functionality is based on the assumption that components have a type and a name. Both types and names are strings of alphanumeric and underscore characters. For example, "protocol" is a type, "foo" can be a name. Method getNames(java.lang.String) allow the caller to get the list of names for a given type. Some other methods, like getInstanceArray(java.lang.String) use this list to return a list of components.

Assuming the configuration is in Properties format (which is currently the only format available) component types and names are defined as follows. Property names containing two non-empty words separated by one dot (".") character are treated specially (the words contain word characters: alphanumeric and underscore ("_")). The first word will be the type, and the second is the name of a component. For example,

   control.conn ConnectivityObserver
   control.1 WireKOut
   control.2 PrintGraph
 
defines control components of names "conn","1" an "2" (arguments of the components not shown). When getNames(java.lang.String) or getInstanceArray(java.lang.String) are called, eg getNames("control"), then the order in which these are returned is alphabetical: ["control.1","control.2","control.conn"]. If you are not satisfied with lexicographic order, you can specify the order in this way.
   order.control 1,conn,2
 
where the names are separated by any non-word character (non alphanumeric or underscore). If not all names are listed then the given order is followed by alphabetical order of the rest of the items, e.g.
   order.control 2
 
results in ["control.2","control.1","control.conn"].

It is also possible to exclude elements from the list, while ordering them. The syntax is identical to that of the above, only the parameter name begins with include. For example

   include.control conn 2
 
will result in returning only control.conn and control.2, in this order. Note that for example the empty list results in a zero length array in this case. Important! If include is defined then ordering is ignored. That is, include is stronger than order.

Protocol names

As mentioned, the configuration is generally blind to the actual names of the components. There is an exception: the components of type "protocol". These are pre-processed a bit to enhance performance: protocol names are mapped to numeric protocol identifiers. The numeric identifier of a protocol is its index in the array returned by getNames(java.lang.String). See above how to control this order. The numeric identifiers then can be looked up based on the name and vice versa. Besides, the identifier can be directly requested based on a property name when the protocol name is the value of a property which is frequently the case.

Expressions

Numeric property values can be complex expressions, that are parsed using JEP. You can write expression using the syntax that you can find here. For example,
   MAG 2
   SIZE 2ˆMAG
 
SIZE=4. You can also have complex expression trees like this:
   A B+C
   B D+E
   C E+F
   D 1
   E F
   F 2
 
that results in A=7, B=3, C=4, D=1, E=2, F=2

Expressions like "sub-expression op sub-expression" are computed based on the type of the sub-expressions. If both sub-expressions are integer, the computation is done using integer arithmetics and the result is an integer. So, for example, 5/2 returns 2. If one of the sub-expression is floating point, the computation is based on floating-point arithmetics (double precision) and the result is a floating point value. So, for example, 5.0/2 returns 2.5.

Expressions are parsed recursively. Note that no optimization is done, so expression F is evaluated three times here (due to the fact that appears twice in C and once in B). But since properties are read just once at initialization, this is not a performance problem.

Finally, recursive definitions are not allowed (and without function definitions, they make no sense). Since it is difficult to discover complex recursive chains, a simple trick is used: if the depth of recursion is greater than a given threshold (configurable, currently 100, an error message is printed. This avoids to fill the stack, that results in an anonymous OutOfMemoryError. So, if you write

   overlay.size SIZE
   SIZE SIZE-1
 
you get an error message: Parameter "overlay.size": Probable recursive definition - exceeded maximum depth 100

Debug

It is possible to obtain debug information about the configuration properties by activating special configuration properties.

If property "debug.config" is defined, each config property and the associated value are printed. Properties that are not present in the config file but have default values are postfixed with the string "(DEFAULT)".

If property "debug.config" is defined and it is equal to "context", information about the configuration method invoked, and where this method is invoked, is also printed. If it is equal to "full", all the properties are printed, even if they are not read.

Each line printed by this debug feature is prefixed by the string "DEBUG".

Use of brackets

For the sake of completeness, we mention it here that if this class is initialized using ParsedProperties, then it is possible to use some more compressed format to specify the components. See ParsedProperties.load(java.lang.String).


Parameter Summary
debug.config
          The debug level for the configuration.
expressions.maxdepth
          The maximum depth for expressions.
order
          Used to configure ordering of the components.
include
          Used to configure ordering of the components.
 
Field Summary
static int DEFAULT_MAXDEPTH
          Default max depth limit to avoid recursive definitions
 
Method Summary
static boolean contains(java.lang.String name)
           
static boolean getBoolean(java.lang.String name)
          Reads given property.
static boolean getBoolean(java.lang.String name, boolean def)
          Reads given configuration property.
static java.lang.Class getClass(java.lang.String name)
          Reads given configuration property.
static java.lang.Class getClass(java.lang.String name, java.lang.Class def)
          Reads given configuration property.
static double getDouble(java.lang.String name)
          Reads given configuration property.
static double getDouble(java.lang.String name, double def)
          Reads given configuration property.
static java.lang.Object getInstance(java.lang.String name)
          Reads given configuration property for a class name.
static java.lang.Object getInstance(java.lang.String name, java.lang.Object def)
          Reads given configuration property for a class name.
static java.lang.Object[] getInstanceArray(java.lang.String name)
          It returns an array of class instances.
static int getInt(java.lang.String name)
          Reads given configuration property.
static int getInt(java.lang.String name, int def)
          Reads given configuration property.
static long getLong(java.lang.String name)
          Reads given configuration property.
static long getLong(java.lang.String name, long def)
          Reads given configuration property.
static java.lang.String[] getNames(java.lang.String name)
          Returns an array of names prefixed by the specified name.
static int getPid(java.lang.String name)
          Reads the given property from the configuration interpreting it as a protocol name.
static int getPid(java.lang.String name, int pid)
          Calls getPid(String), and returns the default if no property is defined with the given name.
static java.lang.String getString(java.lang.String name)
          Reads given configuration property.
static java.lang.String getString(java.lang.String name, java.lang.String def)
          Reads given configuration property.
static java.lang.String lookupPid(int pid)
          Returns the name of a protocol that has the given identifier.
static int lookupPid(java.lang.String protname)
          Returns the numeric protocol identifier of the given protocol name.
static void setConfig(java.util.Properties p)
          Sets the system-wide configuration in Properties format.
static void setConfig(java.util.Properties p, boolean check)
          Sets the system-wide configuration in Properties format.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Parameter Detail

debug.config

The debug level for the configuration. If defined, a line is printed for each configuration parameter read. If defined and equal to "context", additional context information for debug is printed. If defined and equal to "full", all the configuration properties are printed at the beginning, not just when they are called.


expressions.maxdepth

The maximum depth for expressions. This is a simple mechanism to avoid unbounded recursion. The default is 100, and you probably don't want to change it.


order

Used to configure ordering of the components. Determines the ordering in the array as returned by getNames(java.lang.String). See the general description of Configuration for details.


include

Used to configure ordering of the components. Determines the ordering in the array as returned by getNames(java.lang.String), and can bu used to also exclude elements. See the general description of Configuration for details.

Field Detail

DEFAULT_MAXDEPTH

public static final int DEFAULT_MAXDEPTH
Default max depth limit to avoid recursive definitions

See Also:
Constant Field Values
Method Detail

setConfig

public static void setConfig(java.util.Properties p)
Sets the system-wide configuration in Properties format. It can be called only once. After that the configuration becomes unmodifiable (read only). If modification is attempted, a RuntimeException is thrown and no change is made.

Parameters:
p - The Properties object containing configuration info

setConfig

public static void setConfig(java.util.Properties p,
                             boolean check)
Sets the system-wide configuration in Properties format. It can be called only once. After that the configuration becomes unmodifiable (read only). If modification is attempted, a RuntimeException is thrown and no change is made.

Parameters:
p - The Properties object containing configuration info

contains

public static boolean contains(java.lang.String name)
Returns:
true if and only if name is a specified (existing) property.

getBoolean

public static boolean getBoolean(java.lang.String name,
                                 boolean def)
Reads given configuration property. If not found, throws a MissingParameterException.

Parameters:
name - Name of configuration property
def - default value

getBoolean

public static boolean getBoolean(java.lang.String name)
Reads given property. If not found, or the value is empty string then throws a MissingParameterException. Empty string is not accepted as false due to the similar function of contains(java.lang.String) which returns true in that case. True is returned if the lowercase value of the property is "true", otherwise false is returned.

Parameters:
name - Name of configuration property

getInt

public static int getInt(java.lang.String name,
                         int def)
Reads given configuration property. If not found, returns the default value.

Parameters:
name - Name of configuration property
def - default value

getInt

public static int getInt(java.lang.String name)
Reads given configuration property. If not found, throws a MissingParameterException.

Parameters:
name - Name of configuration property

getLong

public static long getLong(java.lang.String name,
                           long def)
Reads given configuration property. If not found, returns the default value.

Parameters:
name - Name of configuration property
def - default value

getLong

public static long getLong(java.lang.String name)
Reads given configuration property. If not found, throws a MissingParameterException.

Parameters:
name - Name of configuration property

getDouble

public static double getDouble(java.lang.String name,
                               double def)
Reads given configuration property. If not found, returns the default value.

Parameters:
name - Name of configuration property
def - default value

getDouble

public static double getDouble(java.lang.String name)
Reads given configuration property. If not found, throws a MissingParameterException.

Parameters:
name - Name of configuration property

getString

public static java.lang.String getString(java.lang.String name,
                                         java.lang.String def)
Reads given configuration property. If not found, returns the default value.

Parameters:
name - Name of configuration property
def - default value

getString

public static java.lang.String getString(java.lang.String name)
Reads given configuration property. If not found, throws a MissingParameterException. Removes trailing whitespace characters.

Parameters:
name - Name of configuration property

getPid

public static int getPid(java.lang.String name)
Reads the given property from the configuration interpreting it as a protocol name. Returns the numeric protocol identifier of this protocol name. See the discussion of protocol name at Configuration for details on how this numeric id is calculated

Parameters:
name - Name of configuration property
Returns:
the numeric protocol identifier associated to the value of the property

getPid

public static int getPid(java.lang.String name,
                         int pid)
Calls getPid(String), and returns the default if no property is defined with the given name.

Parameters:
name - Name of configuration property
pid - the default protocol identifier
Returns:
the numeric protocol identifier associated to the value of the property, or the default if not defined

lookupPid

public static int lookupPid(java.lang.String protname)
Returns the numeric protocol identifier of the given protocol name.

Parameters:
protname - the protocol name.
Returns:
the numeric protocol identifier associated to the protocol name

lookupPid

public static java.lang.String lookupPid(int pid)
Returns the name of a protocol that has the given identifier.

Note that this is not a constant time operation in the number of protocols, although typically there are very few protocols defined.

Parameters:
pid - numeric protocol identifier.
Returns:
name of the protocol that has the given id. null if no protocols have the given id.

getClass

public static java.lang.Class getClass(java.lang.String name)
Reads given configuration property. If not found, throws a MissingParameterException. When creating the Class object, a few attempts are done to resolve the classname. See Configuration for details.

Parameters:
name - Name of configuration property

getClass

public static java.lang.Class getClass(java.lang.String name,
                                       java.lang.Class def)
Reads given configuration property. If not found, returns the default value.

Parameters:
name - Name of configuration property
def - default value
See Also:
getClass(String)

getInstance

public static java.lang.Object getInstance(java.lang.String name)
Reads given configuration property for a class name. It returns an instance of the class. The class must implement a constructor that takes a String as an argument. The value of this string will be name. The constructor of the class can see the configuration so it can make use of this name to read its own parameters from it.

Parameters:
name - Name of configuration property
Throws:
MissingParameterException - if the given property is not defined
IllegalParameterException - if there is any problem creating the instance

getInstance

public static java.lang.Object getInstance(java.lang.String name,
                                           java.lang.Object def)
Reads given configuration property for a class name. It returns an instance of the class. The class must implement a constructor that takes a String as an argument. The value of this string will be name. The constructor of the class can see the configuration so it can make use of this name to read its own parameters from it.

Parameters:
name - Name of configuration property
def - The default object that is returned if there is no property defined with the given name
Throws:
IllegalParameterException - if the given name is defined but there is a problem creating the instance.

getInstanceArray

public static java.lang.Object[] getInstanceArray(java.lang.String name)
It returns an array of class instances. The instances are constructed by calling getInstance(String) on the names returned by getNames(String).

Parameters:
name - The component type (i.e. prefix of the list of configuration properties) which will be passed to getNames(String).

getNames

public static java.lang.String[] getNames(java.lang.String name)
Returns an array of names prefixed by the specified name. The array is sorted as follows. If there is no config entry "include"+"."+name or "order"+"."+name then the order is alphabetical. Otherwise this entry defines the order. For more information see Configuration.

Parameters:
name - the component type (i.e., the prefix)
Returns:
the full property names in the order specified by the configuration