Configuration script files

The Configure tool uses a "script" to tell it what configuration options to capture, how to capture them and where to put them. Here is a simple example illustrating the basic structure of a script file:

<configureScript>
  <type name="integer.type" pattern="[0-9]+"/>
  <type name="yesno.type">
    <alt value="yes"/>
    <alt value="no"/>
  </type>

  <propFile name="test.properties">
    <property name="prop1" type="integer.type"
              description="Enter an integer"
              default="0"/>
    <property name="prop2" type="yesno.type"
              description="Do you want to?"
              default="no"/>
  </propFile>

  <screen title="Testing set 1">
    <item property="prop1"/>
    <item property="prop2"/>
  </screen>
</configureScript>

The main elements of a script are "types", "property sets" and "screens". Lets describe these in that order.

A "type" element introduces a property type which defines a set of allowed values for properties specified later in the script file. A property type's value set can be defined using a regular expression (pattern) or by listing the value set. For more details refer to the "Specifying property types" page.

A "propFile" element introduces a property set consisting of the properties to be written to a given property file. Each property in the property set is specified in terms of a property name and a previously defined type, together with a (one line) description and an optional default value. For more details refer to the "Specifying property files" page.

A "screen" element defines the dialog sequence that is used to request configuration properties from the user. The screen consists of a list of properties, together with (multi-line) explanations to be displayed to the user. For more details refer to the "Specifying property screens" page.

Finally, the "Advanced features" page describes the control properties and the import mechanism.

Specifying property types

Configuration property types define sets of allowable values that can be used in values defined elsewhere in a script file. A property type can be defined either using a regular expression or by listing the set of allowable values. For example:

  <type name="integer.type" pattern="[0-9]+"/>
  <type name="yesno.type">
    <alt value="yes"/>
    <alt value="no"/>
  </type>

The first "type" element defines a type whose values are unsigned integer literals. The second one defines a type that can take the value "yes" or "no".

In both cases, the value sets are modeled in terms of the "token" character sequences that are entered by the user and the "value" character sequences that are written to the property files. For a property types specified using regular expressions, the "token" and "value" sequences are the same, with one exception. The exception is that a sequence of zero characters is not a valid input token. So if the "pattern" could match an empty token, you must define an "emptyToken" that the user will use to enter this value. For example, the following defines a variant of the previous "integer.type" in which the token "none" is used to specify that the corresponding property should have an empty value:

  <type name="optinteger.type" 
        pattern="[0-9]*" emptyToken="none"/>

For property types specified by listing the values, you can make the tokens and values different for any pair. For example:

  <type name="yesno.type">
    <alt token="oui" value="yes"/>
    <alt token="non" value="no"/>
  </type>

Type values and tokens can contain just about any printable character (modulo the issue of zero length tokens). Type names however are restricted to ASCII letters, digits, '.', '-' and '_'.

Specifying property files

A "propFile" element in a script file specifies details about a file to which configuration properties will be written. In the simplest case, a "propFile" element specifies a file name and a set of properties to be written. For example:

  <propFile fileName="jnode.properties">
    <property name="jnode.vm.size"
                 type="integer.type"
                 description="Enter VM size in Mbytes"
                 default="512"/>
    <property name="jnode.vdisk.enabled" type="yesNo.type"
              description="Configure a virtual disk"
              default="no"/>
  </propFile<

This specifies a classic Java properties file called "jnode.properties" which will contain two properties. The "jnode.vm.size" property will have a value that matches the type named "integer.type", with a default value of "512". The "jnode.vdisk.enabled" will have a value that matches the "yesno.type", defaulting to "no".

The Configure tool will act as follows for the example above.

  1. It will test to see if the "jnode.properties" file exists in the same directory as the script file.
  2. If the file exists, it will be read using the java.util.Properties.load method, and the in-memory property set will be populated from the corresponding properties.
  3. If the property file does not exist, the in-memory property set will be populated from the "default" attributes.
  4. The "screen" elements will be processed as described in the "" page to capture new property values.
  5. Finally, the "jnode.properties" file will be created or updated using the java.util.Properties.save method.

Attributes of a "property" element
Each "property" element can have the following attributes:

name
This attribute gives the name of the property. Property names should be restricted to ASCII letters, digits, '-', '-' and '_'. This attribute is mandatory.
type
This attribute gives the name of the property's type. This attribute is mandatory.
description
This attribute gives a short (20 chars or so) description of the property that will be included in the prompt for the property's value. This attribute is mandatory.
default
This attribute gives a default value for the property if none is supplied by other mechanisms. This attribute is optional, but if present it must contain a valid value for the property's type.

Attributes of a "propFile" element
The Configure tool will read and write properties in different ways depending on the "propFile" element's attributes:

fileName
This attribute specifies the name of the file to be written. Depending on the other attributes, it may also be a source of default values. This attribute is mandatory.
fileFormat
This attribute specifies various alternative file formats. Possible values are listed below.
defaultFile
This attribute specifies that default property values should be loaded from a default property file.
templateFile
This attribute specifies that the output file should be written by expanding the supplied template file, as described below.
marker
This attribute specifies an alternative marker character for template expansion; the default is '@'.

Alternative file formats

