You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2006/01/14 22:31:23 UTC

svn commit: r369099 [4/5] - in /geronimo/trunk: assemblies/j2ee-installer/ assemblies/j2ee-installer/src/izpack/ assemblies/j2ee-installer/src/var/config/ modules/installer-processing/ modules/installer-processing/src/ modules/installer-processing/src/...

Added: geronimo/trunk/modules/installer-support/src/java/com/izforge/izpack/panels/ValidatePackSelections.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/installer-support/src/java/com/izforge/izpack/panels/ValidatePackSelections.java?rev=369099&view=auto
==============================================================================
--- geronimo/trunk/modules/installer-support/src/java/com/izforge/izpack/panels/ValidatePackSelections.java (added)
+++ geronimo/trunk/modules/installer-support/src/java/com/izforge/izpack/panels/ValidatePackSelections.java Sat Jan 14 13:31:11 2006
@@ -0,0 +1,3152 @@
+/*
+Apache 2.0 license
+Geronimo
+
+IzPack Panel extension for Geronimo installer
+  Adapted from...
+ * IzPack - Copyright 2001-2005 Julien Ponge, All Rights Reserved.
+ *
+ * http://www.izforge.com/izpack/
+ * http://developer.berlios.de/projects/izpack/
+ *
+ * Copyright 2003 Jonathan Halliday
+ * Copyright 2002 Elmar Grom
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *     
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+package com.izforge.izpack.panels;
+import com.izforge.izpack.Pack;
+import com.izforge.izpack.util.Debug;
+import com.izforge.izpack.installer.IzPanel;
+import com.izforge.izpack.installer.InstallData;
+import com.izforge.izpack.installer.InstallerFrame;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JPasswordField;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemListener;
+import java.awt.event.ItemEvent;
+import java.io.File;
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.Set;
+import java.util.List;
+
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+
+import net.n3.nanoxml.NonValidator;
+import net.n3.nanoxml.StdXMLBuilder;
+import net.n3.nanoxml.StdXMLParser;
+import net.n3.nanoxml.StdXMLReader;
+import net.n3.nanoxml.XMLElement;
+
+import com.izforge.izpack.LocaleDatabase;
+import com.izforge.izpack.Pack;
+import com.izforge.izpack.gui.ButtonFactory;
+import com.izforge.izpack.gui.TwoColumnConstraints;
+import com.izforge.izpack.gui.TwoColumnLayout;
+import com.izforge.izpack.installer.InstallData;
+import com.izforge.izpack.installer.InstallerFrame;
+import com.izforge.izpack.installer.IzPanel;
+import com.izforge.izpack.installer.ResourceManager;
+import com.izforge.izpack.util.MultiLineLabel;
+import com.izforge.izpack.util.OsConstraint;
+import com.izforge.izpack.util.OsVersion;
+import com.izforge.izpack.util.VariableSubstitutor;
+
+public class ValidatePackSelections extends IzPanel {
+   protected   String sTitle = null; // panel title
+   protected   GeronimoConfigProcessor gcp = null;
+   protected void setTitle( String title ) {
+      sTitle = title;
+   }
+   protected String getTitle() {
+      return sTitle;
+   }
+
+/*---------------------------------------------------------------------------*/
+/**
+ * This panel is designed to collect user input during the installation process. The panel is
+ * initially blank and is populated with input elements based on the XML specification in a resource
+ * file.
+ * 
+ * 
+ * @version 0.0.1 / 10/19/02
+ * @author getDirectoryCreated
+ */
+/*---------------------------------------------------------------------------*/
+/*
+ * $ @design
+ * 
+ * Each field is specified in its own node, containing attributes and data. When this class is
+ * instantiated, the specification is read and analyzed. Each field node is processed based on its
+ * type. An specialized member function is called for each field type that creates the necessary UI
+ * elements. All UI elements are stored in the uiElements vector. Elements are packaged in an object
+ * array that must follow this pattern:
+ * 
+ * index 0 - a String object, that specifies the field type. This is identical to the string used to
+ * identify the field type in the XML file. index 1 - a String object that contains the variable
+ * name for substitution. index 2 - the constraints object that should be used for positioning the
+ * UI element index 3 - the UI element itself index 4 - a Vector containg a list of pack for which
+ * the item should be created. This is used by buildUI() to decide if the item should be added to
+ * the UI.
+ * 
+ * In some cases additional entries are used. The use depends on the specific needs of the type of
+ * input field.
+ * 
+ * When the panel is activated, the method buildUI() walks the list of UI elements adds them to the
+ * panel together with the matching constraint.
+ * 
+ * When an attempt is made to move on to another panel, the method readInput() walks the list of UI
+ * elements again and calls specialized methods that know how to read the user input from each of
+ * the UI elemnts and set the associated varaible.
+ * 
+ * The actual variable substitution is not performed by this panel but by the variable substitutor.
+ * 
+ * To Do: ------ * make sure all header documentation is complete and correct
+ * --------------------------------------------------------------------------
+ */
+
+    // ------------------------------------------------------------------------
+    // Constant Definitions
+    // ------------------------------------------------------------------------
+
+    // The constants beginning with 'POS_' define locations in the object arrays
+    // that used to hold all information for the individual fields. Some data is
+    // not required for all field types. If this happens withing the array, that
+    // location must be padded with 'null'. At the end of the array it can be
+    // omitted. The data stored in this way is in most cases only known by
+    // convention between the add and the associated read method. the following
+    // positions are also used by other service methods in this class and must
+    // not be used for other purposes:
+    // - POS_DISPLAYED
+    // - POS_TYPE
+    // - POS_CONSTRAINTS
+    // - POS_PACKS
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 3257850965439886129L;
+
+    protected static final int POS_DISPLAYED = 0;
+
+    protected static final int POS_TYPE = 1;
+
+    protected static final int POS_VARIABLE = 2;
+
+    protected static final int POS_CONSTRAINTS = 3;
+
+    protected static final int POS_FIELD = 4;
+
+    protected static final int POS_PACKS = 5;
+
+    protected static final int POS_OS = 6;
+
+    protected static final int POS_TRUE = 7;
+
+    protected static final int POS_FALSE = 8;
+
+    protected static final int POS_MESSAGE = 9;
+
+    protected static final int POS_GROUP = 10;
+
+    protected static final int POS_ID = 11; 
+
+    /** The name of the XML file that specifies the panel layout */
+    protected static final String SPEC_FILE_NAME = "userInputSpec.xml";
+
+    protected static final String LANG_FILE_NAME = "userInputLang.xml";
+
+    /** how the spec node for a specific panel is identified */
+    protected static final String NODE_ID = "panel";
+
+    protected static final String FIELD_NODE_ID = "field";
+
+    protected static final String INSTANCE_IDENTIFIER = "order";
+
+    protected static final String TYPE = "type";
+
+    protected static final String DESCRIPTION = "description";
+
+    protected static final String VARIABLE = "variable";
+
+    protected static final String TEXT = "txt";
+
+    protected static final String KEY = "id";
+
+    protected static final String SPEC = "spec";
+
+    protected static final String SET = "set";
+
+    protected static final String TRUE = "true";
+
+    protected static final String FALSE = "false";
+
+    protected static final String ALIGNMENT = "align";
+
+    protected static final String LEFT = "left";
+
+    protected static final String CENTER = "center";
+
+    protected static final String RIGHT = "right";
+
+    protected static final String TOP = "top";
+
+    protected static final String ITALICS = "italic";
+
+    protected static final String BOLD = "bold";
+
+    protected static final String SIZE = "size";
+
+    protected static final String VALIDATOR = "validator";
+
+    protected static final String PROCESSOR = "processor";
+
+    protected static final String CLASS = "class";
+
+    protected static final String FIELD_LABEL = "label";
+
+    protected static final String TITLE_FIELD = "title";
+
+    protected static final String TEXT_FIELD = "text";
+
+    protected static final String TEXT_SIZE = "size";
+
+    protected static final String STATIC_TEXT = "staticText";
+
+    protected static final String COMBO_FIELD = "combo";
+
+    protected static final String COMBO_CHOICE = "choice";
+
+    protected static final String COMBO_VALUE = "value";
+
+    protected static final String RADIO_FIELD = "radio";
+
+    protected static final String RADIO_CHOICE = "choice";
+
+    protected static final String RADIO_VALUE = "value";
+
+    protected static final String SPACE_FIELD = "space";
+
+    protected static final String DIVIDER_FIELD = "divider";
+
+    protected static final String CHECK_FIELD = "check";
+
+    protected static final String RULE_FIELD = "rule";
+
+    protected static final String RULE_LAYOUT = "layout";
+
+    protected static final String RULE_SEPARATOR = "separator";
+
+    protected static final String RULE_RESULT_FORMAT = "resultFormat";
+
+    protected static final String RULE_PLAIN_STRING = "plainString";
+
+    protected static final String RULE_DISPLAY_FORMAT = "displayFormat";
+
+    protected static final String RULE_SPECIAL_SEPARATOR = "specialSeparator";
+
+    protected static final String RULE_ENCRYPTED = "processed";
+
+    protected static final String RULE_PARAM_NAME = "name";
+
+    protected static final String RULE_PARAM_VALUE = "value";
+
+    protected static final String RULE_PARAM = "param";
+
+    protected static final String PWD_FIELD = "password";
+
+    protected static final String PWD_INPUT = "pwd";
+
+    protected static final String PWD_SIZE = "size";
+
+    protected static final String SEARCH_FIELD = "search";
+
+    // internal value for the button used to trigger autodetection
+    protected static final String SEARCH_BUTTON_FIELD = "autodetect";
+
+    protected static final String SEARCH_CHOICE = "choice";
+
+    protected static final String SEARCH_FILENAME = "filename";
+
+    protected static final String SEARCH_RESULT = "result";
+
+    protected static final String SEARCH_VALUE = "value";
+
+    protected static final String SEARCH_TYPE = "type";
+
+    protected static final String SEARCH_FILE = "file";
+
+    protected static final String SEARCH_DIRECTORY = "directory";
+
+    protected static final String SEARCH_PARENTDIR = "parentdir";
+
+    protected static final String SEARCH_CHECKFILENAME = "checkfilename";
+
+    protected static final String SELECTEDPACKS = "createForPack"; // renamed
+
+    protected static final String UNSELECTEDPACKS = "createForUnselectedPack"; // new
+
+    // node
+
+    protected static final String NAME = "name";
+
+    protected static final String OS = "os";
+
+    protected static final String FAMILY = "family";
+
+    protected static final String DEPENDS = "depends";
+    protected static final String EXCLUSIVE = "exclusiveOf";
+    protected static final String AUTO_INSTALL = "AutomatedInstallation";
+    protected static final String SELECTED_PACKS = "selected";
+    protected static final String PANEL_PKG = "com.izforge.izpack.panels";
+    protected static final String PACKS_PANEL = "ImgPacksPanel";
+    // ------------------------------------------------------------------------
+    // Variable Declarations
+    // ------------------------------------------------------------------------
+    protected static HashMap varMap = new HashMap(); //###ead
+    protected static boolean fStaticInitComplete = false; //###ead
+
+    protected static int instanceCount = 0;
+
+    protected int instanceNumber = 0;
+
+    protected boolean fInitComplete = false; //###ead used for one time init in buildUI for each panel
+    /**
+     * If there is a possibility that some UI elements will not get added we can not allow to go
+     * back to the PacksPanel, because the process of building the UI is not reversable. This
+     * variable keeps track if any packs have been defined and will be used to make a decision for
+     * locking the 'previous' button.
+     */
+    protected boolean packsDefined = false;
+
+    protected InstallerFrame parentFrame;
+
+    /** The parsed result from reading the XML specification from the file */
+    protected XMLElement spec;
+
+    protected boolean haveSpec = false;
+
+    /** Holds the references to all of the UI elements */
+    protected Vector uiElements = new Vector();
+
+    /** Holds the references to all radio button groups */
+    protected Vector buttonGroups = new Vector();
+
+    /** Holds the references to all password field groups */
+    protected Vector passwordGroups = new Vector();
+
+    /**
+     * used for temporary storage of references to password groups that have already been read in a
+     * given read cycle.
+     */
+    protected Vector passwordGroupsRead = new Vector();
+
+    /** Used to track search fields. Contains SearchField references. */
+    protected Vector searchFields = new Vector();
+
+    /** Holds all user inputs for use in automated installation */
+    protected Vector entries = new Vector();
+
+    protected TwoColumnLayout layout;
+
+    protected LocaleDatabase langpack = null;
+
+    /*--------------------------------------------------------------------------*/
+    // This method can be used to search for layout problems. If this class is
+    // compiled with this method uncommented, the layout guides will be shown
+    // on the panel, making it possible to see if all components are placed
+    // correctly.
+    /*--------------------------------------------------------------------------*/
+    // public void paint (Graphics graphics)
+    // {
+    // super.paint (graphics);
+    // layout.showRules ((Graphics2D)graphics, Color.red);
+    // }
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Constructs a <code>UserInputPanel</code>.
+     * 
+     * @param parent reference to the application frame
+     * @param installData shared information about the installation
+     */
+    /*--------------------------------------------------------------------------*/
+    public ValidatePackSelections(InstallerFrame parent, InstallData installData)
+
+    {
+        super(parent, installData);
+
+        instanceNumber = instanceCount++;
+        this.parentFrame = parent;
+
+        gcp = new GeronimoConfigProcessor();
+        // ----------------------------------------------------
+        // ----------------------------------------------------
+        layout = new TwoColumnLayout(10, 5, 30, 25, TwoColumnLayout.LEFT);
+        setLayout(layout);
+
+        // ----------------------------------------------------
+        // get a locale database
+        // ----------------------------------------------------
+        try
+        {
+            // this.langpack = parent.langpack;
+
+            String resource = LANG_FILE_NAME + "_" + idata.localeISO3;
+            this.langpack = new LocaleDatabase(ResourceManager.getInstance().getInputStream(
+                    resource));
+        }
+        catch (Throwable exception)
+        {}
+
+        // ----------------------------------------------------
+        // read the specifications
+        // ----------------------------------------------------
+        try
+        {
+            readSpec();
+        }
+        catch (Throwable exception)
+        {
+            // log the problem
+            exception.printStackTrace();
+        }
+
+        if (!haveSpec)
+        {
+            // return if we could not read the spec. further
+            // processing will only lead to problems. In this
+            // case we must skip the panel when it gets activated.
+            return;
+        }
+        // ----------------------------------------------------
+        // process all field nodes. Each field node is analyzed
+        // for its type, then an appropriate memeber function
+        // is called that will create the correct UI elements.
+        // ----------------------------------------------------
+        Vector fields = spec.getChildrenNamed(FIELD_NODE_ID);
+
+        for (int i = 0; i < fields.size(); i++)
+        {
+            XMLElement field = (XMLElement) fields.elementAt(i);
+            String attribute = field.getAttribute(TYPE);
+
+            if (attribute != null)
+            {
+                if (attribute.equals(RULE_FIELD))
+                {
+                    addRuleField(field);
+                }
+                else if (attribute.equals(TEXT_FIELD))
+                {
+                    addTextField(field);
+                }
+                else if (attribute.equals(COMBO_FIELD))
+                {
+                    addComboBox(field);
+                }
+                else if (attribute.equals(RADIO_FIELD))
+                {
+                    addRadioButton(field);
+                }
+                else if (attribute.equals(PWD_FIELD))
+                {
+                    addPasswordField(field);
+                }
+                else if (attribute.equals(SPACE_FIELD))
+                {
+                    addSpace(field);
+                }
+                else if (attribute.equals(DIVIDER_FIELD))
+                {
+                    addDivider(field);
+                }
+                else if (attribute.equals(CHECK_FIELD))
+                {
+                    addCheckBox(field);
+                }
+                else if (attribute.equals(STATIC_TEXT))
+                {
+                    addText(field);
+                }
+                else if (attribute.equals(TITLE_FIELD))
+                {
+                    addTitle(field);
+                }
+                else if (attribute.equals(SEARCH_FIELD))
+                {
+                    addSearch(field);
+                }
+            }
+        }
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Indicates wether the panel has been validated or not. The installer won't let the user go
+     * further through the installation process until the panel is validated. Default behavior is to
+     * return true.
+     * 
+     * @return A boolean stating wether the panel has been validated or not.
+     */
+    /*--------------------------------------------------------------------------*/
+
+    public boolean isValidated()
+    {
+      String panelName = getTitle();
+      return  (readInput()  && gcp.checkInput( panelName, idata ));
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * This method is called when the panel becomes active.
+     */
+    /*--------------------------------------------------------------------------*/
+    public void panelActivate()
+    {
+        if (spec == null)
+        {
+            // TODO: translate
+            emitError("User input specification could not be found.",
+                    "The specification for the user input panel could not be found. Please contact the packager.");
+            parentFrame.skipPanel();
+        }
+        if( fStaticInitComplete == false ) { 
+           Set keys = varMap.keySet();
+           Iterator iter = keys.iterator();
+           while( iter.hasNext() ) {
+              String var = (String)iter.next();
+              Debug.trace( "varMap: " + var );
+              VCheckBox vcb = (VCheckBox)varMap.get( var );
+              if( vcb != null ) {
+                 vcb.setupDependents();
+              }
+           }
+           fStaticInitComplete = true;
+        }
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forUnselectedPacks = spec.getChildrenNamed(UNSELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+
+        if (!itemRequiredFor(forPacks) || !itemRequiredForUnselected(forUnselectedPacks)
+                || !itemRequiredForOs(forOs))
+        {
+            parentFrame.skipPanel();
+            return;
+        }
+        if (!haveSpec)
+        {
+            parentFrame.skipPanel();
+            return;
+        }
+        String panelName = getTitle();
+        gcp.panelEntryTasks( idata, panelName );
+        gcp.panelDebug( idata, panelName );
+        if( gcp.shouldSkipPanel( idata, panelName )) {
+           parentFrame.skipPanel();
+           return;
+        }
+        // if (uiBuilt)
+        // {
+        // return;
+        // }
+        // ----------------------------------------------------
+        // ----------------------------------------------------
+
+        buildUI();
+        if (packsDefined)
+        {
+            parentFrame.lockPrevButton();
+        }
+        gcp.panelNavDebug( idata );
+        if( gcp.isCheckpointPanel( panelName )) {
+           String msgs[] = { // this is the default, no error message
+              "Congratulations!",
+              "    Geronimo configuration is complete.",
+              "________________",
+              "Press 'Next' to continue with file installation or,",
+              "    press 'Previous' to review or change configuration", "selections.",
+              "",
+              "",
+              "",
+              "",
+              "",
+              "" };
+           if( gcp.haveConfigErrors( idata, msgs )) {
+              parentFrame.lockNextButton();
+           }
+           Object[] uiElement;
+           int j = 0;
+           // Title
+           // 2 Msg labels
+           // DIVIDER
+           // 8 Msg Labels
+           for( int i = 0; i <  10; ++i ) { // skip title
+              uiElement = (Object[])uiElements.elementAt(i); 
+              if( i != 99 ) {  // there's a divider on the panel
+                              // so skip it
+                 //System.out.println("Element: " + i );
+                 // all of the fields here are JLabels, so there's no
+                 // need to check type. Also, they're all displayed,
+                 // so there's no need to check POS_DISPLAYED
+                 MultiLineLabel label = (MultiLineLabel)uiElement[ POS_FIELD ]; 
+                 label.setText( msgs[ j ] );
+                 ++j;
+              }
+           }
+        }
+
+    }
+
+    public void panelDeactivate() {
+       // ###ead -- work-around for bug in automation xml processing for the
+       // packs panel. Exit, re-entry and exit causes multiple panel entries
+       // to appear.  This results in potentially incorrect <selected>
+       // sections to appear with incorrect selected pack lists.  The last
+       // entry is correct, but unfortunately, the first is used by automated
+       // install.  The work-around is to get the xml, walk the tree to the
+       // packs panel info, delete all the selected sections and then
+       // call the packs panel makeXMLData function to re-create one
+       // entry.  It is possible to delete all but the last entry as
+       // well.
+       // This is all done when the last panel is exited -- although
+       //    which direction is unknown/unchecked.
+       if( gcp.isCheckpointPanel( getTitle() )) {
+          XMLElement xml = idata.xmlData;
+          XMLElement panelRoot = null;
+          Debug.trace( "-ValidatePackSelections.panelDeactivate() - xml: " + xml.getName() );
+          panelRoot = xml.getFirstChildNamed( PANEL_PKG + "." + PACKS_PANEL );
+          if( panelRoot != null ) {
+             Vector vSel = panelRoot.getChildrenNamed( SELECTED_PACKS );
+             for( int i = 0; i < vSel.size(); ++i ) {
+                XMLElement sel = (XMLElement)vSel.elementAt(i);
+                Debug.trace( "-ValidatePackSelections.panelDeactivate() - vSel( " + i + " ) = " + sel.toString() );
+             }
+             int children = panelRoot.getChildrenCount();
+             int curChild = 0;
+             while( panelRoot.getChildrenCount() > 0 ) {
+                panelRoot.removeChildAtIndex( 0 );
+                Debug.trace( "-ValidatePackSelections.panelDeactivate() - removing ImgPack child: " + (++curChild) + " of " + children ); 
+             }
+             
+             List panels = idata.panels;
+             Class packsPanelCls = null;
+             try {
+                packsPanelCls = Class.forName( PANEL_PKG + "." + PACKS_PANEL );
+             } catch( Exception e ) {
+               e.printStackTrace();
+               throw new RuntimeException( e );
+             }
+             IzPanel packsPanel = null;
+             for( int i = 0; i < panels.size(); ++i ) {
+                packsPanel = (IzPanel)panels.get(i);
+                if( packsPanelCls.isInstance( packsPanel )) { // there's only one
+                   break;
+                }
+                packsPanel = null;
+             }
+             if( packsPanel != null ) {
+                Debug.trace( "-ValidatePackSelections.panelDeactivate() - calling ImgPacks panel to make new xml." );
+                packsPanel.makeXMLData( panelRoot );
+             }
+          }
+       }
+    }
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Asks the panel to set its own XML data that can be brought back for an automated installation
+     * process. Use it as a blackbox if your panel needs to do something even in automated mode.
+     * 
+     * @param panelRoot The XML root element of the panels blackbox tree.
+     */
+    /*--------------------------------------------------------------------------*/
+    public void makeXMLData(XMLElement panelRoot)
+    {
+        Map entryMap = new HashMap();
+
+        for (int i = 0; i < entries.size(); i++)
+        {
+            TextValuePair pair = (TextValuePair) entries.elementAt(i);
+            entryMap.put(pair.toString(), pair.getValue());
+        }
+
+        new ValidatePackSelectionsAutomationHelper(entryMap, getTitle() ).makeXMLData(idata, panelRoot);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Builds the UI and makes it ready for display
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void buildUI()
+    {
+        Object[] uiElement;
+
+        for (int i = 0; i < uiElements.size(); i++)
+        {
+            uiElement = (Object[]) uiElements.elementAt(i);
+
+            if ( itemRequiredFor((Vector) uiElement[POS_PACKS])  &&     itemRequiredForOs((Vector) uiElement[POS_OS]))
+            {
+                try
+                {
+                    if (uiElement[POS_DISPLAYED] == null
+                           /*###ead || uiElement[POS_DISPLAYED].toString().equals("false")*/)
+                    {
+                        add((JComponent) uiElement[POS_FIELD], uiElement[POS_CONSTRAINTS]);
+                    }
+
+                    uiElement[POS_DISPLAYED] = Boolean.valueOf(true);
+                    ((JComponent) uiElement[POS_FIELD]).setVisible(true); //###ead                     //###ead uiElements.remove(i);
+                    //###ead uiElements.add(i, uiElement);
+                }
+                catch (Throwable exception)
+                {
+                    System.out.println("Internal format error in field: "
+                            + uiElement[POS_TYPE].toString()); // !!! logging
+                }
+            }
+            else
+            {
+                try
+                {
+                    if (uiElement[POS_DISPLAYED] != null
+                            && uiElement[POS_DISPLAYED].toString().equals("true"))
+                    {
+                        //###ead remove((JComponent) uiElement[POS_FIELD]);
+                        ((JComponent) uiElement[POS_FIELD]).setVisible(false); //###ead
+                        uiElement[POS_DISPLAYED] = Boolean.valueOf(false); //###ead
+                    } 
+                    if( uiElement[POS_DISPLAYED] == null ) { //###ead
+                        add((JComponent) uiElement[POS_FIELD],  uiElement[POS_CONSTRAINTS]);
+                        ((JComponent) uiElement[POS_FIELD]).setVisible(false);     
+                        uiElement[POS_DISPLAYED] = Boolean.valueOf(false);
+                    }
+                }
+                catch (Throwable exception)
+                {
+                    System.out.println("Internal format error in field: "
+                            + uiElement[POS_TYPE].toString()); // !!! logging
+                }
+                uiElement[POS_DISPLAYED] = Boolean.valueOf(false);
+                //###ead uiElements.remove(i);
+                //###ead uiElements.add(i, uiElement);
+            }
+        }
+        if( fInitComplete == false ) { //###ead
+           //fInitComplete = true;
+           for (int i = 0; i < uiElements.size(); i++) {
+              uiElement = (Object[]) uiElements.elementAt(i);
+              Object uiComp = uiElement[POS_FIELD];
+              if( uiComp instanceof VCheckBox ) {
+                 VCheckBox vcb = (VCheckBox)uiComp;
+                 vcb.setValidStates();
+              }
+           }
+        }
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Reads the input data from all UI elements and sets the associated variables.
+     * 
+     * @return <code>true</code> if the operation is successdul, otherwise <code>false</code>.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected boolean readInput()
+    {
+        boolean success;
+        String fieldType = null;
+        Object[] field = null;
+
+        passwordGroupsRead.clear();
+        // ----------------------------------------------------
+        // cycle through all but the password fields and read
+        // their contents
+        // ----------------------------------------------------
+        for (int i = 0; i < uiElements.size(); i++)
+        {
+            field = (Object[]) uiElements.elementAt(i);
+
+            if ((field != null) && (((Boolean) field[POS_DISPLAYED]).booleanValue()))
+            {
+                fieldType = (String) (field[POS_TYPE]);
+
+                // ------------------------------------------------
+                if (fieldType.equals(RULE_FIELD))
+                {
+                    success = readRuleField(field);
+                    if (!success) { return (false); }
+                }
+
+                // ------------------------------------------------
+                if (fieldType.equals(PWD_FIELD))
+                {
+                    success = readPasswordField(field);
+                    if (!success) { return (false); }
+                }
+
+                // ------------------------------------------------
+                else if (fieldType.equals(TEXT_FIELD))
+                {
+                    success = readTextField(field);
+                    if (!success) { return (false); }
+                }
+
+                // ------------------------------------------------
+                else if (fieldType.equals(COMBO_FIELD))
+                {
+                    success = readComboBox(field);
+                    if (!success) { return (false); }
+                }
+
+                // ------------------------------------------------
+                else if (fieldType.equals(RADIO_FIELD))
+                {
+                    success = readRadioButton(field);
+                    if (!success) { return (false); }
+                }
+
+                // ------------------------------------------------
+                else if (fieldType.equals(CHECK_FIELD))
+                {
+                    success = readCheckBox(field);
+                    if (!success) { return (false); }
+                }
+                else if (fieldType.equals(SEARCH_FIELD))
+                {
+                    success = readSearch(field);
+                    if (!success) { return (false); }
+                }
+            }
+        }
+
+        return (true);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Reads the XML specification for the panel layout. The result is stored in spec.
+     * 
+     * @exception Exception for any problems in reading the specification
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void readSpec() throws Exception
+    {
+        InputStream input = null;
+        XMLElement data;
+        Vector specElements;
+        String attribute;
+        String instance = Integer.toString(instanceNumber);
+
+        try
+        {
+            input = parentFrame.getResource(SPEC_FILE_NAME);
+        }
+        catch (Exception exception)
+        {
+            haveSpec = false;
+            return;
+        }
+        if (input == null)
+        {
+            haveSpec = false;
+            return;
+        }
+
+        // initialize the parser
+        StdXMLParser parser = new StdXMLParser();
+        parser.setBuilder(new StdXMLBuilder());
+        parser.setValidator(new NonValidator());
+        parser.setReader(new StdXMLReader(input));
+
+        // get the data
+        data = (XMLElement) parser.parse();
+
+        // extract the spec to this specific panel instance
+        if (data.hasChildren())
+        {
+            specElements = data.getChildrenNamed(NODE_ID);
+            //Debug.trace( "--> Panel elements: " + specElements.size() );
+            for (int i = 0; i < specElements.size(); i++)
+            {
+                data = (XMLElement) specElements.elementAt(i);
+                attribute = data.getAttribute(INSTANCE_IDENTIFIER);
+                //Debug.trace( "----> instance: '" + instance + "'  instanceNumber: '" + instanceNumber + "'");
+                if (instance.equals(attribute))
+                {
+                    // use the current element as spec
+                    spec = data;
+                    // close the stream
+                    input.close();
+                    haveSpec = true;
+                    return;
+                }
+            }
+
+            haveSpec = false;
+            return;
+        }
+
+        haveSpec = false;
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds the title to the panel. There can only be one title, if mutiple titles are defined, they
+     * keep overwriting what has already be defined, so that the last definition is the one that
+     * prevails.
+     * 
+     * @param spec a <code>XMLElement</code> containing the specification for the title.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addTitle(XMLElement spec)
+    {
+        String title = getText(spec);
+	setTitle( title );
+        boolean italic = getBoolean(spec, ITALICS, false);
+        boolean bold = getBoolean(spec, BOLD, false);
+        float multiplier = getFloat(spec, SIZE, 2.0f);
+        int justify = getAlignment(spec);
+
+        if (title != null)
+        {
+            JLabel label = new JLabel(title);
+            Font font = label.getFont();
+            float size = font.getSize();
+            int style = 0;
+
+            if (bold)
+            {
+                style = style + Font.BOLD;
+            }
+            if (italic)
+            {
+                style = style + Font.ITALIC;
+            }
+
+            font = font.deriveFont(style, (size * multiplier));
+            label.setFont(font);
+            label.setAlignmentX(0);
+
+            TwoColumnConstraints constraints = new TwoColumnConstraints();
+            constraints.align = justify;
+            constraints.position = TwoColumnConstraints.NORTH;
+
+            add(label, constraints);
+        }
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds a rule field to the list of UI elements.
+     * 
+     * @param spec a <code>XMLElement</code> containing the specification for the rule field.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addRuleField(XMLElement spec)
+    {
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+        XMLElement element = spec.getFirstChildNamed(SPEC);
+        String variable = spec.getAttribute(VARIABLE);
+        RuleInputField field = null;
+        JLabel label;
+        String layout;
+        String set;
+        String separator;
+        String format;
+        String validator = null;
+        String message = null;
+        boolean hasParams = false;
+        String paramName = null;
+        String paramValue = null;
+        HashMap validateParamMap = null;
+        Vector validateParams = null;
+        String processor = null;
+        int resultFormat = RuleInputField.DISPLAY_FORMAT;
+
+        // ----------------------------------------------------
+        // extract the specification details
+        // ----------------------------------------------------
+        if (element != null)
+        {
+            label = new JLabel(getText(element));
+            layout = element.getAttribute(RULE_LAYOUT);
+            set = element.getAttribute(SET);
+
+            // retrieve value of variable if not specified
+            // (does not work here because of special format for set attribute)
+            // if (set == null)
+            // {
+            // set = idata.getVariable (variable);
+            // }
+
+            separator = element.getAttribute(RULE_SEPARATOR);
+            format = element.getAttribute(RULE_RESULT_FORMAT);
+
+            if (format != null)
+            {
+                if (format.equals(RULE_PLAIN_STRING))
+                {
+                    resultFormat = RuleInputField.PLAIN_STRING;
+                }
+                else if (format.equals(RULE_DISPLAY_FORMAT))
+                {
+                    resultFormat = RuleInputField.DISPLAY_FORMAT;
+                }
+                else if (format.equals(RULE_SPECIAL_SEPARATOR))
+                {
+                    resultFormat = RuleInputField.SPECIAL_SEPARATOR;
+                }
+                else if (format.equals(RULE_ENCRYPTED))
+                {
+                    resultFormat = RuleInputField.ENCRYPTED;
+                }
+            }
+        }
+        // ----------------------------------------------------
+        // if there is no specification element, return without
+        // doing anything.
+        // ----------------------------------------------------
+        else
+        {
+            return;
+        }
+
+        // ----------------------------------------------------
+        // get the description and add it to the list of UI
+        // elements if it exists.
+        // ----------------------------------------------------
+        element = spec.getFirstChildNamed(DESCRIPTION);
+        addDescription(element, forPacks, forOs);
+
+        // ----------------------------------------------------
+        // get the validator and processor if they are defined
+        // ----------------------------------------------------
+        element = spec.getFirstChildNamed(VALIDATOR);
+        if (element != null)
+        {
+            validator = element.getAttribute(CLASS);
+            message = getText(element);
+            // ----------------------------------------------------------
+            // check and see if we have any parameters for this validator.
+            // If so, then add them to validateParamMap.
+            // ----------------------------------------------------------
+            validateParams = element.getChildrenNamed(RULE_PARAM);
+            if (validateParams != null && validateParams.size() > 0 && validateParamMap == null)
+            {
+
+                validateParamMap = new HashMap();
+                hasParams = true;
+
+            }
+
+            for (Iterator it = validateParams.iterator(); it.hasNext();)
+            {
+                element = (XMLElement) it.next();
+                paramName = element.getAttribute(RULE_PARAM_NAME);
+                paramValue = element.getAttribute(RULE_PARAM_VALUE);
+                validateParamMap.put(paramName, paramValue);
+            }
+        }
+
+        element = spec.getFirstChildNamed(PROCESSOR);
+        if (element != null)
+        {
+            processor = element.getAttribute(CLASS);
+        }
+
+        // ----------------------------------------------------
+        // create an instance of RuleInputField based on the
+        // extracted specifications, then add it to the list
+        // of UI elements.
+        // ----------------------------------------------------
+        if (hasParams)
+        {
+            field = new RuleInputField(layout, set, separator, validator, validateParamMap,
+                    processor, resultFormat, getToolkit(), idata);
+        }
+        else
+        {
+            field = new RuleInputField(layout, set, separator, validator, processor, resultFormat,
+                    getToolkit(), idata);
+
+        }
+        TwoColumnConstraints constraints = new TwoColumnConstraints();
+        constraints.position = TwoColumnConstraints.WEST;
+
+        uiElements
+                .add(new Object[] { null, FIELD_LABEL, null, constraints, label, forPacks, forOs});
+
+        TwoColumnConstraints constraints2 = new TwoColumnConstraints();
+        constraints2.position = TwoColumnConstraints.EAST;
+
+        uiElements.add(new Object[] { null, RULE_FIELD, variable, constraints2, field, forPacks,
+                forOs, null, null, message});
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Reads the data from the rule input field and sets the associated variable.
+     * 
+     * @param field the object array that holds the details of the field.
+     * 
+     * @return <code>true</code> if there was no problem reading the data or if there was an
+     * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
+     * dialog is popped up and <code>false</code> is returned.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected boolean readRuleField(Object[] field)
+    {
+        RuleInputField ruleField = null;
+        String variable = null;
+
+        try
+        {
+            ruleField = (RuleInputField) field[POS_FIELD];
+            variable = (String) field[POS_VARIABLE];
+        }
+        catch (Throwable exception)
+        {
+            return (true);
+        }
+        if ((variable == null) || (ruleField == null)) { return (true); }
+
+        boolean success = ruleField.validateContents();
+        if (!success)
+        {
+            String message = "";
+            try
+            {
+                message = langpack.getString((String) field[POS_MESSAGE]);
+                if (message.equals(""))
+                {
+                    message = (String) field[POS_MESSAGE];
+                }
+            }
+            catch (Throwable t)
+            {
+                message = (String) field[POS_MESSAGE];
+            }
+            JOptionPane.showMessageDialog(parentFrame, message, parentFrame.langpack
+                    .getString("UserInputPanel.error.caption"), JOptionPane.WARNING_MESSAGE);
+            return (false);
+        }
+
+        idata.setVariable(variable, ruleField.getText());
+        entries.add(new TextValuePair(variable, ruleField.getText()));
+        return (true);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds a text field to the list of UI elements
+     * 
+     * @param spec a <code>XMLElement</code> containing the specification for the text field.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addTextField(XMLElement spec)
+    {
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+        XMLElement element = spec.getFirstChildNamed(SPEC);
+        JLabel label;
+        String set;
+        int size;
+
+        String variable = spec.getAttribute(VARIABLE);
+        if ((variable == null) || (variable.length() == 0)) { return; }
+
+        // ----------------------------------------------------
+        // extract the specification details
+        // ----------------------------------------------------
+        if (element != null)
+        {
+            label = new JLabel(getText(element));
+            set = element.getAttribute(SET);
+            if (set == null)
+            {
+                set = idata.getVariable(variable);
+                if (set == null)
+                {
+                    set = "";
+                }
+            }else{
+                if (set != null && !"".equals(set)){
+                    VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());
+                    set = vs.substitute(set, null);
+                }
+            }
+                
+            try
+            {
+                size = Integer.parseInt(element.getAttribute(TEXT_SIZE));
+            }
+            catch (Throwable exception)
+            {
+                size = 1;
+            }
+        }
+        // ----------------------------------------------------
+        // if there is no specification element, return without
+        // doing anything.
+        // ----------------------------------------------------
+        else
+        {
+            return;
+        }
+
+        // ----------------------------------------------------
+        // get the description and add it to the list UI
+        // elements if it exists.
+        // ----------------------------------------------------
+        element = spec.getFirstChildNamed(DESCRIPTION);
+        addDescription(element, forPacks, forOs);
+
+        // ----------------------------------------------------
+        // construct the UI element and add it to the list
+        // ----------------------------------------------------
+        JTextField field = new JTextField(set, size);
+        field.setCaretPosition(0);
+
+        TwoColumnConstraints constraints = new TwoColumnConstraints();
+        constraints.position = TwoColumnConstraints.WEST;
+
+        uiElements
+                .add(new Object[] { null, FIELD_LABEL, null, constraints, label, forPacks, forOs});
+
+        TwoColumnConstraints constraints2 = new TwoColumnConstraints();
+        constraints2.position = TwoColumnConstraints.EAST;
+
+        uiElements.add(new Object[] { null, TEXT_FIELD, variable, constraints2, field, forPacks,
+                forOs});
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Reads data from the text field and sets the associated variable.
+     * 
+     * @param field the object array that holds the details of the field.
+     * 
+     * @return <code>true</code> if there was no problem reading the data or if there was an
+     * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
+     * dialog is popped up and <code>false</code> is returned.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected boolean readTextField(Object[] field)
+    {
+        JTextField textField = null;
+        String variable = null;
+        String value = null;
+
+        try
+        {
+            textField = (JTextField) field[POS_FIELD];
+            variable = (String) field[POS_VARIABLE];
+            value = textField.getText();
+        }
+        catch (Throwable exception)
+        {
+            return (true);
+        }
+        if ((variable == null) || (value == null)) { return (true); }
+
+        idata.setVariable(variable, value);
+        entries.add(new TextValuePair(variable, value));
+        return (true);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds a combo box to the list of UI elements. <br>
+     * This is a complete example of a valid XML specification
+     * 
+     * <pre>
+     * 
+     *  
+     *   
+     *    &lt;field type=&quot;combo&quot; variable=&quot;testVariable&quot;&gt;
+     *      &lt;description text=&quot;Description for the combo box&quot; id=&quot;a key for translated text&quot;/&gt;
+     *      &lt;spec text=&quot;label&quot; id=&quot;key for the label&quot;/&gt;
+     *        &lt;choice text=&quot;choice 1&quot; id=&quot;&quot; value=&quot;combo box 1&quot;/&gt;
+     *        &lt;choice text=&quot;choice 2&quot; id=&quot;&quot; value=&quot;combo box 2&quot; set=&quot;true&quot;/&gt;
+     *        &lt;choice text=&quot;choice 3&quot; id=&quot;&quot; value=&quot;combo box 3&quot;/&gt;
+     *        &lt;choice text=&quot;choice 4&quot; id=&quot;&quot; value=&quot;combo box 4&quot;/&gt;
+     *      &lt;/spec&gt;
+     *    &lt;/field&gt;
+     *    
+     *   
+     *  
+     * </pre>
+     * 
+     * @param spec a <code>XMLElement</code> containing the specification for the combo box.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addComboBox(XMLElement spec)
+    {
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+        XMLElement element = spec.getFirstChildNamed(SPEC);
+        String variable = spec.getAttribute(VARIABLE);
+        TextValuePair listItem = null;
+        JComboBox field = new JComboBox();
+        JLabel label;
+
+        // ----------------------------------------------------
+        // extract the specification details
+        // ----------------------------------------------------
+        if (element != null)
+        {
+            label = new JLabel(getText(element));
+
+            Vector choices = element.getChildrenNamed(COMBO_CHOICE);
+
+            if (choices == null) { return; }
+
+            for (int i = 0; i < choices.size(); i++)
+            {
+                String processorClass = ((XMLElement) choices.elementAt(i))
+                        .getAttribute("processor");
+
+                if (processorClass != null && !"".equals(processorClass))
+                {
+                    String choiceValues = "";
+                    try
+                    {
+                        choiceValues = ((Processor) Class.forName(processorClass).newInstance())
+                                .process(null);
+                    }
+                    catch (Throwable t)
+                    {
+                        t.printStackTrace();
+                    }
+                    String set = ((XMLElement) choices.elementAt(i)).getAttribute(SET);
+                    if (set == null)
+                    {
+                        set = "";
+                    }
+                    if (set != null && !"".equals(set)){
+                        VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());
+                        set = vs.substitute(set, null);
+                    }
+                    
+                    StringTokenizer tokenizer = new StringTokenizer(choiceValues, ":");
+                    int counter = 0;
+                    while (tokenizer.hasMoreTokens())
+                    {
+                        String token = tokenizer.nextToken();
+                        listItem = new TextValuePair(token, token);
+                        field.addItem(listItem);
+                        if (set.equals(token))
+                        {
+                            field.setSelectedIndex(field.getItemCount() - 1);
+                        }
+                        counter++;
+                    }
+                }
+                else
+                {
+                    listItem = new TextValuePair(getText((XMLElement) choices.elementAt(i)),
+                            ((XMLElement) choices.elementAt(i)).getAttribute(COMBO_VALUE));
+                    field.addItem(listItem);
+                    String set = ((XMLElement) choices.elementAt(i)).getAttribute(SET);
+                    if (set != null)
+                    {
+                        if (set != null && !"".equals(set)){
+                            VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());
+                            set = vs.substitute(set, null);
+                        }
+                        if (set.equals(TRUE))
+                        {
+                            field.setSelectedIndex(i);
+                        }
+                    }
+                }
+
+            }
+        }
+        // ----------------------------------------------------
+        // if there is no specification element, return without
+        // doing anything.
+        // ----------------------------------------------------
+        else
+        {
+            return;
+        }
+
+        // ----------------------------------------------------
+        // get the description and add it to the list of UI
+        // elements if it exists.
+        // ----------------------------------------------------
+        element = spec.getFirstChildNamed(DESCRIPTION);
+        addDescription(element, forPacks, forOs);
+
+        TwoColumnConstraints constraints = new TwoColumnConstraints();
+        constraints.position = TwoColumnConstraints.WEST;
+
+        uiElements
+                .add(new Object[] { null, FIELD_LABEL, null, constraints, label, forPacks, forOs});
+
+        TwoColumnConstraints constraints2 = new TwoColumnConstraints();
+        constraints2.position = TwoColumnConstraints.EAST;
+
+        uiElements.add(new Object[] { null, COMBO_FIELD, variable, constraints2, field, forPacks,
+                forOs});
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Reads the content of the combobox field and substitutes the associated variable.
+     * 
+     * @param field the object array that holds the details of the field.
+     * 
+     * @return <code>true</code> if there was no problem reading the data or if there was an
+     * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
+     * dialog is popped up and <code>false</code> is returned.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected boolean readComboBox(Object[] field)
+    {
+        String variable;
+        String value;
+        JComboBox comboBox;
+
+        try
+        {
+            variable = (String) field[POS_VARIABLE];
+            comboBox = (JComboBox) field[POS_FIELD];
+            value = ((TextValuePair) comboBox.getSelectedItem()).getValue();
+        }
+        catch (Throwable exception)
+        {
+            return true;
+        }
+        if ((variable == null) || (value == null)) { return true; }
+
+        idata.setVariable(variable, value);
+        entries.add(new TextValuePair(variable, value));
+        return true;
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds a radio button set to the list of UI elements. <br>
+     * This is a complete example of a valid XML specification
+     * 
+     * <pre>
+     * 
+     *  
+     *   
+     *    &lt;field type=&quot;radio&quot; variable=&quot;testVariable&quot;&gt;
+     *      &lt;description text=&quot;Description for the radio buttons&quot; id=&quot;a key for translated text&quot;/&gt;
+     *      &lt;spec text=&quot;label&quot; id=&quot;key for the label&quot;/&gt;
+     *        &lt;choice text=&quot;radio 1&quot; id=&quot;&quot; value=&quot;&quot;/&gt;
+     *        &lt;choice text=&quot;radio 2&quot; id=&quot;&quot; value=&quot;&quot; set=&quot;true&quot;/&gt;
+     *        &lt;choice text=&quot;radio 3&quot; id=&quot;&quot; value=&quot;&quot;/&gt;
+     *        &lt;choice text=&quot;radio 4&quot; id=&quot;&quot; value=&quot;&quot;/&gt;
+     *        &lt;choice text=&quot;radio 5&quot; id=&quot;&quot; value=&quot;&quot;/&gt;
+     *      &lt;/spec&gt;
+     *    &lt;/field&gt;
+     *    
+     *   
+     *  
+     * </pre>
+     * 
+     * @param spec a <code>XMLElement</code> containing the specification for the radio button
+     * set.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addRadioButton(XMLElement spec)
+    {
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+        String variable = spec.getAttribute(VARIABLE);
+        String value = null;
+
+        XMLElement element = null;
+        ButtonGroup group = new ButtonGroup();
+
+        TwoColumnConstraints constraints = new TwoColumnConstraints();
+        constraints.position = TwoColumnConstraints.BOTH;
+        constraints.indent = true;
+        constraints.stretch = true;
+
+        // ----------------------------------------------------
+        // get the description and add it to the list of UI
+        // elements if it exists.
+        // ----------------------------------------------------
+        element = spec.getFirstChildNamed(DESCRIPTION);
+        addDescription(element, forPacks, forOs);
+
+        // ----------------------------------------------------
+        // extract the specification details
+        // ----------------------------------------------------
+        element = spec.getFirstChildNamed(SPEC);
+
+        if (element != null)
+        {
+            Vector choices = element.getChildrenNamed(RADIO_CHOICE);
+
+            if (choices == null) { return; }
+
+            // --------------------------------------------------
+            // process each choice element
+            // --------------------------------------------------
+            for (int i = 0; i < choices.size(); i++)
+            {
+                JRadioButton choice = new JRadioButton();
+                choice.setText(getText((XMLElement) choices.elementAt(i)));
+                value = (((XMLElement) choices.elementAt(i)).getAttribute(RADIO_VALUE));
+
+                group.add(choice);
+
+                String set = ((XMLElement) choices.elementAt(i)).getAttribute(SET);
+                if (set != null)
+                {
+                    if (set != null && !"".equals(set)){
+                        VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());
+                        set = vs.substitute(set, null);
+                    }
+                    if (set.equals(TRUE))
+                    {
+                        choice.setSelected(true);
+                    }
+                }
+
+                buttonGroups.add(group);
+                uiElements.add(new Object[] { null, RADIO_FIELD, variable, constraints, choice,
+                        forPacks, forOs, value, null, null, group});
+            }
+        }
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Reads the content of the radio button field and substitutes the associated variable.
+     * 
+     * @param field the object array that holds the details of the field.
+     * 
+     * @return <code>true</code> if there was no problem reading the data or if there was an
+     * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
+     * dialog is popped up and <code>false</code> is returned.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected boolean readRadioButton(Object[] field)
+    {
+        String variable = null;
+        String value = null;
+        JRadioButton button = null;
+
+        try
+        {
+            button = (JRadioButton) field[POS_FIELD];
+
+            if (!button.isSelected()) { return (true); }
+
+            variable = (String) field[POS_VARIABLE];
+            value = (String) field[POS_TRUE];
+        }
+        catch (Throwable exception)
+        {
+            return (true);
+        }
+
+        idata.setVariable(variable, value);
+        entries.add(new TextValuePair(variable, value));
+        return (true);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds one or more password fields to the list of UI elements. <br>
+     * This is a complete example of a valid XML specification
+     * 
+     * <pre>
+     * 
+     *  
+     *   
+     *    &lt;field type=&quot;password&quot; variable=&quot;testVariable&quot;&gt;
+     *      &lt;description align=&quot;left&quot; txt=&quot;Please enter your password&quot; id=&quot;a key for translated text&quot;/&gt;
+     *      &lt;spec&gt;
+     *        &lt;pwd txt=&quot;Password&quot; id=&quot;key for the label&quot; size=&quot;10&quot; set=&quot;&quot;/&gt;
+     *        &lt;pwd txt=&quot;Retype password&quot; id=&quot;another key for the label&quot; size=&quot;10&quot; set=&quot;&quot;/&gt;
+     *      &lt;/spec&gt;
+     *      &lt;validator class=&quot;com.izforge.sample.PWDValidator&quot; txt=&quot;Both versions of the password must match&quot; id=&quot;key for the error text&quot;/&gt;
+     *      &lt;processor class=&quot;com.izforge.sample.PWDEncryptor&quot;/&gt;
+     *    &lt;/field&gt;
+     *    
+     *   
+     *  
+     * </pre>
+     * 
+     * @param spec a <code>XMLElement</code> containing the specification for the set of password
+     * fields.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addPasswordField(XMLElement spec)
+    {
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+        String variable = spec.getAttribute(VARIABLE);
+        String validator = null;
+        String message = null;
+        String processor = null;
+        XMLElement element = null;
+        PasswordGroup group = null;
+        int size = 0;
+
+        // ----------------------------------------------------
+        // get the description and add it to the list of UI
+        // elements if it exists.
+        // ----------------------------------------------------
+        element = spec.getFirstChildNamed(DESCRIPTION);
+        addDescription(element, forPacks, forOs);
+
+        // ----------------------------------------------------
+        // get the validator and processor if they are defined
+        // ----------------------------------------------------
+        element = spec.getFirstChildNamed(VALIDATOR);
+        if (element != null)
+        {
+            validator = element.getAttribute(CLASS);
+            message = getText(element);
+        }
+
+        element = spec.getFirstChildNamed(PROCESSOR);
+        if (element != null)
+        {
+            processor = element.getAttribute(CLASS);
+        }
+
+        group = new PasswordGroup(validator, processor);
+
+        // ----------------------------------------------------
+        // extract the specification details
+        // ----------------------------------------------------
+        element = spec.getFirstChildNamed(SPEC);
+
+        if (element != null)
+        {
+            Vector inputs = element.getChildrenNamed(PWD_INPUT);
+
+            if (inputs == null) { return; }
+
+            // --------------------------------------------------
+            // process each input field
+            // --------------------------------------------------
+            XMLElement fieldSpec;
+            for (int i = 0; i < inputs.size(); i++)
+            {
+                fieldSpec = (XMLElement) inputs.elementAt(i);
+                String set = fieldSpec.getAttribute(SET);
+                if (set != null && !"".equals(set)){
+                    VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());
+                    set = vs.substitute(set, null);
+                }
+                JLabel label = new JLabel(getText(fieldSpec));
+                try
+                {
+                    size = Integer.parseInt(fieldSpec.getAttribute(PWD_SIZE));
+                }
+                catch (Throwable exception)
+                {
+                    size = 1;
+                }
+
+                // ----------------------------------------------------
+                // construct the UI element and add it to the list
+                // ----------------------------------------------------
+                JPasswordField field = new JPasswordField(set, size);
+                field.setCaretPosition(0);
+
+                TwoColumnConstraints constraints = new TwoColumnConstraints();
+                constraints.position = TwoColumnConstraints.WEST;
+
+                uiElements.add(new Object[] { null, FIELD_LABEL, null, constraints, label,
+                        forPacks, forOs});
+
+                TwoColumnConstraints constraints2 = new TwoColumnConstraints();
+                constraints2.position = TwoColumnConstraints.EAST;
+
+                uiElements.add(new Object[] { null, PWD_FIELD, variable, constraints2, field,
+                        forPacks, forOs, null, null, message, group});
+                group.addField(field);
+            }
+        }
+
+        passwordGroups.add(group);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Reads the content of the password field and substitutes the associated variable.
+     * 
+     * @param field a password group that manages one or more passord fields.
+     * 
+     * @return <code>true</code> if there was no problem reading the data or if there was an
+     * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
+     * dialog is popped up and <code>false</code> is returned.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected boolean readPasswordField(Object[] field)
+    {
+        PasswordGroup group = null;
+        String variable = null;
+        String message = null;
+
+        try
+        {
+            group = (PasswordGroup) field[POS_GROUP];
+            variable = (String) field[POS_VARIABLE];
+            message = (String) field[POS_MESSAGE];
+        }
+        catch (Throwable exception)
+        {
+            return (true);
+        }
+        if ((variable == null) || (passwordGroupsRead.contains(group))) { return (true); }
+        passwordGroups.add(group);
+
+        boolean success = group.validateContents();
+
+        if (!success)
+        {
+            JOptionPane.showMessageDialog(parentFrame, message, parentFrame.langpack
+                    .getString("UserInputPanel.error.caption"), JOptionPane.WARNING_MESSAGE);
+            return (false);
+        }
+
+        idata.setVariable(variable, group.getPassword());
+        entries.add(new TextValuePair(variable, group.getPassword()));
+        return (true);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds a chackbox to the list of UI elements.
+     * 
+     * @param spec a <code>XMLElement</code> containing the specification for the checkbox.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addCheckBox(XMLElement spec)
+    {
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+        String label = "";
+        String set = null;
+        String trueValue = null;
+        String falseValue = null;
+        String variable = spec.getAttribute(VARIABLE);
+        XMLElement detail = spec.getFirstChildNamed(SPEC);
+
+        if (variable == null) { return; }
+
+        if (detail != null)
+        {
+            label = getText(detail);
+            set = detail.getAttribute(SET);
+            trueValue = detail.getAttribute(TRUE);
+            falseValue = detail.getAttribute(FALSE);
+        }
+
+        VCheckBox checkbox = new VCheckBox(label, varMap, idata, spec);
+
+        if (set != null)
+        {
+            if (set != null && !"".equals(set)){
+                VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());
+                set = vs.substitute(set, null);
+            }
+            if (set.equals(FALSE))
+            {
+                checkbox.setSelected(false);
+            }
+            if (set.equals(TRUE))
+            {
+                checkbox.setSelected(true);
+            }
+        }
+
+        // ----------------------------------------------------
+        // get the description and add it to the list of UI
+        // elements if it exists.
+        // ----------------------------------------------------
+        XMLElement element = spec.getFirstChildNamed(DESCRIPTION);
+        addDescription(element, forPacks, forOs);
+
+        TwoColumnConstraints constraints = new TwoColumnConstraints();
+        constraints.position = TwoColumnConstraints.BOTH;
+        constraints.stretch = true;
+        constraints.indent = true;
+
+        uiElements.add(new Object[] { null, CHECK_FIELD, variable, constraints, checkbox, forPacks,
+                forOs, trueValue, falseValue});
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Reads the content of the checkbox field and substitutes the associated variable.
+     * 
+     * @param field the object array that holds the details of the field.
+     * 
+     * @return <code>true</code> if there was no problem reading the data or if there was an
+     * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
+     * dialog is popped up and <code>false</code> is returned.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected boolean readCheckBox(Object[] field)
+    {
+        String variable = null;
+        String trueValue = null;
+        String falseValue = null;
+        JCheckBox box = null;
+
+        try
+        {
+            box = (JCheckBox) field[POS_FIELD];
+            variable = (String) field[POS_VARIABLE];
+            trueValue = (String) field[POS_TRUE];
+            if (trueValue == null)
+            {
+                trueValue = "";
+            }
+
+            falseValue = (String) field[POS_FALSE];
+            if (falseValue == null)
+            {
+                falseValue = "";
+            }
+        }
+        catch (Throwable exception)
+        {
+            return (true);
+        }
+
+        if (box.isSelected())
+        {
+            idata.setVariable(variable, trueValue);
+            entries.add(new TextValuePair(variable, trueValue));
+        }
+        else
+        {
+            idata.setVariable(variable, falseValue);
+            entries.add(new TextValuePair(variable, falseValue));
+        }
+
+        return (true);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds a search field to the list of UI elements.
+     * <p>
+     * This is a complete example of a valid XML specification
+     * 
+     * <pre>
+     * 
+     *  
+     *   
+     *    &lt;field type=&quot;search&quot; variable=&quot;testVariable&quot;&gt;
+     *      &lt;description text=&quot;Description for the search field&quot; id=&quot;a key for translated text&quot;/&gt;
+     *      &lt;spec text=&quot;label&quot; id=&quot;key for the label&quot; filename=&quot;the_file_to_search&quot; result=&quot;directory&quot; /&gt; &lt;!-- values for result: directory, file --&gt;
+     *        &lt;choice dir=&quot;directory1&quot; set=&quot;true&quot; /&gt; &lt;!-- default value --&gt;
+     *        &lt;choice dir=&quot;dir2&quot; /&gt;
+     *      &lt;/spec&gt;
+     *    &lt;/field&gt;
+     *    
+     *   
+     *  
+     * </pre>
+     * 
+     * @param spec a <code>XMLElement</code> containing the specification for the search field
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addSearch(XMLElement spec)
+    {
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+        XMLElement element = spec.getFirstChildNamed(SPEC);
+        String variable = spec.getAttribute(VARIABLE);
+        String filename = null;
+        String check_filename = null;
+        int search_type = 0;
+        int result_type = 0;
+        JComboBox combobox = new JComboBox();
+        JLabel label = null;
+
+        // System.out.println ("adding search combobox, variable "+variable);
+
+        // allow the user to enter something
+        combobox.setEditable(true);
+
+        // ----------------------------------------------------
+        // extract the specification details
+        // ----------------------------------------------------
+        if (element != null)
+        {
+            label = new JLabel(getText(element));
+
+            // search type is optional (default: file)
+            search_type = SearchField.TYPE_FILE;
+
+            String search_type_str = element.getAttribute(SEARCH_TYPE);
+
+            if (search_type_str != null)
+            {
+                if (search_type_str.equals(SEARCH_FILE))
+                {
+                    search_type = SearchField.TYPE_FILE;
+                }
+                else if (search_type_str.equals(SEARCH_DIRECTORY))
+                {
+                    search_type = SearchField.TYPE_DIRECTORY;
+                }
+            }
+
+            // result type is mandatory too
+            String result_type_str = element.getAttribute(SEARCH_RESULT);
+
+            if (result_type_str == null)
+            {
+                return;
+            }
+            else if (result_type_str.equals(SEARCH_FILE))
+            {
+                result_type = SearchField.RESULT_FILE;
+            }
+            else if (result_type_str.equals(SEARCH_DIRECTORY))
+            {
+                result_type = SearchField.RESULT_DIRECTORY;
+            }
+            else if (result_type_str.equals(SEARCH_PARENTDIR))
+            {
+                result_type = SearchField.RESULT_PARENTDIR;
+            }
+            else
+            {
+                return;
+            }
+
+            // might be missing - null is okay
+            filename = element.getAttribute(SEARCH_FILENAME);
+
+            check_filename = element.getAttribute(SEARCH_CHECKFILENAME);
+
+            Vector choices = element.getChildrenNamed(SEARCH_CHOICE);
+
+            if (choices == null) { return; }
+
+            for (int i = 0; i < choices.size(); i++)
+            {
+                XMLElement choice_el = (XMLElement) choices.elementAt(i);
+
+                if (!OsConstraint.oneMatchesCurrentSystem(choice_el)) continue;
+
+                String value = choice_el.getAttribute(SEARCH_VALUE);
+
+                combobox.addItem(value);
+
+                String set = ((XMLElement) choices.elementAt(i)).getAttribute(SET);
+                if (set != null)
+                {
+                    if (set != null && !"".equals(set)){
+                        VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());
+                        set = vs.substitute(set, null);
+                    }
+                    if (set.equals(TRUE))
+                    {
+                        combobox.setSelectedIndex(i);
+                    }
+                }
+            }
+        }
+        // ----------------------------------------------------
+        // if there is no specification element, return without
+        // doing anything.
+        // ----------------------------------------------------
+        else
+        {
+            return;
+        }
+
+        // ----------------------------------------------------
+        // get the description and add it to the list of UI
+        // elements if it exists.
+        // ----------------------------------------------------
+        element = spec.getFirstChildNamed(DESCRIPTION);
+        addDescription(element, forPacks, forOs);
+
+        TwoColumnConstraints westconstraint1 = new TwoColumnConstraints();
+        westconstraint1.position = TwoColumnConstraints.WEST;
+
+        uiElements.add(new Object[] { null, FIELD_LABEL, null, westconstraint1, label, forPacks,
+                forOs});
+
+        TwoColumnConstraints eastconstraint1 = new TwoColumnConstraints();
+        eastconstraint1.position = TwoColumnConstraints.EAST;
+
+        StringBuffer tooltiptext = new StringBuffer();
+
+        if ((filename != null) && (filename.length() > 0))
+        {
+            tooltiptext.append(MessageFormat.format(parentFrame.langpack
+                    .getString("UserInputPanel.search.location"), new String[] { filename}));
+        }
+
+        boolean showAutodetect = (check_filename != null) && (check_filename.length() > 0);
+        if (showAutodetect)
+        {
+            tooltiptext.append(MessageFormat.format(parentFrame.langpack
+                    .getString("UserInputPanel.search.location.checkedfile"),
+                    new String[] { check_filename}));
+        }
+
+        if (tooltiptext.length() > 0) combobox.setToolTipText(tooltiptext.toString());
+
+        uiElements.add(new Object[] { null, SEARCH_FIELD, variable, eastconstraint1, combobox,
+                forPacks, forOs});
+
+        JPanel buttonPanel = new JPanel();
+        buttonPanel.setLayout(new com.izforge.izpack.gui.FlowLayout(
+                com.izforge.izpack.gui.FlowLayout.LEADING));
+
+        JButton autodetectButton = ButtonFactory.createButton(parentFrame.langpack
+                .getString("UserInputPanel.search.autodetect"), idata.buttonsHColor);
+        autodetectButton.setVisible(showAutodetect);
+
+        autodetectButton.setToolTipText(parentFrame.langpack
+                .getString("UserInputPanel.search.autodetect.tooltip"));
+
+        buttonPanel.add(autodetectButton);
+
+        JButton browseButton = ButtonFactory.createButton(parentFrame.langpack
+                .getString("UserInputPanel.search.browse"), idata.buttonsHColor);
+
+        buttonPanel.add(browseButton);
+
+        TwoColumnConstraints eastonlyconstraint = new TwoColumnConstraints();
+        eastonlyconstraint.position = TwoColumnConstraints.EASTONLY;
+
+        uiElements.add(new Object[] { null, SEARCH_BUTTON_FIELD, null, eastonlyconstraint,
+                buttonPanel, forPacks, forOs});
+
+        searchFields.add(new SearchField(filename, check_filename, parentFrame, combobox,
+                autodetectButton, browseButton, search_type, result_type));
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Reads the content of the search field and substitutes the associated variable.
+     * 
+     * @param field the object array that holds the details of the field.
+     * 
+     * @return <code>true</code> if there was no problem reading the data or if there was an
+     * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
+     * dialog is popped up and <code>false</code> is returned.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected boolean readSearch(Object[] field)
+    {
+        String variable = null;
+        String value = null;
+        JComboBox comboBox = null;
+
+        try
+        {
+            variable = (String) field[POS_VARIABLE];
+            comboBox = (JComboBox) field[POS_FIELD];
+            for (int i = 0; i < this.searchFields.size(); ++i)
+            {
+                SearchField sf = (SearchField) this.searchFields.elementAt(i);
+                if (sf.belongsTo(comboBox))
+                {
+                    value = sf.getResult();
+                    break;
+                }
+            }
+        }
+        catch (Throwable exception)
+        {
+            return (true);
+        }
+        if ((variable == null) || (value == null)) { return (true); }
+
+        idata.setVariable(variable, value);
+        entries.add(new TextValuePair(variable, value));
+        return (true);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds text to the list of UI elements
+     * 
+     * @param spec a <code>XMLElement</code> containing the specification for the text.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addText(XMLElement spec)
+    {
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+
+        addDescription(spec, forPacks, forOs);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds a dummy field to the list of UI elements to act as spacer.
+     * 
+     * @param spec a <code>XMLElement</code> containing other specifications. At present this
+     * information is not used but might be in future versions.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addSpace(XMLElement spec)
+    {
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+        JPanel panel = new JPanel();
+
+        TwoColumnConstraints constraints = new TwoColumnConstraints();
+        constraints.position = TwoColumnConstraints.BOTH;
+        constraints.stretch = true;
+
+        uiElements
+                .add(new Object[] { null, SPACE_FIELD, null, constraints, panel, forPacks, forOs});
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds a dividing line to the list of UI elements act as separator.
+     * 
+     * @param spec a <code>XMLElement</code> containing additional specifications.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addDivider(XMLElement spec)
+    {
+        Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS);
+        Vector forOs = spec.getChildrenNamed(OS);
+        JPanel panel = new JPanel();
+        String alignment = spec.getAttribute(ALIGNMENT);
+
+        if (alignment != null)
+        {
+            if (alignment.equals(TOP))
+            {
+                panel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.gray));
+            }
+            else
+            {
+                panel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.gray));
+            }
+        }
+        else
+        {
+            panel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.gray));
+        }
+
+        TwoColumnConstraints constraints = new TwoColumnConstraints();
+        constraints.position = TwoColumnConstraints.BOTH;
+        constraints.stretch = true;
+
+        uiElements.add(new Object[] { null, DIVIDER_FIELD, null, constraints, panel, forPacks,
+                forOs});
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Adds a description to the list of UI elements.
+     * 
+     * @param spec a <code>XMLElement</code> containing the specification for the description.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected void addDescription(XMLElement spec, Vector forPacks, Vector forOs)
+    {
+        String description;
+        TwoColumnConstraints constraints = new TwoColumnConstraints();
+        constraints.position = TwoColumnConstraints.BOTH;
+        constraints.stretch = true;
+
+        if (spec != null)
+        {
+            description = getText(spec);
+
+            // if we have a description, add it to the UI elements
+            if (description != null)
+            {
+                String alignment = spec.getAttribute(ALIGNMENT);
+                int justify = MultiLineLabel.LEFT;
+
+                if (alignment != null)
+                {
+                    if (alignment.equals(LEFT))
+                    {
+                        justify = MultiLineLabel.LEFT;
+                    }
+                    else if (alignment.equals(CENTER))
+                    {
+                        justify = MultiLineLabel.CENTER;
+                    }
+                    else if (alignment.equals(RIGHT))
+                    {
+                        justify = MultiLineLabel.RIGHT;
+                    }
+                }
+
+                MultiLineLabel label = new MultiLineLabel(description, justify);
+
+                uiElements.add(new Object[] { null, DESCRIPTION, null, constraints, label,
+                        forPacks, forOs});
+            }
+        }
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Retrieves the value of a boolean attribute. If the attribute is found and the values equals
+     * the value of the constant <code>TRUE</code> then true is returned. If it equals
+     * <code>FALSE</code> the false is returned. In all other cases, including when the attribute
+     * is not found, the default value is returned.
+     * 
+     * @param element the <code>XMLElement</code> to search for the attribute.
+     * @param attribute the attribute to search for
+     * @param defaultValue the default value to use if the attribute does not exist or a illegal
+     * value was discovered.
+     * 
+     * @return <code>true</code> if the attribute is found and the value equals the the constant
+     * <code>TRUE</code>. <<code> if the
+     *            attribute is <code>FALSE</code>. In all other cases the
+     *            default value is returned.
+     */
+    /*--------------------------------------------------------------------------*/
+    protected boolean getBoolean(XMLElement element, String attribute, boolean defaultValue)
+    {
+        boolean result = defaultValue;
+
+        if ((attribute != null) && (attribute.length() > 0))
+        {
+            String value = element.getAttribute(attribute);
+
+            if (value != null)
+            {
+                if (value.equals(TRUE))
+                {
+                    result = true;
+                }
+                else if (value.equals(FALSE))
+                {
+                    result = false;
+                }
+            }
+        }
+
+        return (result);
+    }
+
+    /*--------------------------------------------------------------------------*/
+    /**
+     * Retrieves the value of an integer attribute. If the attribute is not found or the value is
+     * non-numeric then the default value is returned.
+     * 
+     * @param element the <code>XMLElement</code> to search for the attribute.
+     * @param attribute the attribute to search for
+     * @param defaultValue the default value to use in case the attribute does not exist.
+     * 
+     * @return the value of the attribute. If the attribute is not found or the content is not a
+     * legal integer, then the default value is returned.
+     */
+    /*--------------------------------------------------------------------------*/
+//    private int getInt(XMLElement element, String attribute, int defaultValue)
+//    {
+//        int result = defaultValue;
+//
+//        if ((attribute != null) && (attribute.length() > 0))
+//        {
+//            try
+//            {
+//                result = Integer.parseInt(element.getAttribute(attribute));
+//            }
+//            catch (Throwable exception)
+//            {}
+//        }
+//
+//        return (result);
+//    }
+

[... 844 lines stripped ...]