As described above, the Configure tool supports five different file types: more if you use plugin classes. These are as follows:

"properties"
This denotes a classic Java properties file, as documented in the Sun javadocs for the java.util.Properties class.
"xmlProperties"
This denotes a XML Java properties file, as documented in the Sun javadocs for the java.util.Prfoperties class (Java 1.5 or later).
"xml"
This denotes an XML file whose structure is not known.
"java"
This denotes a Java source code file.
"text"
This denotes an arbitrary text file.
other
org.jnode.configure.adapter.FileAdapter class. The behavior is as described below

The file types "xml", "java" and "text" require the use of a template file, and do not permit properties to be loaded.

Template file expansion

If Configure uses a java.util.Properties.saveXXX method to write properties, you do not have a great deal of control over how the file is generated. For example, you cannot include comments for each property, and you cannot control the order of the properties.

The alternative is to create a template of a file that you want the Configure tool to add properties to. Here is a simple example:

# This file contains some interesting properties

# The following property is interesting
interesting=@interesting@

# The following property is not at all interesting
boring=@boring@

If the file above is specified as the "templateFile" for a property set that includes the "interesting" and "boring" properties, the Configure tool will output the property set by expanding the template to replace "@interesting@" and "@boring@" with the corresponding property values.

The general syntax for @...@ sequences is:

    at_sequence ::= '@' name [ '/' modifiers ] '@'
    name        ::= ... # any valid property name
    modifiers   ::= ... # one or more modifier chars

The template expansion process replaces @...@ sequences as follows:

  • If the <name> matches a property name in the property set, the sequence is replaced with the named property's value, rewritten as described below.
  • If the @<name>@ does not match a property name in the property set, the sequence is replaced with an empty string. (This is a change from early versions of the tool which left sequence unchanged.)
  • The sequence @@ is replaced a single '@' character.
  • It is an error for an "opening" @ to not have a "closing" @ on the same line.

The template expansion is aware of the type of the file being expanded, and performs file-type specific escaping of properties before writing them to the output stream:

  • The expander for a "properties" file escapes the value according to the Java property file syntax. Three <modifier> values are supported:
    • The '=' modifier causes the property name and value to be expanded; i.e. "<name>=<value>" where the name and value parts are suitably escaped.
    • The '!' modifier (with '=') causes an empty property value to be suppressed by replacing the @...@ sequence with an empty string.
    • The '#' modifier (with '=') causes an empty property value to be commented out; i.e. "# <name>=<value>"
  • The expanders for "xmlProperties" and "xml" files escapes the value so that it can be embedded in the text content of an element.
  • The expander for "java" files outputs the value with Java string literal escapes.

Specifying property screens

The "dialog" between the Configure tool and the user is organized into sequences of questions called screens. Each screen is a described by a "screen" element in the configuration script. Here is a typical example:

  <screen title="Main JNode Build Settings">
    <item property="jnode.virt.platform">
The JNode build can generate config files for use with
various virtualization products.
    </item>
    <item property="expert.mode">
Some JNode build settings should only be used by experts.
    </item>
  </screen>

When the Configure tool processes a screen, it first outputs the screen's "title" and then iterates over the "item" elements in the screen. For each item, the tool outputs the multi-line content of the item, followed by a prompt formed from the designated property's description, type and default value. The user can enter a value, or just hit ENTER to accept the default. If the value entered by the user is acceptable, the Configure tool moves to the next item in the screen. If not, the prompt is repeated.

Conditional Screens

The screen mechanism allows you to structure the property capture dialog(s) independently of the property files. But the real power of this mechanism is that screens can be made conditional on properties captured by other screens. For example:

  <screen title="Virtualization Platform Settings"
          guardProp="jnode.virt.platform" valueIsNot="none">
    <item property="jnode.vm.size">
You can specify the memory size for the virtual PC.  
We recommended a memory size of least 512 Mbytes.
    </item>
    <item property="jnode.virtual.disk">
Select a disk image to be mounted as a virtual hard drive.
    </item>
  </screen>

This screen is controlled by the state of a guard property; viz the "guardProp" attribute. In this case, the "valueIsNot" attribute says that property needs to be set to some value other than "none" for the screen to be acted on. (There is also a "valueIs" attribute with an analogous meaning.)

The Configuration tool uses an algorithm equivalent to the following one to decide which screen to process next:

  1. The tool builds a work-list of the screens in the script. The screens are added to the list in the order that they are encountered by the script file parser.
  2. To find the next screen, the tool iterates over the work list entries, looking for the screen one that satisfies one of the following criteria:
    • a screen with no guard property, or
    • a screen with whose guard property has been set, and
      • has a "valueIs" attribute whose value equals the guard property's value, or
      • has a "valueIsNot" atttibute whose value does not equal the guard property's value.
  3. The selected screen is then removed from the work-list and processed as described previously.
  4. To select the next screen, the tool goes back to step 2), repeating until either the work-list is empty, or none of the remaining screens satisfy the criteria.

Advanced features

The "changed" attribute
The "item" element of a screen can take an attribute called "changed". If present, this contains a message that will be displayed after a property is captured if the new value is different from the previous (or default) value. For example, it can be used to remind the user to do a full rebuild when critical parameters are changed.