0001: /*
0002: * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved.
0003: *
0004: * http://izpack.org/
0005: * http://izpack.codehaus.org/
0006: *
0007: * Copyright 2002 Elmar Grom
0008: *
0009: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
0010: * in compliance with the License. You may obtain a copy of the License at
0011: *
0012: * http://www.apache.org/licenses/LICENSE-2.0
0013: *
0014: * Unless required by applicable law or agreed to in writing, software distributed under the License
0015: * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
0016: * or implied. See the License for the specific language governing permissions and limitations under
0017: * the License.
0018: */
0019:
0020: package com.izforge.izpack.panels;
0021:
0022: import java.awt.Color;
0023: import java.awt.Font;
0024: import java.awt.event.ActionEvent;
0025: import java.awt.event.ActionListener;
0026: import java.io.File;
0027: import java.io.InputStream;
0028: import java.text.MessageFormat;
0029: import java.util.HashMap;
0030: import java.util.HashSet;
0031: import java.util.Iterator;
0032: import java.util.Map;
0033: import java.util.StringTokenizer;
0034: import java.util.Vector;
0035:
0036: import javax.swing.BorderFactory;
0037: import javax.swing.ButtonGroup;
0038: import javax.swing.ImageIcon;
0039: import javax.swing.JButton;
0040: import javax.swing.JCheckBox;
0041: import javax.swing.JComboBox;
0042: import javax.swing.JComponent;
0043: import javax.swing.JFileChooser;
0044: import javax.swing.JLabel;
0045: import javax.swing.JOptionPane;
0046: import javax.swing.JPanel;
0047: import javax.swing.JPasswordField;
0048: import javax.swing.JRadioButton;
0049: import javax.swing.JTextField;
0050: import javax.swing.event.DocumentEvent;
0051: import javax.swing.event.DocumentListener;
0052: import javax.swing.filechooser.FileFilter;
0053: import javax.swing.text.BadLocationException;
0054: import javax.swing.text.Document;
0055:
0056: import net.n3.nanoxml.NonValidator;
0057: import net.n3.nanoxml.StdXMLParser;
0058: import net.n3.nanoxml.StdXMLReader;
0059: import net.n3.nanoxml.XMLElement;
0060: import net.n3.nanoxml.XMLBuilderFactory;
0061:
0062: import com.izforge.izpack.LocaleDatabase;
0063: import com.izforge.izpack.Pack;
0064: import com.izforge.izpack.Panel;
0065: import com.izforge.izpack.gui.ButtonFactory;
0066: import com.izforge.izpack.gui.LabelFactory;
0067: import com.izforge.izpack.gui.TwoColumnConstraints;
0068: import com.izforge.izpack.gui.TwoColumnLayout;
0069: import com.izforge.izpack.installer.InstallData;
0070: import com.izforge.izpack.installer.InstallerFrame;
0071: import com.izforge.izpack.installer.IzPanel;
0072: import com.izforge.izpack.installer.ResourceManager;
0073: import com.izforge.izpack.rules.RulesEngine;
0074: import com.izforge.izpack.util.Debug;
0075: import com.izforge.izpack.util.MultiLineLabel;
0076: import com.izforge.izpack.util.OsConstraint;
0077: import com.izforge.izpack.util.OsVersion;
0078: import com.izforge.izpack.util.VariableSubstitutor;
0079: import java.util.ArrayList;
0080: import java.util.List;
0081:
0082: /*---------------------------------------------------------------------------*/
0083: /**
0084: * This panel is designed to collect user input during the installation process. The panel is
0085: * initially blank and is populated with input elements based on the XML specification in a resource
0086: * file.
0087: *
0088: *
0089: * @version 0.0.1 / 10/19/02
0090: * @author getDirectoryCreated
0091: */
0092: /*---------------------------------------------------------------------------*/
0093: /*
0094: * $ @design
0095: *
0096: * Each field is specified in its own node, containing attributes and data. When this class is
0097: * instantiated, the specification is read and analyzed. Each field node is processed based on its
0098: * type. An specialized member function is called for each field type that creates the necessary UI
0099: * elements. All UI elements are stored in the uiElements vector. Elements are packaged in an object
0100: * array that must follow this pattern:
0101: *
0102: * index 0 - a String object, that specifies the field type. This is identical to the string used to
0103: * identify the field type in the XML file. index 1 - a String object that contains the variable
0104: * name for substitution. index 2 - the constraints object that should be used for positioning the
0105: * UI element index 3 - the UI element itself index 4 - a Vector containg a list of pack for which
0106: * the item should be created. This is used by buildUI() to decide if the item should be added to
0107: * the UI.
0108: *
0109: * In some cases additional entries are used. The use depends on the specific needs of the type of
0110: * input field.
0111: *
0112: * When the panel is activated, the method buildUI() walks the list of UI elements adds them to the
0113: * panel together with the matching constraint.
0114: *
0115: * When an attempt is made to move on to another panel, the method readInput() walks the list of UI
0116: * elements again and calls specialized methods that know how to read the user input from each of
0117: * the UI elemnts and set the associated varaible.
0118: *
0119: * The actual variable substitution is not performed by this panel but by the variable substitutor.
0120: *
0121: * To Do: ------ * make sure all header documentation is complete and correct
0122: * --------------------------------------------------------------------------
0123: */
0124: public class UserInputPanel extends IzPanel implements ActionListener {
0125:
0126: // ------------------------------------------------------------------------
0127: // Constant Definitions
0128: // ------------------------------------------------------------------------
0129:
0130: // The constants beginning with 'POS_' define locations in the object arrays
0131: // that used to hold all information for the individual fields. Some data is
0132: // not required for all field types. If this happens withing the array, that
0133: // location must be padded with 'null'. At the end of the array it can be
0134: // omitted. The data stored in this way is in most cases only known by
0135: // convention between the add and the associated read method. the following
0136: // positions are also used by other service methods in this class and must
0137: // not be used for other purposes:
0138: // - POS_DISPLAYED
0139: // - POS_TYPE
0140: // - POS_CONSTRAINTS
0141: // - POS_PACKS
0142:
0143: /**
0144: *
0145: */
0146: private static final long serialVersionUID = 3257850965439886129L;
0147:
0148: private static final int POS_DISPLAYED = 0;
0149:
0150: private static final int POS_TYPE = 1;
0151:
0152: private static final int POS_VARIABLE = 2;
0153:
0154: private static final int POS_CONSTRAINTS = 3;
0155:
0156: private static final int POS_FIELD = 4;
0157:
0158: private static final int POS_PACKS = 5;
0159:
0160: private static final int POS_OS = 6;
0161:
0162: private static final int POS_TRUE = 7;
0163:
0164: private static final int POS_FALSE = 8;
0165:
0166: private static final int POS_MESSAGE = 9;
0167:
0168: private static final int POS_GROUP = 10;
0169:
0170: protected static final String ICON_KEY = "icon";
0171:
0172: /** The name of the XML file that specifies the panel layout */
0173: private static final String SPEC_FILE_NAME = "userInputSpec.xml";
0174:
0175: private static final String LANG_FILE_NAME = "userInputLang.xml";
0176:
0177: /** how the spec node for a specific panel is identified */
0178: private static final String NODE_ID = "panel";
0179:
0180: private static final String FIELD_NODE_ID = "field";
0181:
0182: private static final String INSTANCE_IDENTIFIER = "order";
0183: protected static final String PANEL_IDENTIFIER = "id";
0184:
0185: private static final String TYPE = "type";
0186:
0187: private static final String DESCRIPTION = "description";
0188:
0189: private static final String VARIABLE = "variable";
0190:
0191: private static final String TEXT = "txt";
0192:
0193: private static final String KEY = "id";
0194:
0195: private static final String SPEC = "spec";
0196:
0197: private static final String SET = "set";
0198:
0199: private static final String REVALIDATE = "revalidate";
0200:
0201: private static final String TOPBUFFER = "topBuffer";
0202:
0203: private static final String TRUE = "true";
0204:
0205: private static final String FALSE = "false";
0206:
0207: private static final String ALIGNMENT = "align";
0208:
0209: private static final String LEFT = "left";
0210:
0211: private static final String CENTER = "center";
0212:
0213: private static final String RIGHT = "right";
0214:
0215: private static final String TOP = "top";
0216:
0217: private static final String ITALICS = "italic";
0218:
0219: private static final String BOLD = "bold";
0220:
0221: private static final String SIZE = "size";
0222:
0223: private static final String VALIDATOR = "validator";
0224:
0225: private static final String PROCESSOR = "processor";
0226:
0227: private static final String CLASS = "class";
0228:
0229: private static final String FIELD_LABEL = "label";
0230:
0231: private static final String TITLE_FIELD = "title";
0232:
0233: private static final String TEXT_FIELD = "text";
0234:
0235: private static final String TEXT_SIZE = "size";
0236:
0237: private static final String STATIC_TEXT = "staticText";
0238:
0239: private static final String COMBO_FIELD = "combo";
0240:
0241: private static final String COMBO_CHOICE = "choice";
0242:
0243: private static final String COMBO_VALUE = "value";
0244:
0245: private static final String RADIO_FIELD = "radio";
0246:
0247: private static final String RADIO_CHOICE = "choice";
0248:
0249: private static final String RADIO_VALUE = "value";
0250:
0251: private static final String SPACE_FIELD = "space";
0252:
0253: private static final String DIVIDER_FIELD = "divider";
0254:
0255: private static final String CHECK_FIELD = "check";
0256:
0257: private static final String RULE_FIELD = "rule";
0258:
0259: private static final String RULE_LAYOUT = "layout";
0260:
0261: private static final String RULE_SEPARATOR = "separator";
0262:
0263: private static final String RULE_RESULT_FORMAT = "resultFormat";
0264:
0265: private static final String RULE_PLAIN_STRING = "plainString";
0266:
0267: private static final String RULE_DISPLAY_FORMAT = "displayFormat";
0268:
0269: private static final String RULE_SPECIAL_SEPARATOR = "specialSeparator";
0270:
0271: private static final String RULE_ENCRYPTED = "processed";
0272:
0273: private static final String RULE_PARAM_NAME = "name";
0274:
0275: private static final String RULE_PARAM_VALUE = "value";
0276:
0277: private static final String RULE_PARAM = "param";
0278:
0279: private static final String PWD_FIELD = "password";
0280:
0281: private static final String PWD_INPUT = "pwd";
0282:
0283: private static final String PWD_SIZE = "size";
0284:
0285: private static final String SEARCH_FIELD = "search";
0286:
0287: private static final String FILE_FIELD = "file";
0288:
0289: private static final String DIR_FIELD = "dir";
0290:
0291: // internal value for the button used to trigger autodetection
0292: private static final String SEARCH_BUTTON_FIELD = "autodetect";
0293:
0294: private static final String SEARCH_CHOICE = "choice";
0295:
0296: private static final String SEARCH_FILENAME = "filename";
0297:
0298: private static final String SEARCH_RESULT = "result";
0299:
0300: private static final String SEARCH_VALUE = "value";
0301:
0302: private static final String SEARCH_TYPE = "type";
0303:
0304: private static final String SEARCH_FILE = "file";
0305:
0306: private static final String SEARCH_DIRECTORY = "directory";
0307:
0308: private static final String SEARCH_PARENTDIR = "parentdir";
0309:
0310: private static final String SEARCH_CHECKFILENAME = "checkfilename";
0311:
0312: private static final String SELECTEDPACKS = "createForPack"; // renamed
0313:
0314: private static final String UNSELECTEDPACKS = "createForUnselectedPack"; // new
0315:
0316: protected static final String ATTRIBUTE_CONDITIONID_NAME = "conditionid";
0317:
0318: protected static final String VARIABLE_NODE = "variable";
0319:
0320: protected static final String ATTRIBUTE_VARIABLE_NAME = "name";
0321:
0322: protected static final String ATTRIBUTE_VARIABLE_VALUE = "value";
0323:
0324: // node
0325:
0326: private static final String NAME = "name";
0327:
0328: private static final String OS = "os";
0329:
0330: private static final String FAMILY = "family";
0331:
0332: private static final String FIELD_BUTTON = "button";
0333:
0334: // ------------------------------------------------------------------------
0335: // Variable Declarations
0336: // ------------------------------------------------------------------------
0337: private static int instanceCount = 0;
0338:
0339: protected int instanceNumber = 0;
0340:
0341: /**
0342: * If there is a possibility that some UI elements will not get added we can not allow to go
0343: * back to the PacksPanel, because the process of building the UI is not reversable. This
0344: * variable keeps track if any packs have been defined and will be used to make a decision for
0345: * locking the 'previous' button.
0346: */
0347: private boolean packsDefined = false;
0348:
0349: private InstallerFrame parentFrame;
0350:
0351: /** The parsed result from reading the XML specification from the file */
0352: private XMLElement spec;
0353:
0354: private boolean haveSpec = false;
0355:
0356: /** Holds the references to all of the UI elements */
0357: private Vector<Object[]> uiElements = new Vector<Object[]>();
0358:
0359: /** Holds the references to all radio button groups */
0360: private Vector<ButtonGroup> buttonGroups = new Vector<ButtonGroup>();
0361:
0362: /** Holds the references to all password field groups */
0363: private Vector<PasswordGroup> passwordGroups = new Vector<PasswordGroup>();
0364:
0365: /**
0366: * used for temporary storage of references to password groups that have already been read in a
0367: * given read cycle.
0368: */
0369: private Vector passwordGroupsRead = new Vector();
0370:
0371: /** Used to track search fields. Contains SearchField references. */
0372: private Vector<SearchField> searchFields = new Vector<SearchField>();
0373:
0374: /** Holds all user inputs for use in automated installation */
0375: private Vector<TextValuePair> entries = new Vector<TextValuePair>();
0376:
0377: private LocaleDatabase langpack = null;
0378:
0379: // Used for dynamic controls to skip content validation unless the user
0380: // really clicks "Next"
0381: private boolean validating = true;
0382:
0383: /*--------------------------------------------------------------------------*/
0384: // This method can be used to search for layout problems. If this class is
0385: // compiled with this method uncommented, the layout guides will be shown
0386: // on the panel, making it possible to see if all components are placed
0387: // correctly.
0388: /*--------------------------------------------------------------------------*/
0389: // public void paint (Graphics graphics)
0390: // {
0391: // super.paint (graphics);
0392: // layout.showRules ((Graphics2D)graphics, Color.red);
0393: // }
0394: /*--------------------------------------------------------------------------*/
0395: /**
0396: * Constructs a <code>UserInputPanel</code>.
0397: *
0398: * @param parent reference to the application frame
0399: * @param installData shared information about the installation
0400: */
0401: /*--------------------------------------------------------------------------*/
0402: public UserInputPanel(InstallerFrame parent, InstallData installData) {
0403: super (parent, installData);
0404: instanceNumber = instanceCount++;
0405: this .parentFrame = parent;
0406: }
0407:
0408: protected void init() {
0409:
0410: TwoColumnLayout layout;
0411: super .removeAll();
0412: uiElements.clear();
0413:
0414: // ----------------------------------------------------
0415: // get a locale database
0416: // ----------------------------------------------------
0417: try {
0418: // this.langpack = parent.langpack;
0419:
0420: String resource = LANG_FILE_NAME + "_" + idata.localeISO3;
0421: this .langpack = new LocaleDatabase(ResourceManager
0422: .getInstance().getInputStream(resource));
0423: } catch (Throwable exception) {
0424: }
0425:
0426: // ----------------------------------------------------
0427: // read the specifications
0428: // ----------------------------------------------------
0429: try {
0430: readSpec();
0431: } catch (Throwable exception) {
0432: // log the problem
0433: exception.printStackTrace();
0434: }
0435:
0436: // ----------------------------------------------------
0437: // Set the topBuffer from the attribute. topBuffer=0 is useful
0438: // if you don't want your panel to be moved up and down during
0439: // dynamic validation (showing and hiding components within the
0440: // same panel)
0441: // ----------------------------------------------------
0442: int topbuff = 25;
0443: try {
0444: topbuff = Integer.parseInt(spec.getAttribute(TOPBUFFER));
0445: } catch (Exception ex) {
0446: } finally {
0447: layout = new TwoColumnLayout(10, 5, 30, topbuff,
0448: TwoColumnLayout.LEFT);
0449: }
0450: setLayout(layout);
0451:
0452: if (!haveSpec) {
0453: // return if we could not read the spec. further
0454: // processing will only lead to problems. In this
0455: // case we must skip the panel when it gets activated.
0456: return;
0457: }
0458:
0459: // refresh variables specified in spec
0460: updateVariables();
0461:
0462: // ----------------------------------------------------
0463: // process all field nodes. Each field node is analyzed
0464: // for its type, then an appropriate memeber function
0465: // is called that will create the correct UI elements.
0466: // ----------------------------------------------------
0467: Vector<XMLElement> fields = spec
0468: .getChildrenNamed(FIELD_NODE_ID);
0469:
0470: for (int i = 0; i < fields.size(); i++) {
0471: XMLElement field = fields.elementAt(i);
0472: String attribute = field.getAttribute(TYPE);
0473: String conditionid = field
0474: .getAttribute(ATTRIBUTE_CONDITIONID_NAME);
0475: if (conditionid != null) {
0476: // check if condition is fulfilled
0477: if (!this .parent.getRules().isConditionTrue(
0478: conditionid, idata.getVariables())) {
0479: continue;
0480: }
0481: }
0482: if (attribute != null) {
0483: if (attribute.equals(RULE_FIELD)) {
0484: addRuleField(field);
0485: } else if (attribute.equals(TEXT_FIELD)) {
0486: addTextField(field);
0487: } else if (attribute.equals(COMBO_FIELD)) {
0488: addComboBox(field);
0489: } else if (attribute.equals(RADIO_FIELD)) {
0490: addRadioButton(field);
0491: } else if (attribute.equals(PWD_FIELD)) {
0492: addPasswordField(field);
0493: } else if (attribute.equals(SPACE_FIELD)) {
0494: addSpace(field);
0495: } else if (attribute.equals(DIVIDER_FIELD)) {
0496: addDivider(field);
0497: } else if (attribute.equals(CHECK_FIELD)) {
0498: addCheckBox(field);
0499: } else if (attribute.equals(STATIC_TEXT)) {
0500: addText(field);
0501: } else if (attribute.equals(TITLE_FIELD)) {
0502: addTitle(field);
0503: } else if (attribute.equals(SEARCH_FIELD)) {
0504: addSearch(field);
0505: } else if (attribute.equals(FILE_FIELD)) {
0506: addFileField(field);
0507: } else if (attribute.equals(DIR_FIELD)) {
0508: addDirectoryField(field);
0509: }
0510: }
0511: }
0512: }
0513:
0514: private void addDirectoryField(XMLElement field) {
0515: Vector<XMLElement> forPacks = field
0516: .getChildrenNamed(SELECTEDPACKS);
0517: Vector<XMLElement> forOs = field.getChildrenNamed(OS);
0518:
0519: JLabel label;
0520: String set;
0521: int size;
0522:
0523: String filter = null;
0524: String filterdesc = null;
0525:
0526: String variable = field.getAttribute(VARIABLE);
0527: if ((variable == null) || (variable.length() == 0)) {
0528: return;
0529: }
0530:
0531: XMLElement element = field.getFirstChildNamed(SPEC);
0532: if (element == null) {
0533: Debug.trace("Error: no spec element defined in file field");
0534: return;
0535: } else {
0536: label = new JLabel(getText(element));
0537: // ----------------------------------------------------
0538: // extract the specification details
0539: // ----------------------------------------------------
0540: set = element.getAttribute(SET);
0541: if (set == null) {
0542: set = idata.getVariable(variable);
0543: if (set == null) {
0544: set = "";
0545: }
0546: } else {
0547: if (set != null && !"".equals(set)) {
0548: VariableSubstitutor vs = new VariableSubstitutor(
0549: idata.getVariables());
0550: set = vs.substitute(set, null);
0551: }
0552: }
0553:
0554: try {
0555: size = Integer
0556: .parseInt(element.getAttribute(TEXT_SIZE));
0557: } catch (Throwable exception) {
0558: size = 1;
0559: }
0560:
0561: filter = element.getAttribute("fileext");
0562: if (filter == null) {
0563: filter = "";
0564: }
0565: filterdesc = element.getAttribute("fileextdesc");
0566: if (filterdesc == null) {
0567: filterdesc = "";
0568: }
0569: // internationalize it
0570: filterdesc = idata.langpack.getString(filterdesc);
0571: }
0572:
0573: final JTextField filetxt = new JTextField(set, size);
0574: filetxt.setCaretPosition(0);
0575:
0576: TwoColumnConstraints constraints = new TwoColumnConstraints();
0577: constraints.position = TwoColumnConstraints.WEST;
0578:
0579: uiElements.add(new Object[] { null, FIELD_LABEL, null,
0580: constraints, label, forPacks, forOs });
0581:
0582: TwoColumnConstraints constraints2 = new TwoColumnConstraints();
0583: constraints2.position = TwoColumnConstraints.EAST;
0584:
0585: // TODO: use separate key for button text
0586: JButton button = ButtonFactory.createButton(idata.langpack
0587: .getString("UserInputPanel.search.browse"),
0588: idata.buttonsHColor);
0589: button.addActionListener(new ActionListener() {
0590: public void actionPerformed(ActionEvent e) {
0591: System.out.println("Show dirchooser");
0592: JFileChooser filechooser = new JFileChooser();
0593: filechooser
0594: .setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
0595:
0596: if (filechooser.showOpenDialog(parentFrame) == JFileChooser.APPROVE_OPTION) {
0597: filetxt.setText(filechooser.getSelectedFile()
0598: .getAbsolutePath());
0599: }
0600: }
0601: });
0602: JPanel panel = new JPanel();
0603: panel.add(filetxt);
0604: panel.add(button);
0605: uiElements.add(new Object[] { null, DIR_FIELD, variable,
0606: constraints2, panel, forPacks, forOs });
0607:
0608: }
0609:
0610: private void addFileField(XMLElement field) {
0611: Vector<XMLElement> forPacks = field
0612: .getChildrenNamed(SELECTEDPACKS);
0613: Vector<XMLElement> forOs = field.getChildrenNamed(OS);
0614:
0615: JLabel label;
0616: String set;
0617: int size;
0618:
0619: String filter = null;
0620: String filterdesc = null;
0621:
0622: String variable = field.getAttribute(VARIABLE);
0623: if ((variable == null) || (variable.length() == 0)) {
0624: return;
0625: }
0626:
0627: XMLElement element = field.getFirstChildNamed(SPEC);
0628: if (element == null) {
0629: Debug.trace("Error: no spec element defined in file field");
0630: return;
0631: } else {
0632: label = new JLabel(getText(element));
0633: // ----------------------------------------------------
0634: // extract the specification details
0635: // ----------------------------------------------------
0636: set = element.getAttribute(SET);
0637: if (set == null) {
0638: set = idata.getVariable(variable);
0639: if (set == null) {
0640: set = "";
0641: }
0642: } else {
0643: if (set != null && !"".equals(set)) {
0644: VariableSubstitutor vs = new VariableSubstitutor(
0645: idata.getVariables());
0646: set = vs.substitute(set, null);
0647: }
0648: }
0649:
0650: try {
0651: size = Integer
0652: .parseInt(element.getAttribute(TEXT_SIZE));
0653: } catch (Throwable exception) {
0654: size = 1;
0655: }
0656:
0657: filter = element.getAttribute("fileext");
0658: if (filter == null) {
0659: filter = "";
0660: }
0661: filterdesc = element.getAttribute("fileextdesc");
0662: if (filterdesc == null) {
0663: filterdesc = "";
0664: }
0665: // internationalize it
0666: filterdesc = idata.langpack.getString(filterdesc);
0667: }
0668:
0669: final JTextField filetxt = new JTextField(set, size);
0670: filetxt.setCaretPosition(0);
0671:
0672: TwoColumnConstraints constraints = new TwoColumnConstraints();
0673: constraints.position = TwoColumnConstraints.WEST;
0674:
0675: uiElements.add(new Object[] { null, FIELD_LABEL, null,
0676: constraints, label, forPacks, forOs });
0677:
0678: TwoColumnConstraints constraints2 = new TwoColumnConstraints();
0679: constraints2.position = TwoColumnConstraints.EAST;
0680:
0681: final UserInputFileFilter uiff = new UserInputFileFilter();
0682: uiff.setFileExt(filter);
0683: uiff.setFileExtDesc(filterdesc);
0684:
0685: // TODO: use separate key for button text
0686: JButton button = ButtonFactory.createButton(idata.langpack
0687: .getString("UserInputPanel.search.browse"),
0688: idata.buttonsHColor);
0689: button.addActionListener(new ActionListener() {
0690: public void actionPerformed(ActionEvent e) {
0691: System.out.println("Show filechooser");
0692: JFileChooser filechooser = new JFileChooser();
0693: filechooser
0694: .setFileSelectionMode(JFileChooser.FILES_ONLY);
0695: filechooser.setFileFilter(uiff);
0696:
0697: if (filechooser.showOpenDialog(parentFrame) == JFileChooser.APPROVE_OPTION) {
0698: filetxt.setText(filechooser.getSelectedFile()
0699: .getAbsolutePath());
0700: }
0701: }
0702: });
0703: JPanel panel = new JPanel();
0704: panel.add(filetxt);
0705: panel.add(button);
0706: uiElements.add(new Object[] { null, FILE_FIELD, variable,
0707: constraints2, panel, forPacks, forOs });
0708: }
0709:
0710: protected void updateUIElements() {
0711: boolean updated = false;
0712: VariableSubstitutor vs = new VariableSubstitutor(idata
0713: .getVariables());
0714:
0715: for (int i = 0; i < uiElements.size(); i++) {
0716: Object[] element = uiElements.get(i);
0717: if (element[POS_VARIABLE] == null) {
0718: continue;
0719: }
0720: String value = idata
0721: .getVariable((String) element[POS_VARIABLE]);
0722:
0723: if (RADIO_FIELD.equals(element[POS_TYPE])) {
0724: // we have a radio field, which should be updated
0725: JRadioButton choice = (JRadioButton) element[POS_FIELD];
0726: if (value == null) {
0727: continue;
0728: }
0729: if (value.equals(element[POS_TRUE])) {
0730: choice.setSelected(true);
0731: } else {
0732: choice.setSelected(false);
0733: }
0734: element[POS_FIELD] = choice;
0735: } else if (TEXT_FIELD.equals(element[POS_TYPE])) {
0736: // update TextField
0737: TextInputField textf = (TextInputField) element[POS_FIELD];
0738:
0739: if (value == null) {
0740: value = textf.getText();
0741: }
0742: textf.setText(vs.substitute(value, null));
0743: element[POS_FIELD] = textf;
0744: } else if (CHECK_FIELD.equals(element[POS_TYPE])) {
0745: // TODO: HAS TO BE IMPLEMENTED
0746: } else if (SEARCH_FIELD.equals(element[POS_TYPE])) {
0747: // TODO: HAS TO BE IMPLEMENTED
0748: } else if (RULE_FIELD.equals(element[POS_TYPE])) {
0749:
0750: RuleInputField rulef = (RuleInputField) element[POS_FIELD];
0751: // System.out.println("RuleInputField: " + value);
0752: if (value == null) {
0753: value = rulef.getText();
0754: }
0755: } else if (FIELD_BUTTON.equals(element[POS_TYPE])) {
0756: // nothing to do
0757: }
0758: // overwrite entry;
0759: uiElements.set(i, element);
0760: updated = true;
0761: }
0762: if (updated) {
0763: // super.removeAll();
0764: super .invalidate();
0765: // buildUI();
0766: }
0767: }
0768:
0769: /*--------------------------------------------------------------------------*/
0770: /**
0771: * Indicates wether the panel has been validated or not. The installer won't let the user go
0772: * further through the installation process until the panel is validated. Default behavior is to
0773: * return true.
0774: *
0775: * @return A boolean stating wether the panel has been validated or not.
0776: */
0777: /*--------------------------------------------------------------------------*/
0778: public boolean isValidated() {
0779: return readInput();
0780: }
0781:
0782: /*--------------------------------------------------------------------------*/
0783: /**
0784: * This method is called when the panel becomes active.
0785: */
0786: /*--------------------------------------------------------------------------*/
0787: public void panelActivate() {
0788: this .init();
0789:
0790: if (spec == null) {
0791: // TODO: translate
0792: emitError(
0793: "User input specification could not be found.",
0794: "The specification for the user input panel could not be found. Please contact the packager.");
0795: parentFrame.skipPanel();
0796: }
0797: // update UI with current values of associated variables
0798: updateUIElements();
0799: Vector<XMLElement> forPacks = spec
0800: .getChildrenNamed(SELECTEDPACKS);
0801: Vector<XMLElement> forUnselectedPacks = spec
0802: .getChildrenNamed(UNSELECTEDPACKS);
0803: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
0804:
0805: if (!itemRequiredFor(forPacks)
0806: || !itemRequiredForUnselected(forUnselectedPacks)
0807: || !itemRequiredForOs(forOs)) {
0808: parentFrame.skipPanel();
0809: return;
0810: }
0811: if (!haveSpec) {
0812: parentFrame.skipPanel();
0813: return;
0814: }
0815: // if (uiBuilt)
0816: // {
0817: // return;
0818: // }
0819:
0820: buildUI();
0821: //need a validation, else ui is scrambled
0822:
0823: this .setSize(this .getMaximumSize().width,
0824: this .getMaximumSize().height);
0825: validate();
0826: if (packsDefined) {
0827: parentFrame.lockPrevButton();
0828: }
0829: }
0830:
0831: /*--------------------------------------------------------------------------*/
0832: /**
0833: * Asks the panel to set its own XML data that can be brought back for an automated installation
0834: * process. Use it as a blackbox if your panel needs to do something even in automated mode.
0835: *
0836: * @param panelRoot The XML root element of the panels blackbox tree.
0837: */
0838: /*--------------------------------------------------------------------------*/
0839: public void makeXMLData(XMLElement panelRoot) {
0840: Map<String, String> entryMap = new HashMap<String, String>();
0841:
0842: for (int i = 0; i < entries.size(); i++) {
0843: TextValuePair pair = entries.elementAt(i);
0844: entryMap.put(pair.toString(), pair.getValue());
0845: }
0846:
0847: new UserInputPanelAutomationHelper(entryMap).makeXMLData(idata,
0848: panelRoot);
0849: }
0850:
0851: /*--------------------------------------------------------------------------*/
0852: /**
0853: * Builds the UI and makes it ready for display
0854: */
0855: /*--------------------------------------------------------------------------*/
0856: private void buildUI() {
0857: Object[] uiElement;
0858:
0859: for (int i = 0; i < uiElements.size(); i++) {
0860: uiElement = uiElements.elementAt(i);
0861:
0862: if (itemRequiredFor((Vector<XMLElement>) uiElement[POS_PACKS])
0863: && itemRequiredForOs((Vector<XMLElement>) uiElement[POS_OS])) {
0864: try {
0865: if (uiElement[POS_DISPLAYED] == null
0866: || "false".equals(uiElement[POS_DISPLAYED]
0867: .toString())) {
0868: add((JComponent) uiElement[POS_FIELD],
0869: uiElement[POS_CONSTRAINTS]);
0870: }
0871:
0872: uiElement[POS_DISPLAYED] = true;
0873: uiElements.remove(i);
0874: uiElements.add(i, uiElement);
0875: } catch (Throwable exception) {
0876: System.out
0877: .println("Internal format error in field: "
0878: + uiElement[POS_TYPE].toString()); // !!! logging
0879: }
0880: } else {
0881: try {
0882: if (uiElement[POS_DISPLAYED] != null
0883: && "true".equals(uiElement[POS_DISPLAYED]
0884: .toString())) {
0885: remove((JComponent) uiElement[POS_FIELD]);
0886: }
0887: } catch (Throwable exception) {
0888: System.out
0889: .println("Internal format error in field: "
0890: + uiElement[POS_TYPE].toString()); // !!! logging
0891: }
0892: uiElement[POS_DISPLAYED] = false;
0893: uiElements.remove(i);
0894: uiElements.add(i, uiElement);
0895: }
0896: }
0897: }
0898:
0899: /*--------------------------------------------------------------------------*/
0900: /**
0901: * Reads the input data from all UI elements and sets the associated variables.
0902: *
0903: * @return <code>true</code> if the operation is successdul, otherwise <code>false</code>.
0904: */
0905: /*--------------------------------------------------------------------------*/
0906: private boolean readInput() {
0907: boolean success;
0908: String fieldType = null;
0909: Object[] field = null;
0910:
0911: passwordGroupsRead.clear();
0912: // ----------------------------------------------------
0913: // cycle through all but the password fields and read
0914: // their contents
0915: // ----------------------------------------------------
0916: for (int i = 0; i < uiElements.size(); i++) {
0917: field = uiElements.elementAt(i);
0918:
0919: if ((field != null) && ((Boolean) field[POS_DISPLAYED])) {
0920: fieldType = (String) (field[POS_TYPE]);
0921:
0922: // ------------------------------------------------
0923: if (fieldType.equals(RULE_FIELD)) {
0924: success = readRuleField(field);
0925: if (!success) {
0926: return (false);
0927: }
0928: }
0929:
0930: // ------------------------------------------------
0931: if (fieldType.equals(PWD_FIELD)) {
0932: success = readPasswordField(field);
0933: if (!success) {
0934: return (false);
0935: }
0936: }
0937:
0938: // ------------------------------------------------
0939: else if (fieldType.equals(TEXT_FIELD)) {
0940: success = readTextField(field);
0941: if (!success) {
0942: return (false);
0943: }
0944: }
0945:
0946: // ------------------------------------------------
0947: else if (fieldType.equals(COMBO_FIELD)) {
0948: success = readComboBox(field);
0949: if (!success) {
0950: return (false);
0951: }
0952: }
0953:
0954: // ------------------------------------------------
0955: else if (fieldType.equals(RADIO_FIELD)) {
0956: success = readRadioButton(field);
0957: if (!success) {
0958: return (false);
0959: }
0960: }
0961:
0962: // ------------------------------------------------
0963: else if (fieldType.equals(CHECK_FIELD)) {
0964: success = readCheckBox(field);
0965: if (!success) {
0966: return (false);
0967: }
0968: } else if (fieldType.equals(SEARCH_FIELD)) {
0969: success = readSearch(field);
0970: if (!success) {
0971: return (false);
0972: }
0973: } else if (fieldType.equals(FILE_FIELD)) {
0974: success = readFileField(field);
0975: if (!success) {
0976: return (false);
0977: }
0978: } else if (fieldType.equals(DIR_FIELD)) {
0979: success = readDirectoryField(field);
0980: if (!success) {
0981: return (false);
0982: }
0983: }
0984: }
0985: }
0986:
0987: return (true);
0988: }
0989:
0990: private boolean readDirectoryField(Object[] field) {
0991: try {
0992: JPanel panel = (JPanel) field[POS_FIELD];
0993: JTextField textf = (JTextField) panel.getComponent(0);
0994: String file = textf.getText();
0995: if (file != null) {
0996: File ffile = new File(file);
0997: if (ffile.isDirectory()) {
0998: idata.setVariable((String) field[POS_VARIABLE],
0999: file);
1000: entries.add(new TextValuePair(
1001: (String) field[POS_VARIABLE], file));
1002: return true;
1003: } else {
1004: showMessage("dir.notdirectory");
1005: return false;
1006: }
1007: } else {
1008: showMessage("dir.nodirectory");
1009: return false;
1010: }
1011: } catch (Exception e) {
1012: if (Debug.stackTracing()) {
1013: Debug.trace(e);
1014: }
1015: return false;
1016: }
1017: }
1018:
1019: private void showMessage(String messageType) {
1020: JOptionPane.showMessageDialog(parent,
1021: parent.langpack.getString("UserInputPanel."
1022: + messageType + ".message"), parent.langpack
1023: .getString("UserInputPanel." + messageType
1024: + ".caption"),
1025: JOptionPane.WARNING_MESSAGE);
1026: }
1027:
1028: private boolean readFileField(Object[] field) {
1029: try {
1030: JPanel panel = (JPanel) field[POS_FIELD];
1031: JTextField textf = (JTextField) panel.getComponent(0);
1032: String file = textf.getText();
1033: if (file != null) {
1034: File ffile = new File(file);
1035: if (ffile.isFile()) {
1036: idata.setVariable((String) field[POS_VARIABLE],
1037: file);
1038: entries.add(new TextValuePair(
1039: (String) field[POS_VARIABLE], file));
1040: return true;
1041: } else {
1042: showMessage("file.notfile");
1043: return false;
1044: }
1045: } else {
1046: showMessage("file.nofile");
1047: return false;
1048: }
1049: } catch (Exception e) {
1050: if (Debug.stackTracing()) {
1051: Debug.trace(e);
1052: }
1053: return false;
1054: }
1055: }
1056:
1057: /*--------------------------------------------------------------------------*/
1058: /**
1059: * Reads the XML specification for the panel layout. The result is stored in spec.
1060: *
1061: * @exception Exception for any problems in reading the specification
1062: */
1063: /*--------------------------------------------------------------------------*/
1064: private void readSpec() throws Exception {
1065: InputStream input = null;
1066: XMLElement data;
1067: Vector<XMLElement> specElements;
1068: String attribute;
1069: String panelattribute;
1070: String instance = Integer.toString(instanceNumber);
1071:
1072: String panelid = null;
1073: Panel p = this .getMetadata();
1074: if (p != null) {
1075: panelid = p.getPanelid();
1076: }
1077: try {
1078: input = parentFrame.getResource(SPEC_FILE_NAME);
1079: } catch (Exception exception) {
1080: haveSpec = false;
1081: return;
1082: }
1083: if (input == null) {
1084: haveSpec = false;
1085: return;
1086: }
1087:
1088: // initialize the parser
1089: StdXMLParser parser = new StdXMLParser();
1090: parser.setBuilder(XMLBuilderFactory.createXMLBuilder());
1091: parser.setValidator(new NonValidator());
1092: parser.setReader(new StdXMLReader(input));
1093:
1094: // get the data
1095: data = (XMLElement) parser.parse();
1096:
1097: // extract the spec to this specific panel instance
1098: if (data.hasChildren()) {
1099: specElements = data.getChildrenNamed(NODE_ID);
1100: for (int i = 0; i < specElements.size(); i++) {
1101: data = specElements.elementAt(i);
1102: attribute = data.getAttribute(INSTANCE_IDENTIFIER);
1103: panelattribute = data.getAttribute(PANEL_IDENTIFIER);
1104:
1105: if (((attribute != null) && instance.equals(attribute))
1106: || ((panelattribute != null)
1107: && (panelid != null) && (panelid
1108: .equals(panelattribute)))) {
1109: // use the current element as spec
1110: spec = data;
1111: // close the stream
1112: input.close();
1113: haveSpec = true;
1114: return;
1115: }
1116: }
1117:
1118: haveSpec = false;
1119: return;
1120: }
1121:
1122: haveSpec = false;
1123: }
1124:
1125: /*--------------------------------------------------------------------------*/
1126: /**
1127: * Adds the title to the panel. There can only be one title, if mutiple titles are defined, they
1128: * keep overwriting what has already be defined, so that the last definition is the one that
1129: * prevails.
1130: *
1131: * @param spec a <code>XMLElement</code> containing the specification for the title.
1132: */
1133: /*--------------------------------------------------------------------------*/
1134: private void addTitle(XMLElement spec) {
1135: String title = getText(spec);
1136: boolean italic = getBoolean(spec, ITALICS, false);
1137: boolean bold = getBoolean(spec, BOLD, false);
1138: float multiplier = getFloat(spec, SIZE, 2.0f);
1139: int justify = getAlignment(spec);
1140:
1141: String icon = getIconName(spec);
1142:
1143: if (title != null) {
1144: JLabel label = null;
1145: ImageIcon imgicon = null;
1146: try {
1147: imgicon = parent.icons.getImageIcon(icon);
1148: label = LabelFactory.create(title, imgicon,
1149: JLabel.TRAILING, true);
1150: } catch (Exception e) {
1151: Debug.trace("Icon " + icon
1152: + " not found in icon list. " + e.getMessage());
1153: label = LabelFactory.create(title);
1154: }
1155: Font font = label.getFont();
1156: float size = font.getSize();
1157: int style = 0;
1158:
1159: if (bold) {
1160: style += Font.BOLD;
1161: }
1162: if (italic) {
1163: style += Font.ITALIC;
1164: }
1165:
1166: font = font.deriveFont(style, (size * multiplier));
1167: label.setFont(font);
1168: label.setAlignmentX(0);
1169:
1170: TwoColumnConstraints constraints = new TwoColumnConstraints();
1171: constraints.align = justify;
1172: constraints.position = TwoColumnConstraints.NORTH;
1173:
1174: add(label, constraints);
1175: }
1176: }
1177:
1178: protected String getIconName(XMLElement element) {
1179: if (element == null) {
1180: return (null);
1181: }
1182:
1183: String key = element.getAttribute(ICON_KEY);
1184: String text = null;
1185: if ((key != null) && (langpack != null)) {
1186: try {
1187: text = langpack.getString(key);
1188: } catch (Throwable exception) {
1189: text = null;
1190: }
1191: }
1192:
1193: return (text);
1194: }
1195:
1196: /*--------------------------------------------------------------------------*/
1197: /**
1198: * Adds a rule field to the list of UI elements.
1199: *
1200: * @param spec a <code>XMLElement</code> containing the specification for the rule field.
1201: */
1202: /*--------------------------------------------------------------------------*/
1203: private void addRuleField(XMLElement spec) {
1204: Vector<XMLElement> forPacks = spec
1205: .getChildrenNamed(SELECTEDPACKS);
1206: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
1207: XMLElement element = spec.getFirstChildNamed(SPEC);
1208: String variable = spec.getAttribute(VARIABLE);
1209: RuleInputField field = null;
1210: JLabel label;
1211: String layout;
1212: String set;
1213: String separator;
1214: String format;
1215: String validator = null;
1216: String message = null;
1217: boolean hasParams = false;
1218: String paramName = null;
1219: String paramValue = null;
1220: HashMap<String, String> validateParamMap = null;
1221: Vector<XMLElement> validateParams = null;
1222: String processor = null;
1223: int resultFormat = RuleInputField.DISPLAY_FORMAT;
1224:
1225: // ----------------------------------------------------
1226: // extract the specification details
1227: // ----------------------------------------------------
1228: if (element != null) {
1229: label = new JLabel(getText(element));
1230: layout = element.getAttribute(RULE_LAYOUT);
1231: set = element.getAttribute(SET);
1232:
1233: // retrieve value of variable if not specified
1234: // (does not work here because of special format for set attribute)
1235: // if (set == null)
1236: // {
1237: // set = idata.getVariable (variable);
1238: // }
1239:
1240: separator = element.getAttribute(RULE_SEPARATOR);
1241: format = element.getAttribute(RULE_RESULT_FORMAT);
1242:
1243: if (format != null) {
1244: if (format.equals(RULE_PLAIN_STRING)) {
1245: resultFormat = RuleInputField.PLAIN_STRING;
1246: } else if (format.equals(RULE_DISPLAY_FORMAT)) {
1247: resultFormat = RuleInputField.DISPLAY_FORMAT;
1248: } else if (format.equals(RULE_SPECIAL_SEPARATOR)) {
1249: resultFormat = RuleInputField.SPECIAL_SEPARATOR;
1250: } else if (format.equals(RULE_ENCRYPTED)) {
1251: resultFormat = RuleInputField.ENCRYPTED;
1252: }
1253: }
1254: }
1255: // ----------------------------------------------------
1256: // if there is no specification element, return without
1257: // doing anything.
1258: // ----------------------------------------------------
1259: else {
1260: return;
1261: }
1262:
1263: // ----------------------------------------------------
1264: // get the description and add it to the list of UI
1265: // elements if it exists.
1266: // ----------------------------------------------------
1267: element = spec.getFirstChildNamed(DESCRIPTION);
1268: addDescription(element, forPacks, forOs);
1269:
1270: // ----------------------------------------------------
1271: // get the validator and processor if they are defined
1272: // ----------------------------------------------------
1273: element = spec.getFirstChildNamed(VALIDATOR);
1274: if (element != null) {
1275: validator = element.getAttribute(CLASS);
1276: message = getText(element);
1277: // ----------------------------------------------------------
1278: // check and see if we have any parameters for this validator.
1279: // If so, then add them to validateParamMap.
1280: // ----------------------------------------------------------
1281: validateParams = element.getChildrenNamed(RULE_PARAM);
1282: if (validateParams != null && validateParams.size() > 0) {
1283: hasParams = true;
1284:
1285: if (validateParamMap == null)
1286: validateParamMap = new HashMap<String, String>();
1287:
1288: for (XMLElement validateParam : validateParams) {
1289: element = validateParam;
1290: paramName = element.getAttribute(RULE_PARAM_NAME);
1291: paramValue = element.getAttribute(RULE_PARAM_VALUE);
1292: validateParamMap.put(paramName, paramValue);
1293: }
1294:
1295: }
1296:
1297: }
1298:
1299: element = spec.getFirstChildNamed(PROCESSOR);
1300: if (element != null) {
1301: processor = element.getAttribute(CLASS);
1302: }
1303:
1304: // ----------------------------------------------------
1305: // create an instance of RuleInputField based on the
1306: // extracted specifications, then add it to the list
1307: // of UI elements.
1308: // ----------------------------------------------------
1309: if (hasParams) {
1310: field = new RuleInputField(layout, set, separator,
1311: validator, validateParamMap, processor,
1312: resultFormat, getToolkit(), idata);
1313: } else {
1314: field = new RuleInputField(layout, set, separator,
1315: validator, processor, resultFormat, getToolkit(),
1316: idata);
1317:
1318: }
1319: TwoColumnConstraints constraints = new TwoColumnConstraints();
1320: constraints.position = TwoColumnConstraints.WEST;
1321:
1322: uiElements.add(new Object[] { null, FIELD_LABEL, null,
1323: constraints, label, forPacks, forOs });
1324:
1325: TwoColumnConstraints constraints2 = new TwoColumnConstraints();
1326: constraints2.position = TwoColumnConstraints.EAST;
1327:
1328: uiElements.add(new Object[] { null, RULE_FIELD, variable,
1329: constraints2, field, forPacks, forOs, null, null,
1330: message });
1331: }
1332:
1333: /*--------------------------------------------------------------------------*/
1334: /**
1335: * Reads the data from the rule input field and sets the associated variable.
1336: *
1337: * @param field the object array that holds the details of the field.
1338: *
1339: * @return <code>true</code> if there was no problem reading the data or if there was an
1340: * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
1341: * dialog is popped up and <code>false</code> is returned.
1342: */
1343: /*--------------------------------------------------------------------------*/
1344: private boolean readRuleField(Object[] field) {
1345: RuleInputField ruleField = null;
1346: String variable = null;
1347: String message = null;
1348:
1349: try {
1350: ruleField = (RuleInputField) field[POS_FIELD];
1351: variable = (String) field[POS_VARIABLE];
1352: message = (String) field[POS_MESSAGE];
1353: } catch (Throwable exception) {
1354: return (true);
1355: }
1356: if ((variable == null) || (ruleField == null)) {
1357: return (true);
1358: }
1359:
1360: boolean success = !validating || ruleField.validateContents();
1361: if (!success) {
1362: showWarningMessageDialog(parentFrame, message);
1363: return (false);
1364: }
1365:
1366: idata.setVariable(variable, ruleField.getText());
1367: entries.add(new TextValuePair(variable, ruleField.getText()));
1368: return (true);
1369: }
1370:
1371: /*--------------------------------------------------------------------------*/
1372: /**
1373: * Adds a text field to the list of UI elements
1374: *
1375: * @param spec a <code>XMLElement</code> containing the specification for the text field.
1376: */
1377: /*--------------------------------------------------------------------------*/
1378: private void addTextField(XMLElement spec) {
1379: Vector<XMLElement> forPacks = spec
1380: .getChildrenNamed(SELECTEDPACKS);
1381: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
1382: XMLElement element = spec.getFirstChildNamed(SPEC);
1383: JLabel label;
1384: String set;
1385: int size;
1386: HashMap<String, String> validateParamMap = null;
1387: Vector<XMLElement> validateParams = null;
1388: String validator = null;
1389: String message = null;
1390: boolean hasParams = false;
1391: TextInputField inputField;
1392:
1393: String variable = spec.getAttribute(VARIABLE);
1394: if ((variable == null) || (variable.length() == 0)) {
1395: return;
1396: }
1397:
1398: // ----------------------------------------------------
1399: // extract the specification details
1400: // ----------------------------------------------------
1401: if (element != null) {
1402: label = new JLabel(getText(element));
1403: set = element.getAttribute(SET);
1404: if (set == null) {
1405: set = idata.getVariable(variable);
1406: if (set == null) {
1407: set = "";
1408: }
1409: } else {
1410: if (set != null && !"".equals(set)) {
1411: VariableSubstitutor vs = new VariableSubstitutor(
1412: idata.getVariables());
1413: set = vs.substitute(set, null);
1414: }
1415: }
1416:
1417: try {
1418: size = Integer
1419: .parseInt(element.getAttribute(TEXT_SIZE));
1420: } catch (Throwable exception) {
1421: size = 1;
1422: }
1423: }
1424: // ----------------------------------------------------
1425: // if there is no specification element, return without
1426: // doing anything.
1427: // ----------------------------------------------------
1428: else {
1429: return;
1430: }
1431:
1432: // ----------------------------------------------------
1433: // get the validator if was defined
1434: // ----------------------------------------------------
1435: element = spec.getFirstChildNamed(VALIDATOR);
1436: if (element != null) {
1437: validator = element.getAttribute(CLASS);
1438: message = getText(element);
1439: // ----------------------------------------------------------
1440: // check and see if we have any parameters for this validator.
1441: // If so, then add them to validateParamMap.
1442: // ----------------------------------------------------------
1443: validateParams = element.getChildrenNamed(RULE_PARAM);
1444: if (validateParams != null && validateParams.size() > 0) {
1445: hasParams = true;
1446:
1447: if (validateParamMap == null)
1448: validateParamMap = new HashMap<String, String>();
1449:
1450: for (XMLElement validateParam : validateParams) {
1451: element = validateParam;
1452: String paramName = element
1453: .getAttribute(RULE_PARAM_NAME);
1454: String paramValue = element
1455: .getAttribute(RULE_PARAM_VALUE);
1456: validateParamMap.put(paramName, paramValue);
1457: }
1458:
1459: }
1460:
1461: }
1462:
1463: // ----------------------------------------------------
1464: // get the description and add it to the list UI
1465: // elements if it exists.
1466: // ----------------------------------------------------
1467: element = spec.getFirstChildNamed(DESCRIPTION);
1468: addDescription(element, forPacks, forOs);
1469:
1470: // ----------------------------------------------------
1471: // construct the UI element and add it to the list
1472: // ----------------------------------------------------
1473: if (hasParams) {
1474: inputField = new TextInputField(set, size, validator,
1475: validateParamMap);
1476: } else {
1477: inputField = new TextInputField(set, size, validator);
1478: }
1479:
1480: TwoColumnConstraints constraints = new TwoColumnConstraints();
1481: constraints.position = TwoColumnConstraints.WEST;
1482:
1483: uiElements.add(new Object[] { null, FIELD_LABEL, null,
1484: constraints, label, forPacks, forOs });
1485:
1486: TwoColumnConstraints constraints2 = new TwoColumnConstraints();
1487: constraints2.position = TwoColumnConstraints.EAST;
1488:
1489: uiElements.add(new Object[] { null, TEXT_FIELD, variable,
1490: constraints2, inputField, forPacks, forOs, null, null,
1491: message });
1492: }
1493:
1494: /*--------------------------------------------------------------------------*/
1495: /**
1496: * Reads data from the text field and sets the associated variable.
1497: *
1498: * @param field the object array that holds the details of the field.
1499: *
1500: * @return <code>true</code> if there was no problem reading the data or if there was an
1501: * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
1502: * dialog is popped up and <code>false</code> is returned.
1503: */
1504: /*--------------------------------------------------------------------------*/
1505: private boolean readTextField(Object[] field) {
1506: TextInputField textField = null;
1507: String variable = null;
1508: String value = null;
1509: String message = null;
1510:
1511: try {
1512: textField = (TextInputField) field[POS_FIELD];
1513: variable = (String) field[POS_VARIABLE];
1514: message = (String) field[POS_MESSAGE];
1515: value = textField.getText();
1516: } catch (Throwable exception) {
1517: return (true);
1518: }
1519: if ((variable == null) || (value == null)) {
1520: return (true);
1521: }
1522:
1523: // validate the input
1524: boolean success = textField.validateContents();
1525: if (!success) {
1526: showWarningMessageDialog(parentFrame, message);
1527: return (false);
1528: }
1529:
1530: idata.setVariable(variable, value);
1531: entries.add(new TextValuePair(variable, value));
1532: return (true);
1533: }
1534:
1535: /*--------------------------------------------------------------------------*/
1536: /**
1537: * Adds a combo box to the list of UI elements. <br>
1538: * This is a complete example of a valid XML specification
1539: *
1540: * <pre>
1541: *
1542: *
1543: *
1544: * <field type="combo" variable="testVariable">
1545: * <description text="Description for the combo box" id="a key for translated text"/>
1546: * <spec text="label" id="key for the label"/>
1547: * <choice text="choice 1" id="" value="combo box 1"/>
1548: * <choice text="choice 2" id="" value="combo box 2" set="true"/>
1549: * <choice text="choice 3" id="" value="combo box 3"/>
1550: * <choice text="choice 4" id="" value="combo box 4"/>
1551: * </spec>
1552: * </field>
1553: *
1554: *
1555: *
1556: * </pre>
1557: *
1558: * @param spec a <code>XMLElement</code> containing the specification for the combo box.
1559: */
1560: /*--------------------------------------------------------------------------*/
1561: private void addComboBox(XMLElement spec) {
1562: Vector<XMLElement> forPacks = spec
1563: .getChildrenNamed(SELECTEDPACKS);
1564: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
1565: XMLElement element = spec.getFirstChildNamed(SPEC);
1566: String variable = spec.getAttribute(VARIABLE);
1567: TextValuePair listItem = null;
1568: JComboBox field = new JComboBox();
1569: JLabel label;
1570:
1571: boolean userinput = false; // is there already user input?
1572: // ----------------------------------------------------
1573: // extract the specification details
1574: // ----------------------------------------------------
1575: if (element != null) {
1576: label = new JLabel(getText(element));
1577:
1578: Vector<XMLElement> choices = element
1579: .getChildrenNamed(COMBO_CHOICE);
1580:
1581: if (choices == null) {
1582: return;
1583: }
1584: // get current value of associated variable
1585: String currentvariablevalue = idata.getVariable(variable);
1586: if (currentvariablevalue != null) {
1587: // there seems to be user input
1588: userinput = true;
1589: }
1590: for (int i = 0; i < choices.size(); i++) {
1591: String processorClass = (choices.elementAt(i))
1592: .getAttribute("processor");
1593:
1594: if (processorClass != null
1595: && !"".equals(processorClass)) {
1596: String choiceValues = "";
1597: try {
1598: choiceValues = ((Processor) Class.forName(
1599: processorClass).newInstance())
1600: .process(null);
1601: } catch (Throwable t) {
1602: t.printStackTrace();
1603: }
1604: String set = (choices.elementAt(i))
1605: .getAttribute(SET);
1606: if (set == null) {
1607: set = "";
1608: }
1609: if (set != null && !"".equals(set)) {
1610: VariableSubstitutor vs = new VariableSubstitutor(
1611: idata.getVariables());
1612: set = vs.substitute(set, null);
1613: }
1614:
1615: StringTokenizer tokenizer = new StringTokenizer(
1616: choiceValues, ":");
1617: int counter = 0;
1618: while (tokenizer.hasMoreTokens()) {
1619: String token = tokenizer.nextToken();
1620: listItem = new TextValuePair(token, token);
1621: field.addItem(listItem);
1622: if (set.equals(token)) {
1623: field
1624: .setSelectedIndex(field
1625: .getItemCount() - 1);
1626: }
1627: counter++;
1628: }
1629: } else {
1630: String value = (choices.elementAt(i))
1631: .getAttribute(COMBO_VALUE);
1632: listItem = new TextValuePair(getText(choices
1633: .elementAt(i)), value);
1634: field.addItem(listItem);
1635: if (userinput) {
1636: // is the current value identical to the value associated with this element
1637: if ((value != null) && (value.length() > 0)
1638: && (currentvariablevalue.equals(value))) {
1639: // select it
1640: field.setSelectedIndex(i);
1641: }
1642: // else do nothing
1643: } else {
1644: // there is no user input
1645: String set = (choices.elementAt(i))
1646: .getAttribute(SET);
1647: if (set != null) {
1648: if (set != null && !"".equals(set)) {
1649: VariableSubstitutor vs = new VariableSubstitutor(
1650: idata.getVariables());
1651: set = vs.substitute(set, null);
1652: }
1653: if (set.equals(TRUE)) {
1654: field.setSelectedIndex(i);
1655: }
1656: }
1657: }
1658: }
1659:
1660: }
1661: }
1662: // ----------------------------------------------------
1663: // if there is no specification element, return without
1664: // doing anything.
1665: // ----------------------------------------------------
1666: else {
1667: return;
1668: }
1669:
1670: // ----------------------------------------------------
1671: // get the description and add it to the list of UI
1672: // elements if it exists.
1673: // ----------------------------------------------------
1674: element = spec.getFirstChildNamed(DESCRIPTION);
1675: addDescription(element, forPacks, forOs);
1676:
1677: TwoColumnConstraints constraints = new TwoColumnConstraints();
1678: constraints.position = TwoColumnConstraints.WEST;
1679:
1680: uiElements.add(new Object[] { null, FIELD_LABEL, null,
1681: constraints, label, forPacks, forOs });
1682:
1683: TwoColumnConstraints constraints2 = new TwoColumnConstraints();
1684: constraints2.position = TwoColumnConstraints.EAST;
1685:
1686: uiElements.add(new Object[] { null, COMBO_FIELD, variable,
1687: constraints2, field, forPacks, forOs });
1688: }
1689:
1690: /*--------------------------------------------------------------------------*/
1691: /**
1692: * Reads the content of the combobox field and substitutes the associated variable.
1693: *
1694: * @param field the object array that holds the details of the field.
1695: *
1696: * @return <code>true</code> if there was no problem reading the data or if there was an
1697: * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
1698: * dialog is popped up and <code>false</code> is returned.
1699: */
1700: /*--------------------------------------------------------------------------*/
1701: private boolean readComboBox(Object[] field) {
1702: String variable;
1703: String value;
1704: JComboBox comboBox;
1705:
1706: try {
1707: variable = (String) field[POS_VARIABLE];
1708: comboBox = (JComboBox) field[POS_FIELD];
1709: value = ((TextValuePair) comboBox.getSelectedItem())
1710: .getValue();
1711: } catch (Throwable exception) {
1712: return true;
1713: }
1714: if ((variable == null) || (value == null)) {
1715: return true;
1716: }
1717:
1718: idata.setVariable(variable, value);
1719: entries.add(new TextValuePair(variable, value));
1720: return true;
1721: }
1722:
1723: /*--------------------------------------------------------------------------*/
1724: /**
1725: * Adds a radio button set to the list of UI elements. <br>
1726: * This is a complete example of a valid XML specification
1727: *
1728: * <pre>
1729: *
1730: *
1731: *
1732: * <field type="radio" variable="testVariable">
1733: * <description text="Description for the radio buttons" id="a key for translated text"/>
1734: * <spec text="label" id="key for the label"/>
1735: * <choice text="radio 1" id="" value=""/>
1736: * <choice text="radio 2" id="" value="" set="true"/>
1737: * <choice text="radio 3" id="" value=""/>
1738: * <choice text="radio 4" id="" value=""/>
1739: * <choice text="radio 5" id="" value=""/>
1740: * </spec>
1741: * </field>
1742: *
1743: *
1744: *
1745: * </pre>
1746: *
1747: * @param spec a <code>XMLElement</code> containing the specification for the radio button
1748: * set.
1749: */
1750: /*--------------------------------------------------------------------------*/
1751: private void addRadioButton(XMLElement spec) {
1752: Vector<XMLElement> forPacks = spec
1753: .getChildrenNamed(SELECTEDPACKS);
1754: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
1755: String variable = spec.getAttribute(VARIABLE);
1756: String value = null;
1757:
1758: XMLElement element = null;
1759: ButtonGroup group = new ButtonGroup();
1760:
1761: TwoColumnConstraints constraints = new TwoColumnConstraints();
1762: constraints.position = TwoColumnConstraints.BOTH;
1763: constraints.indent = true;
1764: constraints.stretch = true;
1765:
1766: // ----------------------------------------------------
1767: // get the description and add it to the list of UI
1768: // elements if it exists.
1769: // ----------------------------------------------------
1770: element = spec.getFirstChildNamed(DESCRIPTION);
1771: addDescription(element, forPacks, forOs);
1772:
1773: // ----------------------------------------------------
1774: // extract the specification details
1775: // ----------------------------------------------------
1776: element = spec.getFirstChildNamed(SPEC);
1777:
1778: if (element != null) {
1779: Vector<XMLElement> choices = element
1780: .getChildrenNamed(RADIO_CHOICE);
1781:
1782: if (choices == null) {
1783: return;
1784: }
1785:
1786: // --------------------------------------------------
1787: // process each choice element
1788: // --------------------------------------------------
1789: for (int i = 0; i < choices.size(); i++) {
1790: JRadioButton choice = new JRadioButton();
1791: choice.setText(getText(choices.elementAt(i)));
1792: String causesValidataion = (choices.elementAt(i))
1793: .getAttribute(REVALIDATE);
1794: if (causesValidataion != null
1795: && causesValidataion.equals("yes"))
1796: choice.addActionListener(this );
1797: value = ((choices.elementAt(i))
1798: .getAttribute(RADIO_VALUE));
1799:
1800: group.add(choice);
1801:
1802: String set = (choices.elementAt(i)).getAttribute(SET);
1803: // in order to properly initialize dependent controls
1804: // we must set this variable now
1805: if (idata.getVariable(variable) == null)
1806: if (set != null)
1807: idata.setVariable(variable, value);
1808: if (set != null) {
1809: if (set != null && !"".equals(set)) {
1810: VariableSubstitutor vs = new VariableSubstitutor(
1811: idata.getVariables());
1812: set = vs.substitute(set, null);
1813: }
1814: if (set.equals(TRUE)) {
1815: choice.setSelected(true);
1816: }
1817: }
1818:
1819: buttonGroups.add(group);
1820: uiElements.add(new Object[] { null, RADIO_FIELD,
1821: variable, constraints, choice, forPacks, forOs,
1822: value, null, null, group });
1823: }
1824: }
1825: }
1826:
1827: /*--------------------------------------------------------------------------*/
1828: /**
1829: * Reads the content of the radio button field and substitutes the associated variable.
1830: *
1831: * @param field the object array that holds the details of the field.
1832: *
1833: * @return <code>true</code> if there was no problem reading the data or if there was an
1834: * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
1835: * dialog is popped up and <code>false</code> is returned.
1836: */
1837: /*--------------------------------------------------------------------------*/
1838: private boolean readRadioButton(Object[] field) {
1839: String variable = null;
1840: String value = null;
1841: JRadioButton button = null;
1842:
1843: try {
1844: button = (JRadioButton) field[POS_FIELD];
1845:
1846: if (!button.isSelected()) {
1847: return (true);
1848: }
1849:
1850: variable = (String) field[POS_VARIABLE];
1851: value = (String) field[POS_TRUE];
1852: } catch (Throwable exception) {
1853: return (true);
1854: }
1855:
1856: idata.setVariable(variable, value);
1857: entries.add(new TextValuePair(variable, value));
1858: return (true);
1859: }
1860:
1861: /*--------------------------------------------------------------------------*/
1862: /**
1863: * Adds one or more password fields to the list of UI elements. <br>
1864: * This is a complete example of a valid XML specification
1865: *
1866: * <pre>
1867: *
1868: *
1869: *
1870: * <field type="password" variable="testVariable">
1871: * <description align="left" txt="Please enter your password" id="a key for translated text"/>
1872: * <spec>
1873: * <pwd txt="Password" id="key for the label" size="10" set=""/>
1874: * <pwd txt="Retype password" id="another key for the label" size="10" set=""/>
1875: * </spec>
1876: * <validator class="com.izforge.sample.PWDValidator" txt="Both versions of the password must match" id="key for the error text"/>
1877: * <processor class="com.izforge.sample.PWDEncryptor"/>
1878: * </field>
1879: *
1880: * </pre>
1881: * Additionally, parameters and multiple validators can be used to provide
1882: * separate validation and error messages for each case.
1883: * <pre>
1884: *
1885: * <field type="password" align="left" variable="keystore.password">
1886: * <spec>
1887: * <pwd txt="Keystore Password:" size="25" set=""/>
1888: * <pwd txt="Retype Password:" size="25" set=""/>
1889: * </spec>
1890: * <validator class="com.izforge.izpack.util.PasswordEqualityValidator" txt="Both keystore passwords must match." id="key for the error text"/>
1891: * <validator class="com.izforge.izpack.util.PasswordKeystoreValidator" txt="Could not validate keystore with password and alias provided." id="key for the error text">
1892: * <param name="keystoreFile" value="${existing.ssl.keystore}"/>
1893: * <param name="keystoreType" value="JKS"/>
1894: * <param name="keystoreAlias" value="${keystore.key.alias}"/>
1895: * </validator>
1896: * </field>
1897: *
1898: * </pre>
1899: *
1900: * @param spec a <code>XMLElement</code> containing the specification for the set of password
1901: * fields.
1902: */
1903: /*--------------------------------------------------------------------------*/
1904: private void addPasswordField(XMLElement spec) {
1905: Vector<XMLElement> forPacks = spec
1906: .getChildrenNamed(SELECTEDPACKS);
1907: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
1908: String variable = spec.getAttribute(VARIABLE);
1909: String message = null;
1910: String processor = null;
1911: XMLElement element = null;
1912: PasswordGroup group = null;
1913: int size = 0;
1914: // For multiple validator support
1915: Vector<XMLElement> validatorsElem = null;
1916: List<ValidatorContainer> validatorsList = new ArrayList<ValidatorContainer>();
1917: int vsize = 0;
1918:
1919: // ----------------------------------------------------
1920: // get the description and add it to the list of UI
1921: // elements if it exists.
1922: // ----------------------------------------------------
1923: element = spec.getFirstChildNamed(DESCRIPTION);
1924: addDescription(element, forPacks, forOs);
1925:
1926: // ----------------------------------------------------
1927: // get the validator and processor if they are defined
1928: // ----------------------------------------------------
1929:
1930: validatorsElem = spec.getChildrenNamed(VALIDATOR);
1931: if (validatorsElem != null && validatorsElem.size() > 0) {
1932: vsize = validatorsElem.size();
1933: for (int i = 0; i < vsize; i++) {
1934: element = validatorsElem.get(i);
1935: String validator = element.getAttribute(CLASS);
1936: message = getText(element);
1937: HashMap<String, String> validateParamMap = new HashMap<String, String>();
1938: // ----------------------------------------------------------
1939: // check and see if we have any parameters for this validator.
1940: // If so, then add them to validateParamMap.
1941: // ----------------------------------------------------------
1942: Vector<XMLElement> validateParams = element
1943: .getChildrenNamed(RULE_PARAM);
1944: if (validateParams != null && validateParams.size() > 0) {
1945: Iterator<XMLElement> iter = validateParams
1946: .iterator();
1947: while (iter.hasNext()) {
1948: element = iter.next();
1949: String paramName = element
1950: .getAttribute(RULE_PARAM_NAME);
1951: String paramValue = element
1952: .getAttribute(RULE_PARAM_VALUE);
1953: // System.out.println("Adding parameter: "+paramName+"="+paramValue);
1954: validateParamMap.put(paramName, paramValue);
1955: }
1956: }
1957: validatorsList.add(new ValidatorContainer(validator,
1958: message, validateParamMap));
1959: }
1960: }
1961:
1962: element = spec.getFirstChildNamed(PROCESSOR);
1963: if (element != null) {
1964: processor = element.getAttribute(CLASS);
1965: }
1966:
1967: group = new PasswordGroup(idata, validatorsList, processor);
1968:
1969: // ----------------------------------------------------
1970: // extract the specification details
1971: // ----------------------------------------------------
1972: element = spec.getFirstChildNamed(SPEC);
1973:
1974: if (element != null) {
1975: Vector<XMLElement> inputs = element
1976: .getChildrenNamed(PWD_INPUT);
1977:
1978: if (inputs == null) {
1979: return;
1980: }
1981:
1982: // --------------------------------------------------
1983: // process each input field
1984: // --------------------------------------------------
1985: XMLElement fieldSpec;
1986: for (int i = 0; i < inputs.size(); i++) {
1987: fieldSpec = inputs.elementAt(i);
1988: String set = fieldSpec.getAttribute(SET);
1989: if (set != null && !"".equals(set)) {
1990: VariableSubstitutor vs = new VariableSubstitutor(
1991: idata.getVariables());
1992: set = vs.substitute(set, null);
1993: }
1994: JLabel label = new JLabel(getText(fieldSpec));
1995: try {
1996: size = Integer.parseInt(fieldSpec
1997: .getAttribute(PWD_SIZE));
1998: } catch (Throwable exception) {
1999: size = 1;
2000: }
2001:
2002: // ----------------------------------------------------
2003: // construct the UI element and add it to the list
2004: // ----------------------------------------------------
2005: JPasswordField field = new JPasswordField(set, size);
2006: field.setCaretPosition(0);
2007:
2008: TwoColumnConstraints constraints = new TwoColumnConstraints();
2009: constraints.position = TwoColumnConstraints.WEST;
2010:
2011: uiElements.add(new Object[] { null, FIELD_LABEL, null,
2012: constraints, label, forPacks, forOs });
2013:
2014: TwoColumnConstraints constraints2 = new TwoColumnConstraints();
2015: constraints2.position = TwoColumnConstraints.EAST;
2016:
2017: // Removed message to support pulling from multiple validators
2018: uiElements.add(new Object[] { null, PWD_FIELD,
2019: variable, constraints2, field, forPacks, forOs,
2020: null, null, null, group });
2021: // Original
2022: // uiElements.add(new Object[]{null, PWD_FIELD, variable, constraints2, field,
2023: // forPacks, forOs, null, null, message, group
2024: // });
2025: group.addField(field);
2026: }
2027: }
2028:
2029: passwordGroups.add(group);
2030: }
2031:
2032: /*--------------------------------------------------------------------------*/
2033: /**
2034: * Reads the content of the password field and substitutes the associated variable.
2035: *
2036: * @param field a password group that manages one or more passord fields.
2037: *
2038: * @return <code>true</code> if there was no problem reading the data or if there was an
2039: * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
2040: * dialog is popped up and <code>false</code> is returned.
2041: */
2042: /*--------------------------------------------------------------------------*/
2043: private boolean readPasswordField(Object[] field) {
2044: PasswordGroup group = null;
2045: String variable = null;
2046: String message = null;
2047:
2048: try {
2049: group = (PasswordGroup) field[POS_GROUP];
2050: variable = (String) field[POS_VARIABLE];
2051: // Removed to support grabbing the message from multiple validators
2052: // message = (String) field[POS_MESSAGE];
2053: } catch (Throwable exception) {
2054: return (true);
2055: }
2056: if ((variable == null) || (passwordGroupsRead.contains(group))) {
2057: return (true);
2058: }
2059: passwordGroups.add(group);
2060:
2061: //boolean success = !validating || group.validateContents();
2062: boolean success = !validating;
2063:
2064: // Use each validator to validate contents
2065: if (!success) {
2066: int size = group.validatorSize();
2067: // System.out.println("Found "+(size)+" validators");
2068: for (int i = 0; i < size; i++) {
2069: success = group.validateContents(i);
2070: if (!success) {
2071: JOptionPane
2072: .showMessageDialog(
2073: parentFrame,
2074: group.getValidatorMessage(i),
2075: parentFrame.langpack
2076: .getString("UserInputPanel.error.caption"),
2077: JOptionPane.WARNING_MESSAGE);
2078: break;
2079: }
2080: }
2081: }
2082:
2083: // // Changed to show messages for each validator
2084: // if (!success) {
2085: // JOptionPane.showMessageDialog(parentFrame, message, parentFrame.langpack.getString("UserInputPanel.error.caption"), JOptionPane.WARNING_MESSAGE);
2086: // return (false);
2087: // }
2088:
2089: if (success) {
2090: idata.setVariable(variable, group.getPassword());
2091: entries
2092: .add(new TextValuePair(variable, group
2093: .getPassword()));
2094: }
2095: return success;
2096: }
2097:
2098: /*--------------------------------------------------------------------------*/
2099: /**
2100: * Adds a chackbox to the list of UI elements.
2101: *
2102: * @param spec a <code>XMLElement</code> containing the specification for the checkbox.
2103: */
2104: /*--------------------------------------------------------------------------*/
2105: private void addCheckBox(XMLElement spec) {
2106: Vector<XMLElement> forPacks = spec
2107: .getChildrenNamed(SELECTEDPACKS);
2108: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
2109: String label = "";
2110: String set = null;
2111: String trueValue = null;
2112: String falseValue = null;
2113: String variable = spec.getAttribute(VARIABLE);
2114: String causesValidataion = null;
2115: XMLElement detail = spec.getFirstChildNamed(SPEC);
2116:
2117: if (variable == null) {
2118: return;
2119: }
2120:
2121: if (detail != null) {
2122: label = getText(detail);
2123: set = detail.getAttribute(SET);
2124: trueValue = detail.getAttribute(TRUE);
2125: falseValue = detail.getAttribute(FALSE);
2126: causesValidataion = detail.getAttribute(REVALIDATE);
2127: String value = idata.getVariable(variable);
2128: if (value != null) {
2129: set = value;
2130: }
2131: }
2132:
2133: JCheckBox checkbox = new JCheckBox(label);
2134:
2135: if (causesValidataion != null
2136: && causesValidataion.equals("yes"))
2137: checkbox.addActionListener(this );
2138: idata.setVariable(variable, set);
2139:
2140: if (set != null) {
2141: if (set != null && !"".equals(set)) {
2142: VariableSubstitutor vs = new VariableSubstitutor(idata
2143: .getVariables());
2144: set = vs.substitute(set, null);
2145: }
2146: if (set.equals(FALSE)) {
2147: checkbox.setSelected(false);
2148: }
2149: if (set.equals(TRUE)) {
2150: checkbox.setSelected(true);
2151: }
2152: }
2153:
2154: // ----------------------------------------------------
2155: // get the description and add it to the list of UI
2156: // elements if it exists.
2157: // ----------------------------------------------------
2158: XMLElement element = spec.getFirstChildNamed(DESCRIPTION);
2159: addDescription(element, forPacks, forOs);
2160:
2161: TwoColumnConstraints constraints = new TwoColumnConstraints();
2162: constraints.position = TwoColumnConstraints.BOTH;
2163: constraints.stretch = true;
2164: constraints.indent = true;
2165:
2166: uiElements.add(new Object[] { null, CHECK_FIELD, variable,
2167: constraints, checkbox, forPacks, forOs, trueValue,
2168: falseValue });
2169: }
2170:
2171: /*--------------------------------------------------------------------------*/
2172: /**
2173: * Reads the content of the checkbox field and substitutes the associated variable.
2174: *
2175: * @param field the object array that holds the details of the field.
2176: *
2177: * @return <code>true</code> if there was no problem reading the data or if there was an
2178: * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
2179: * dialog is popped up and <code>false</code> is returned.
2180: */
2181: /*--------------------------------------------------------------------------*/
2182: private boolean readCheckBox(Object[] field) {
2183: String variable = null;
2184: String trueValue = null;
2185: String falseValue = null;
2186: JCheckBox box = null;
2187:
2188: try {
2189: box = (JCheckBox) field[POS_FIELD];
2190: variable = (String) field[POS_VARIABLE];
2191: trueValue = (String) field[POS_TRUE];
2192: if (trueValue == null) {
2193: trueValue = "";
2194: }
2195:
2196: falseValue = (String) field[POS_FALSE];
2197: if (falseValue == null) {
2198: falseValue = "";
2199: }
2200: } catch (Throwable exception) {
2201: return (true);
2202: }
2203:
2204: if (box.isSelected()) {
2205: idata.setVariable(variable, trueValue);
2206: entries.add(new TextValuePair(variable, trueValue));
2207: } else {
2208: idata.setVariable(variable, falseValue);
2209: entries.add(new TextValuePair(variable, falseValue));
2210: }
2211:
2212: return (true);
2213: }
2214:
2215: /*--------------------------------------------------------------------------*/
2216: /**
2217: * Adds a search field to the list of UI elements.
2218: * <p>
2219: * This is a complete example of a valid XML specification
2220: *
2221: * <pre>
2222: *
2223: *
2224: *
2225: * <field type="search" variable="testVariable">
2226: * <description text="Description for the search field" id="a key for translated text"/>
2227: * <spec text="label" id="key for the label" filename="the_file_to_search" result="directory" /> <!-- values for result: directory, file -->
2228: * <choice dir="directory1" set="true" /> <!-- default value -->
2229: * <choice dir="dir2" />
2230: * </spec>
2231: * </field>
2232: *
2233: *
2234: *
2235: * </pre>
2236: *
2237: * @param spec a <code>XMLElement</code> containing the specification for the search field
2238: */
2239: /*--------------------------------------------------------------------------*/
2240: private void addSearch(XMLElement spec) {
2241: Vector<XMLElement> forPacks = spec
2242: .getChildrenNamed(SELECTEDPACKS);
2243: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
2244: XMLElement element = spec.getFirstChildNamed(SPEC);
2245: String variable = spec.getAttribute(VARIABLE);
2246: String filename = null;
2247: String check_filename = null;
2248: int search_type = 0;
2249: int result_type = 0;
2250: JComboBox combobox = new JComboBox();
2251: JLabel label = null;
2252:
2253: // System.out.println ("adding search combobox, variable "+variable);
2254:
2255: // allow the user to enter something
2256: combobox.setEditable(true);
2257:
2258: // ----------------------------------------------------
2259: // extract the specification details
2260: // ----------------------------------------------------
2261: if (element != null) {
2262: label = new JLabel(getText(element));
2263:
2264: // search type is optional (default: file)
2265: search_type = SearchField.TYPE_FILE;
2266:
2267: String search_type_str = element.getAttribute(SEARCH_TYPE);
2268:
2269: if (search_type_str != null) {
2270: if (search_type_str.equals(SEARCH_FILE)) {
2271: search_type = SearchField.TYPE_FILE;
2272: } else if (search_type_str.equals(SEARCH_DIRECTORY)) {
2273: search_type = SearchField.TYPE_DIRECTORY;
2274: }
2275: }
2276:
2277: // result type is mandatory too
2278: String result_type_str = element
2279: .getAttribute(SEARCH_RESULT);
2280:
2281: if (result_type_str == null) {
2282: return;
2283: } else if (result_type_str.equals(SEARCH_FILE)) {
2284: result_type = SearchField.RESULT_FILE;
2285: } else if (result_type_str.equals(SEARCH_DIRECTORY)) {
2286: result_type = SearchField.RESULT_DIRECTORY;
2287: } else if (result_type_str.equals(SEARCH_PARENTDIR)) {
2288: result_type = SearchField.RESULT_PARENTDIR;
2289: } else {
2290: return;
2291: }
2292:
2293: // might be missing - null is okay
2294: filename = element.getAttribute(SEARCH_FILENAME);
2295:
2296: check_filename = element.getAttribute(SEARCH_CHECKFILENAME);
2297:
2298: Vector<XMLElement> choices = element
2299: .getChildrenNamed(SEARCH_CHOICE);
2300:
2301: if (choices == null) {
2302: return;
2303: }
2304:
2305: for (int i = 0; i < choices.size(); i++) {
2306: XMLElement choice_el = choices.elementAt(i);
2307:
2308: if (!OsConstraint.oneMatchesCurrentSystem(choice_el))
2309: continue;
2310:
2311: String value = choice_el.getAttribute(SEARCH_VALUE);
2312:
2313: combobox.addItem(value);
2314:
2315: String set = (choices.elementAt(i)).getAttribute(SET);
2316: if (set != null) {
2317: if (set != null && !"".equals(set)) {
2318: VariableSubstitutor vs = new VariableSubstitutor(
2319: idata.getVariables());
2320: set = vs.substitute(set, null);
2321: }
2322: if (set.equals(TRUE)) {
2323: combobox.setSelectedIndex(i);
2324: }
2325: }
2326: }
2327: }
2328: // ----------------------------------------------------
2329: // if there is no specification element, return without
2330: // doing anything.
2331: // ----------------------------------------------------
2332: else {
2333: return;
2334: }
2335:
2336: // ----------------------------------------------------
2337: // get the description and add it to the list of UI
2338: // elements if it exists.
2339: // ----------------------------------------------------
2340: element = spec.getFirstChildNamed(DESCRIPTION);
2341: addDescription(element, forPacks, forOs);
2342:
2343: TwoColumnConstraints westconstraint1 = new TwoColumnConstraints();
2344: westconstraint1.position = TwoColumnConstraints.WEST;
2345:
2346: uiElements.add(new Object[] { null, FIELD_LABEL, null,
2347: westconstraint1, label, forPacks, forOs });
2348:
2349: TwoColumnConstraints eastconstraint1 = new TwoColumnConstraints();
2350: eastconstraint1.position = TwoColumnConstraints.EAST;
2351:
2352: StringBuffer tooltiptext = new StringBuffer();
2353:
2354: if ((filename != null) && (filename.length() > 0)) {
2355: tooltiptext
2356: .append(MessageFormat
2357: .format(
2358: parentFrame.langpack
2359: .getString("UserInputPanel.search.location"),
2360: new Object[] { new String[] { filename } }));
2361: }
2362:
2363: boolean showAutodetect = (check_filename != null)
2364: && (check_filename.length() > 0);
2365: if (showAutodetect) {
2366: tooltiptext
2367: .append(MessageFormat
2368: .format(
2369: parentFrame.langpack
2370: .getString("UserInputPanel.search.location.checkedfile"),
2371: new Object[] { new String[] { check_filename } }));
2372: }
2373:
2374: if (tooltiptext.length() > 0)
2375: combobox.setToolTipText(tooltiptext.toString());
2376:
2377: uiElements.add(new Object[] { null, SEARCH_FIELD, variable,
2378: eastconstraint1, combobox, forPacks, forOs });
2379:
2380: JPanel buttonPanel = new JPanel();
2381: buttonPanel.setLayout(new com.izforge.izpack.gui.FlowLayout(
2382: com.izforge.izpack.gui.FlowLayout.LEADING));
2383:
2384: JButton autodetectButton = ButtonFactory.createButton(
2385: parentFrame.langpack
2386: .getString("UserInputPanel.search.autodetect"),
2387: idata.buttonsHColor);
2388: autodetectButton.setVisible(showAutodetect);
2389:
2390: autodetectButton.setToolTipText(parentFrame.langpack
2391: .getString("UserInputPanel.search.autodetect.tooltip"));
2392:
2393: buttonPanel.add(autodetectButton);
2394:
2395: JButton browseButton = ButtonFactory.createButton(
2396: parentFrame.langpack
2397: .getString("UserInputPanel.search.browse"),
2398: idata.buttonsHColor);
2399:
2400: buttonPanel.add(browseButton);
2401:
2402: TwoColumnConstraints eastonlyconstraint = new TwoColumnConstraints();
2403: eastonlyconstraint.position = TwoColumnConstraints.EASTONLY;
2404:
2405: uiElements.add(new Object[] { null, SEARCH_BUTTON_FIELD, null,
2406: eastonlyconstraint, buttonPanel, forPacks, forOs });
2407:
2408: searchFields.add(new SearchField(filename, check_filename,
2409: parentFrame, combobox, autodetectButton, browseButton,
2410: search_type, result_type));
2411: }
2412:
2413: /*--------------------------------------------------------------------------*/
2414: /**
2415: * Reads the content of the search field and substitutes the associated variable.
2416: *
2417: * @param field the object array that holds the details of the field.
2418: *
2419: * @return <code>true</code> if there was no problem reading the data or if there was an
2420: * irrecovarable problem. If there was a problem that can be corrected by the operator, an error
2421: * dialog is popped up and <code>false</code> is returned.
2422: */
2423: /*--------------------------------------------------------------------------*/
2424: private boolean readSearch(Object[] field) {
2425: String variable = null;
2426: String value = null;
2427: JComboBox comboBox = null;
2428:
2429: try {
2430: variable = (String) field[POS_VARIABLE];
2431: comboBox = (JComboBox) field[POS_FIELD];
2432: for (int i = 0; i < this .searchFields.size(); ++i) {
2433: SearchField sf = this .searchFields.elementAt(i);
2434: if (sf.belongsTo(comboBox)) {
2435: value = sf.getResult();
2436: break;
2437: }
2438: }
2439: } catch (Throwable exception) {
2440: return (true);
2441: }
2442: if ((variable == null) || (value == null)) {
2443: return (true);
2444: }
2445:
2446: idata.setVariable(variable, value);
2447: entries.add(new TextValuePair(variable, value));
2448: return (true);
2449: }
2450:
2451: /*--------------------------------------------------------------------------*/
2452: /**
2453: * Adds text to the list of UI elements
2454: *
2455: * @param spec a <code>XMLElement</code> containing the specification for the text.
2456: */
2457: /*--------------------------------------------------------------------------*/
2458: private void addText(XMLElement spec) {
2459: Vector<XMLElement> forPacks = spec
2460: .getChildrenNamed(SELECTEDPACKS);
2461: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
2462:
2463: addDescription(spec, forPacks, forOs);
2464: }
2465:
2466: /*--------------------------------------------------------------------------*/
2467: /**
2468: * Adds a dummy field to the list of UI elements to act as spacer.
2469: *
2470: * @param spec a <code>XMLElement</code> containing other specifications. At present this
2471: * information is not used but might be in future versions.
2472: */
2473: /*--------------------------------------------------------------------------*/
2474: private void addSpace(XMLElement spec) {
2475: Vector<XMLElement> forPacks = spec
2476: .getChildrenNamed(SELECTEDPACKS);
2477: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
2478: JPanel panel = new JPanel();
2479:
2480: TwoColumnConstraints constraints = new TwoColumnConstraints();
2481: constraints.position = TwoColumnConstraints.BOTH;
2482: constraints.stretch = true;
2483:
2484: uiElements.add(new Object[] { null, SPACE_FIELD, null,
2485: constraints, panel, forPacks, forOs });
2486: }
2487:
2488: /*--------------------------------------------------------------------------*/
2489: /**
2490: * Adds a dividing line to the list of UI elements act as separator.
2491: *
2492: * @param spec a <code>XMLElement</code> containing additional specifications.
2493: */
2494: /*--------------------------------------------------------------------------*/
2495: private void addDivider(XMLElement spec) {
2496: Vector<XMLElement> forPacks = spec
2497: .getChildrenNamed(SELECTEDPACKS);
2498: Vector<XMLElement> forOs = spec.getChildrenNamed(OS);
2499: JPanel panel = new JPanel();
2500: String alignment = spec.getAttribute(ALIGNMENT);
2501:
2502: if (alignment != null) {
2503: if (alignment.equals(TOP)) {
2504: panel.setBorder(BorderFactory.createMatteBorder(1, 0,
2505: 0, 0, Color.gray));
2506: } else {
2507: panel.setBorder(BorderFactory.createMatteBorder(0, 0,
2508: 1, 0, Color.gray));
2509: }
2510: } else {
2511: panel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0,
2512: Color.gray));
2513: }
2514:
2515: TwoColumnConstraints constraints = new TwoColumnConstraints();
2516: constraints.position = TwoColumnConstraints.BOTH;
2517: constraints.stretch = true;
2518:
2519: uiElements.add(new Object[] { null, DIVIDER_FIELD, null,
2520: constraints, panel, forPacks, forOs });
2521: }
2522:
2523: /*--------------------------------------------------------------------------*/
2524: /**
2525: * Adds a description to the list of UI elements.
2526: *
2527: * @param spec a <code>XMLElement</code> containing the specification for the description.
2528: */
2529: /*--------------------------------------------------------------------------*/
2530: private void addDescription(XMLElement spec,
2531: Vector<XMLElement> forPacks, Vector<XMLElement> forOs) {
2532: String description;
2533: TwoColumnConstraints constraints = new TwoColumnConstraints();
2534: constraints.position = TwoColumnConstraints.BOTH;
2535: constraints.stretch = true;
2536:
2537: if (spec != null) {
2538: description = getText(spec);
2539:
2540: // if we have a description, add it to the UI elements
2541: if (description != null) {
2542: String alignment = spec.getAttribute(ALIGNMENT);
2543: // FIX needed: where do we use this variable at all? i dont think so...
2544: int justify = MultiLineLabel.LEFT;
2545:
2546: if (alignment != null) {
2547: if (alignment.equals(LEFT)) {
2548: justify = MultiLineLabel.LEFT;
2549: } else if (alignment.equals(CENTER)) {
2550: justify = MultiLineLabel.CENTER;
2551: } else if (alignment.equals(RIGHT)) {
2552: justify = MultiLineLabel.RIGHT;
2553: }
2554: }
2555:
2556: javax.swing.JTextPane label = new javax.swing.JTextPane();
2557:
2558: // Not editable, but still selectable.
2559: label.setEditable(false);
2560:
2561: // If html tags are present enable html rendering, otherwise the JTextPane
2562: // looks exactly like MultiLineLabel.
2563: if (description.startsWith("<html>")
2564: && description.endsWith("</html>"))
2565: label.setContentType("text/html");
2566: label.setText(description);
2567:
2568: // Background color and font to match the label's.
2569: label.setBackground(javax.swing.UIManager
2570: .getColor("label.backgroud"));
2571: label.setMargin(new java.awt.Insets(3, 0, 3, 0));
2572: // workaround to cut out layout problems
2573: label.getPreferredSize();
2574: // end of workaround.
2575:
2576: uiElements.add(new Object[] { null, DESCRIPTION, null,
2577: constraints, label, forPacks, forOs });
2578: }
2579: }
2580: }
2581:
2582: /*--------------------------------------------------------------------------*/
2583: /**
2584: * Retrieves the value of a boolean attribute. If the attribute is found and the values equals
2585: * the value of the constant <code>TRUE</code> then true is returned. If it equals
2586: * <code>FALSE</code> the false is returned. In all other cases, including when the attribute
2587: * is not found, the default value is returned.
2588: *
2589: * @param element the <code>XMLElement</code> to search for the attribute.
2590: * @param attribute the attribute to search for
2591: * @param defaultValue the default value to use if the attribute does not exist or a illegal
2592: * value was discovered.
2593: *
2594: * @return <code>true</code> if the attribute is found and the value equals the the constant
2595: * <code>TRUE</code>. <<code> if the
2596: * attribute is <code>FALSE</code>. In all other cases the
2597: * default value is returned.
2598: */
2599: /*--------------------------------------------------------------------------*/
2600: private boolean getBoolean(XMLElement element, String attribute,
2601: boolean defaultValue) {
2602: boolean result = defaultValue;
2603:
2604: if ((attribute != null) && (attribute.length() > 0)) {
2605: String value = element.getAttribute(attribute);
2606:
2607: if (value != null) {
2608: if (value.equals(TRUE)) {
2609: result = true;
2610: } else if (value.equals(FALSE)) {
2611: result = false;
2612: }
2613: }
2614: }
2615:
2616: return (result);
2617: }
2618:
2619: /*--------------------------------------------------------------------------*/
2620: /**
2621: * Retrieves the value of an integer attribute. If the attribute is not found or the value is
2622: * non-numeric then the default value is returned.
2623: *
2624: * @param element the <code>XMLElement</code> to search for the attribute.
2625: * @param attribute the attribute to search for
2626: * @param defaultValue the default value to use in case the attribute does not exist.
2627: *
2628: * @return the value of the attribute. If the attribute is not found or the content is not a
2629: * legal integer, then the default value is returned.
2630: */
2631: /*--------------------------------------------------------------------------*/
2632: // private int getInt(XMLElement element, String attribute, int defaultValue)
2633: // {
2634: // int result = defaultValue;
2635: //
2636: // if ((attribute != null) && (attribute.length() > 0))
2637: // {
2638: // try
2639: // {
2640: // result = Integer.parseInt(element.getAttribute(attribute));
2641: // }
2642: // catch (Throwable exception)
2643: // {}
2644: // }
2645: //
2646: // return (result);
2647: // }
2648: /*--------------------------------------------------------------------------*/
2649: /**
2650: * Retrieves the value of a floating point attribute. If the attribute is not found or the value
2651: * is non-numeric then the default value is returned.
2652: *
2653: * @param element the <code>XMLElement</code> to search for the attribute.
2654: * @param attribute the attribute to search for
2655: * @param defaultValue the default value to use in case the attribute does not exist.
2656: *
2657: * @return the value of the attribute. If the attribute is not found or the content is not a
2658: * legal integer, then the default value is returned.
2659: */
2660: /*--------------------------------------------------------------------------*/
2661: private float getFloat(XMLElement element, String attribute,
2662: float defaultValue) {
2663: float result = defaultValue;
2664:
2665: if ((attribute != null) && (attribute.length() > 0)) {
2666: try {
2667: result = Float.parseFloat(element
2668: .getAttribute(attribute));
2669: } catch (Throwable exception) {
2670: }
2671: }
2672:
2673: return (result);
2674: }
2675:
2676: /*--------------------------------------------------------------------------*/
2677: /**
2678: * Extracts the text from an <code>XMLElement</code>. The text must be defined in the
2679: * resource file under the key defined in the <code>id</code> attribute or as value of the
2680: * attribute <code>text</code>.
2681: *
2682: * @param element the <code>XMLElement</code> from which to extract the text.
2683: *
2684: * @return The text defined in the <code>XMLElement</code>. If no text can be located,
2685: * <code>null</code> is returned.
2686: */
2687: /*--------------------------------------------------------------------------*/
2688: private String getText(XMLElement element) {
2689: if (element == null) {
2690: return (null);
2691: }
2692:
2693: String key = element.getAttribute(KEY);
2694: String text = null;
2695:
2696: if ((key != null) && (langpack != null)) {
2697: try {
2698: text = langpack.getString(key);
2699: } catch (Throwable exception) {
2700: text = null;
2701: }
2702: }
2703:
2704: // if there is no text in the description, then
2705: // we were unable to retrieve it form the resource.
2706: // In this case try to get the text directly from
2707: // the XMLElement
2708: if (text == null) {
2709: text = element.getAttribute(TEXT);
2710: }
2711:
2712: // try to parse the text, and substitute any variable it finds
2713: VariableSubstitutor vs = new VariableSubstitutor(idata
2714: .getVariables());
2715:
2716: return (vs.substitute(text, null));
2717: }
2718:
2719: /*--------------------------------------------------------------------------*/
2720: /**
2721: * Retreives the alignment setting for the <code>XMLElement</code>. The default value in case
2722: * the <code>ALIGNMENT</code> attribute is not found or the value is illegal is
2723: * <code>TwoColumnConstraints.LEFT</code>.
2724: *
2725: * @param element the <code>XMLElement</code> from which to extract the alignment setting.
2726: *
2727: * @return the alignement setting for the <code>XMLElement</code>. The value is either
2728: * <code>TwoColumnConstraints.LEFT</code>, <code>TwoColumnConstraints.CENTER</code> or
2729: * <code>TwoColumnConstraints.RIGHT</code>.
2730: *
2731: * @see com.izforge.izpack.gui.TwoColumnConstraints
2732: */
2733: /*--------------------------------------------------------------------------*/
2734: private int getAlignment(XMLElement element) {
2735: int result = TwoColumnConstraints.LEFT;
2736:
2737: String value = element.getAttribute(ALIGNMENT);
2738:
2739: if (value != null) {
2740: if (value.equals(LEFT)) {
2741: result = TwoColumnConstraints.LEFT;
2742: } else if (value.equals(CENTER)) {
2743: result = TwoColumnConstraints.CENTER;
2744: } else if (value.equals(RIGHT)) {
2745: result = TwoColumnConstraints.RIGHT;
2746: }
2747: }
2748:
2749: return (result);
2750: }
2751:
2752: /**
2753: * Verifies if an item is required for the operating system the installer executed. The
2754: * configuration for this feature is: <br/> <os family="unix"/> <br>
2755: * <br>
2756: * <b>Note:</b><br>
2757: * If the list of the os is empty then <code>true</code> is always returnd.
2758: *
2759: * @param os The <code>Vector</code> of <code>String</code>s. containing the os names
2760: *
2761: * @return <code>true</code> if the item is required for the os, otherwise returns
2762: * <code>false</code>.
2763: */
2764: public boolean itemRequiredForOs(Vector<XMLElement> os) {
2765: if (os.size() == 0) {
2766: return true;
2767: }
2768:
2769: for (int i = 0; i < os.size(); i++) {
2770: String family = (os.elementAt(i)).getAttribute(FAMILY);
2771: boolean match = false;
2772:
2773: if ("windows".equals(family)) {
2774: match = OsVersion.IS_WINDOWS;
2775: } else if ("mac".equals(family)) {
2776: match = OsVersion.IS_OSX;
2777: } else if ("unix".equals(family)) {
2778: match = OsVersion.IS_UNIX;
2779: }
2780: if (match) {
2781: return true;
2782: }
2783: }
2784: return false;
2785: }
2786:
2787: /*--------------------------------------------------------------------------*/
2788: /**
2789: * Verifies if an item is required for any of the packs listed. An item is required for a pack
2790: * in the list if that pack is actually selected for installation. <br>
2791: * <br>
2792: * <b>Note:</b><br>
2793: * If the list of selected packs is empty then <code>true</code> is always returnd. The same
2794: * is true if the <code>packs</code> list is empty.
2795: *
2796: * @param packs a <code>Vector</code> of <code>String</code>s. Each of the strings denotes
2797: * a pack for which an item should be created if the pack is actually installed.
2798: *
2799: * @return <code>true</code> if the item is required for at least one pack in the list,
2800: * otherwise returns <code>false</code>.
2801: */
2802: /*--------------------------------------------------------------------------*/
2803: /*
2804: * $ @design
2805: *
2806: * The information about the installed packs comes from InstallData.selectedPacks. This assumes
2807: * that this panel is presented to the user AFTER the PacksPanel.
2808: * --------------------------------------------------------------------------
2809: */
2810: private boolean itemRequiredFor(Vector<XMLElement> packs) {
2811:
2812: String selected;
2813: String required;
2814:
2815: if (packs.size() == 0) {
2816: return (true);
2817: }
2818:
2819: // ----------------------------------------------------
2820: // We are getting to this point if any packs have been
2821: // specified. This means that there is a possibility
2822: // that some UI elements will not get added. This
2823: // means that we can not allow to go back to the
2824: // PacksPanel, because the process of building the
2825: // UI is not reversable.
2826: // ----------------------------------------------------
2827: // packsDefined = true;
2828:
2829: // ----------------------------------------------------
2830: // analyze if the any of the packs for which the item
2831: // is required have been selected for installation.
2832: // ----------------------------------------------------
2833: for (int i = 0; i < idata.selectedPacks.size(); i++) {
2834: selected = ((Pack) idata.selectedPacks.get(i)).name;
2835:
2836: for (int k = 0; k < packs.size(); k++) {
2837: required = (packs.elementAt(k)).getAttribute(NAME, "");
2838: if (selected.equals(required)) {
2839: return (true);
2840: }
2841: }
2842: }
2843:
2844: return (false);
2845: }
2846:
2847: /*--------------------------------------------------------------------------*/
2848: /**
2849: * Verifies if an item is required for any of the packs listed. An item is required for a pack
2850: * in the list if that pack is actually NOT selected for installation. <br>
2851: * <br>
2852: * <b>Note:</b><br>
2853: * If the list of selected packs is empty then <code>true</code> is always returnd. The same
2854: * is true if the <code>packs</code> list is empty.
2855: *
2856: * @param packs a <code>Vector</code> of <code>String</code>s. Each of the strings denotes
2857: * a pack for which an item should be created if the pack is actually installed.
2858: *
2859: * @return <code>true</code> if the item is required for at least one pack in the list,
2860: * otherwise returns <code>false</code>.
2861: */
2862: /*--------------------------------------------------------------------------*/
2863: /*
2864: * $ @design
2865: *
2866: * The information about the installed packs comes from InstallData.selectedPacks. This assumes
2867: * that this panel is presented to the user AFTER the PacksPanel.
2868: * --------------------------------------------------------------------------
2869: */
2870: private boolean itemRequiredForUnselected(Vector<XMLElement> packs) {
2871:
2872: String selected;
2873: String required;
2874:
2875: if (packs.size() == 0) {
2876: return (true);
2877: }
2878:
2879: // ----------------------------------------------------
2880: // analyze if the any of the packs for which the item
2881: // is required have been selected for installation.
2882: // ----------------------------------------------------
2883: for (int i = 0; i < idata.selectedPacks.size(); i++) {
2884: selected = ((Pack) idata.selectedPacks.get(i)).name;
2885:
2886: for (int k = 0; k < packs.size(); k++) {
2887: required = (packs.elementAt(k)).getAttribute(NAME, "");
2888: if (selected.equals(required)) {
2889: return (false);
2890: }
2891: }
2892: }
2893:
2894: return (true);
2895: }
2896:
2897: // ----------- Inheritance stuff -----------------------------------------
2898: /**
2899: * Returns the uiElements.
2900: *
2901: * @return Returns the uiElements.
2902: */
2903: protected Vector<Object[]> getUiElements() {
2904: return uiElements;
2905: }
2906:
2907: // --------------------------------------------------------------------------
2908: // Inner Classes
2909: // --------------------------------------------------------------------------
2910:
2911: /*---------------------------------------------------------------------------*/
2912: /**
2913: * This class can be used to associate a text string and a (text) value.
2914: */
2915: /*---------------------------------------------------------------------------*/
2916: private static class TextValuePair {
2917:
2918: private String text = "";
2919:
2920: private String value = "";
2921:
2922: /*--------------------------------------------------------------------------*/
2923: /**
2924: * Constructs a new Text/Value pair, initialized with the text and a value.
2925: *
2926: * @param text the text that this object should represent
2927: * @param value the value that should be associated with this object
2928: */
2929: /*--------------------------------------------------------------------------*/
2930: public TextValuePair(String text, String value) {
2931: this .text = text;
2932: this .value = value;
2933: }
2934:
2935: /*--------------------------------------------------------------------------*/
2936: /**
2937: * Sets the text
2938: *
2939: * @param text the text for this object
2940: */
2941: /*--------------------------------------------------------------------------*/
2942: public void setText(String text) {
2943: this .text = text;
2944: }
2945:
2946: /*--------------------------------------------------------------------------*/
2947: /**
2948: * Sets the value of this object
2949: *
2950: * @param value the value for this object
2951: */
2952: /*--------------------------------------------------------------------------*/
2953: public void setValue(String value) {
2954: this .value = value;
2955: }
2956:
2957: /*--------------------------------------------------------------------------*/
2958: /**
2959: * This method returns the text that was set for the object
2960: *
2961: * @return the object's text
2962: */
2963: /*--------------------------------------------------------------------------*/
2964: public String toString() {
2965: return (text);
2966: }
2967:
2968: /*--------------------------------------------------------------------------*/
2969: /**
2970: * This method returns the value that was associated with this object
2971: *
2972: * @return the object's value
2973: */
2974: /*--------------------------------------------------------------------------*/
2975: public String getValue() {
2976: return (value);
2977: }
2978: }
2979:
2980: /*---------------------------------------------------------------------------*/
2981: /**
2982: * This class encapsulates a lot of search field functionality.
2983: *
2984: * A search field supports searching directories and files on the target system. This is a
2985: * helper class to manage all data belonging to a search field.
2986: */
2987: /*---------------------------------------------------------------------------*/
2988:
2989: private class SearchField implements ActionListener {
2990:
2991: /** used in constructor - we search for a directory. */
2992: public static final int TYPE_DIRECTORY = 1;
2993:
2994: /** used in constructor - we search for a file. */
2995: public static final int TYPE_FILE = 2;
2996:
2997: /** used in constructor - result of search is the directory. */
2998: public static final int RESULT_DIRECTORY = 1;
2999:
3000: /** used in constructor - result of search is the whole file name. */
3001: public static final int RESULT_FILE = 2;
3002:
3003: /** used in constructor - result of search is the parent directory. */
3004: public static final int RESULT_PARENTDIR = 3;
3005:
3006: private String filename = null;
3007:
3008: private String checkFilename = null;
3009:
3010: private JButton autodetectButton = null;
3011:
3012: private JButton browseButton = null;
3013:
3014: private JComboBox pathComboBox = null;
3015:
3016: private int searchType = TYPE_DIRECTORY;
3017:
3018: private int resultType = RESULT_DIRECTORY;
3019:
3020: private InstallerFrame parent = null;
3021:
3022: /*---------------------------------------------------------------------------*/
3023: /**
3024: * Constructor - initializes the object, adds it as action listener to the "autodetect"
3025: * button.
3026: *
3027: * @param filename the name of the file to search for (might be null for searching
3028: * directories)
3029: * @param checkFilename the name of the file to check when searching for directories (the
3030: * checkFilename is appended to a found directory to figure out whether it is the right
3031: * directory)
3032: * @param combobox the <code>JComboBox</code> holding the list of choices; it should be
3033: * editable and contain only Strings
3034: * @param autobutton the autodetection button for triggering autodetection
3035: * @param browsebutton the browse button to look for the file
3036: * @param search_type what to search for - TYPE_FILE or TYPE_DIRECTORY
3037: * @param result_type what to return as the result - RESULT_FILE or RESULT_DIRECTORY or
3038: * RESULT_PARENTDIR
3039: */
3040: /*---------------------------------------------------------------------------*/
3041: public SearchField(String filename, String checkFilename,
3042: InstallerFrame parent, JComboBox combobox,
3043: JButton autobutton, JButton browsebutton,
3044: int search_type, int result_type) {
3045: this .filename = filename;
3046: this .checkFilename = checkFilename;
3047: this .parent = parent;
3048: this .autodetectButton = autobutton;
3049: this .browseButton = browsebutton;
3050: this .pathComboBox = combobox;
3051: this .searchType = search_type;
3052: this .resultType = result_type;
3053:
3054: this .autodetectButton.addActionListener(this );
3055: this .browseButton.addActionListener(this );
3056:
3057: /*
3058: * add DocumentListener to manage nextButton if user enters input
3059: */
3060: ((JTextField) this .pathComboBox.getEditor()
3061: .getEditorComponent()).getDocument()
3062: .addDocumentListener(new DocumentListener() {
3063: public void changedUpdate(DocumentEvent e) {
3064: checkNextButtonState();
3065: }
3066:
3067: public void insertUpdate(DocumentEvent e) {
3068: checkNextButtonState();
3069: }
3070:
3071: public void removeUpdate(DocumentEvent e) {
3072: checkNextButtonState();
3073: }
3074:
3075: private void checkNextButtonState() {
3076: Document doc = ((JTextField) pathComboBox
3077: .getEditor().getEditorComponent())
3078: .getDocument();
3079: try {
3080: if (pathMatches(doc.getText(0, doc
3081: .getLength())))
3082: getInstallerFrame()
3083: .unlockNextButton(false);
3084: else
3085: getInstallerFrame()
3086: .lockNextButton();
3087: } catch (BadLocationException e) {/*ignore, it not happens*/
3088: }
3089: }
3090: });
3091:
3092: autodetect();
3093: }
3094:
3095: /**
3096: * convenient method
3097: */
3098: private InstallerFrame getInstallerFrame() {
3099: return parent;
3100: }
3101:
3102: /**
3103: * Check whether the given combobox belongs to this searchfield. This is used when reading
3104: * the results.
3105: */
3106: public boolean belongsTo(JComboBox combobox) {
3107: return (this .pathComboBox == combobox);
3108: }
3109:
3110: /** check whether the given path matches */
3111: private boolean pathMatches(String path) {
3112: if (path != null) { // Make sure, path is not null
3113: // System.out.println ("checking path " + path);
3114:
3115: File file = null;
3116:
3117: if ((this .filename == null)
3118: || (this .searchType == TYPE_DIRECTORY)) {
3119: file = new File(path);
3120: } else {
3121: file = new File(path, this .filename);
3122: }
3123:
3124: if (file.exists()) {
3125:
3126: if (((this .searchType == TYPE_DIRECTORY) && (file
3127: .isDirectory()))
3128: || ((this .searchType == TYPE_FILE) && (file
3129: .isFile()))) {
3130: // no file to check for
3131: if (this .checkFilename == null)
3132: return true;
3133:
3134: file = new File(file, this .checkFilename);
3135:
3136: return file.exists();
3137: }
3138:
3139: }
3140:
3141: // System.out.println (path + " did not match");
3142: } // end if
3143: return false;
3144: }
3145:
3146: /** perform autodetection */
3147: public boolean autodetect() {
3148: Vector<String> items = new Vector<String>();
3149:
3150: /*
3151: * Check if the user has entered data into the ComboBox and add it to the Itemlist
3152: */
3153: String selected = (String) this .pathComboBox
3154: .getSelectedItem();
3155: if (selected == null) {
3156: parent.lockNextButton();
3157: return false;
3158: }
3159: boolean found = false;
3160: for (int x = 0; x < this .pathComboBox.getItemCount(); x++) {
3161: if (this .pathComboBox.getItemAt(x).equals(selected)) {
3162: found = true;
3163: }
3164: }
3165: if (!found) {
3166: // System.out.println("Not found in Itemlist");
3167: this .pathComboBox.addItem(this .pathComboBox
3168: .getSelectedItem());
3169: }
3170:
3171: // Checks whether a placeholder item is in the combobox
3172: // and resolve the pathes automatically:
3173: // /usr/lib/* searches all folders in usr/lib to find
3174: // /usr/lib/*/lib/tools.jar
3175: for (int i = 0; i < this .pathComboBox.getItemCount(); ++i) {
3176: String path = (String) this .pathComboBox.getItemAt(i);
3177:
3178: if (path.endsWith("*")) {
3179: path = path.substring(0, path.length() - 1);
3180: File dir = new File(path);
3181:
3182: if (dir.isDirectory()) {
3183: File[] subdirs = dir.listFiles();
3184: for (File subdir : subdirs) {
3185: String search = subdir.getAbsolutePath();
3186: if (this .pathMatches(search)) {
3187: items.add(search);
3188: }
3189: }
3190: }
3191: } else {
3192: if (this .pathMatches(path)) {
3193: items.add(path);
3194: }
3195: }
3196: }
3197: // Make the enties in the vector unique
3198: items = new Vector<String>(new HashSet<String>(items));
3199:
3200: // Now clear the combobox and add the items out of the newly
3201: // generated vector
3202: this .pathComboBox.removeAllItems();
3203: VariableSubstitutor vs = new VariableSubstitutor(idata
3204: .getVariables());
3205: for (String item : items) {
3206: this .pathComboBox.addItem(vs.substitute(item, "plain"));
3207: }
3208:
3209: // loop through all items
3210: for (int i = 0; i < this .pathComboBox.getItemCount(); ++i) {
3211: String path = (String) this .pathComboBox.getItemAt(i);
3212:
3213: if (this .pathMatches(path)) {
3214: this .pathComboBox.setSelectedIndex(i);
3215: parent.unlockNextButton();
3216: return true;
3217: }
3218:
3219: }
3220:
3221: // if the user entered something else, it's not listed as an item
3222: if (this .pathMatches((String) this .pathComboBox
3223: .getSelectedItem())) {
3224: parent.unlockNextButton();
3225: return true;
3226: }
3227: parent.lockNextButton();
3228: return false;
3229: }
3230:
3231: /*--------------------------------------------------------------------------*/
3232: /**
3233: * This is called if one of the buttons has been pressed.
3234: *
3235: * It checks, which button caused the action and acts accordingly.
3236: */
3237: /*--------------------------------------------------------------------------*/
3238: public void actionPerformed(ActionEvent event) {
3239: // System.out.println ("autodetection button pressed.");
3240:
3241: if (event.getSource() == this .autodetectButton) {
3242: if (!autodetect())
3243: showMessageDialog(
3244: parent,
3245: "UserInputPanel.search.autodetect.failed.message",
3246: "UserInputPanel.search.autodetect.failed.caption",
3247: JOptionPane.WARNING_MESSAGE);
3248: } else if (event.getSource() == this .browseButton) {
3249: JFileChooser chooser = new JFileChooser();
3250:
3251: if (this .resultType != TYPE_FILE)
3252: chooser
3253: .setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
3254:
3255: int result = chooser.showOpenDialog(this .parent);
3256:
3257: if (result == JFileChooser.APPROVE_OPTION) {
3258: File f = chooser.getSelectedFile();
3259:
3260: this .pathComboBox.setSelectedItem(f
3261: .getAbsolutePath());
3262:
3263: // use any given directory directly
3264: if (this .resultType != TYPE_FILE
3265: && !this .pathMatches(f.getAbsolutePath())) {
3266: showMessageDialog(
3267: parent,
3268: "UserInputPanel.search.wrongselection.message",
3269: "UserInputPanel.search.wrongselection.caption",
3270: JOptionPane.WARNING_MESSAGE);
3271:
3272: }
3273: }
3274:
3275: }
3276:
3277: // we don't care for anything more here - getResult() does the rest
3278: }
3279:
3280: /*--------------------------------------------------------------------------*/
3281: /**
3282: * Return the result of the search according to result type.
3283: *
3284: * Sometimes, the whole path of the file is wanted, sometimes only the directory where the
3285: * file is in, sometimes the parent directory.
3286: *
3287: * @return null on error
3288: */
3289: /*--------------------------------------------------------------------------*/
3290: public String getResult() {
3291: String item = (String) this .pathComboBox.getSelectedItem();
3292: if (item != null)
3293: item = item.trim();
3294: String path = item;
3295:
3296: File f = new File(item);
3297:
3298: if (!f.isDirectory()) {
3299: path = f.getParent();
3300: }
3301:
3302: // path now contains the final content of the combo box
3303: if (this .resultType == RESULT_DIRECTORY) {
3304: return path;
3305: } else if (this .resultType == RESULT_FILE) {
3306: if (this .filename != null) {
3307: return path + File.separatorChar + this .filename;
3308: } else {
3309: return item;
3310: }
3311: } else if (this .resultType == RESULT_PARENTDIR) {
3312: File dir = new File(path);
3313: return dir.getParent();
3314: }
3315:
3316: return null;
3317: }
3318:
3319: } // private class SearchFile
3320:
3321: protected void updateVariables() {
3322: /**
3323: * Look if there are new variables defined
3324: */
3325: Vector<XMLElement> variables = spec
3326: .getChildrenNamed(VARIABLE_NODE);
3327: RulesEngine rules = parent.getRules();
3328:
3329: VariableSubstitutor vs = new VariableSubstitutor(idata
3330: .getVariables());
3331: for (int i = 0; i < variables.size(); i++) {
3332: XMLElement variable = variables.elementAt(i);
3333: String vname = variable
3334: .getAttribute(ATTRIBUTE_VARIABLE_NAME);
3335: String vvalue = variable
3336: .getAttribute(ATTRIBUTE_VARIABLE_VALUE);
3337:
3338: if (vvalue == null) {
3339: // try to read value element
3340: if (variable.hasChildren()) {
3341: XMLElement value = variable
3342: .getFirstChildNamed("value");
3343: vvalue = value.getContent();
3344: }
3345: }
3346:
3347: String conditionid = variable
3348: .getAttribute(ATTRIBUTE_CONDITIONID_NAME);
3349: if (conditionid != null) {
3350: // check if condition for this variable is fulfilled
3351: if (!rules.isConditionTrue(conditionid, idata
3352: .getVariables())) {
3353: continue;
3354: }
3355: }
3356: // are there any OS-Constraints?
3357: if (OsConstraint.oneMatchesCurrentSystem(variable)) {
3358: if (vname == null) {
3359: } else {
3360: // vname is given
3361: if (vvalue != null) {
3362: // try to substitute variables in value field
3363: vvalue = vs.substitute(vvalue, null);
3364: // to cut out circular references
3365: idata.setVariable(vname, "");
3366: vvalue = vs.substitute(vvalue, null);
3367: }
3368: // try to set variable
3369: idata.setVariable(vname, vvalue);
3370:
3371: // for save this variable to be used later by Automation Helper
3372: entries.add(new TextValuePair(vname, vvalue));
3373: }
3374: }
3375: }
3376: }
3377:
3378: // Repaint all controls and validate them agains the current variables
3379: public void actionPerformed(ActionEvent e) {
3380: validating = false;
3381: readInput();
3382: panelActivate();
3383: validating = true;
3384: }
3385:
3386: /*--------------------------------------------------------------------------*/
3387: /**
3388: * Show localized message dialog basing on given parameters.
3389: *
3390: * @param parentFrame The parent frame.
3391: * @param message The message to print out in dialog box.
3392: * @param caption The caption of dialog box.
3393: * @param messageType The message type (JOptionPane.*_MESSAGE)
3394: */
3395: /*--------------------------------------------------------------------------*/
3396: private void showMessageDialog(InstallerFrame parentFrame,
3397: String message, String caption, int messageType) {
3398: String localizedMessage = langpack.getString(message);
3399: if ("".equals(localizedMessage)) {
3400: localizedMessage = message;
3401: }
3402: JOptionPane.showMessageDialog(parentFrame, localizedMessage,
3403: caption, messageType);
3404: }
3405:
3406: /*--------------------------------------------------------------------------*/
3407: /**
3408: * Show localized warning message dialog basing on given parameters.
3409: *
3410: * @param parentFrame parent frame.
3411: * @param message the message to print out in dialog box.
3412: */
3413: /*--------------------------------------------------------------------------*/
3414: private void showWarningMessageDialog(InstallerFrame parentFrame,
3415: String message) {
3416: showMessageDialog(parentFrame, message, parentFrame.langpack
3417: .getString("UserInputPanel.error.caption"),
3418: JOptionPane.WARNING_MESSAGE);
3419: }
3420:
3421: } // public class UserInputPanel
3422:
3423: /*---------------------------------------------------------------------------*/
3424: class UserInputFileFilter extends FileFilter {
3425: String fileext = "";
3426: String description = "";
3427:
3428: public void setFileExt(String fileext) {
3429: this .fileext = fileext;
3430: }
3431:
3432: public void setFileExtDesc(String desc) {
3433: this .description = desc;
3434: }
3435:
3436: public boolean accept(File pathname) {
3437: if (pathname.isDirectory()) {
3438: return true;
3439: } else {
3440: return pathname.getAbsolutePath().endsWith(this .fileext);
3441: }
3442: }
3443:
3444: public String getDescription() {
3445: return this.description;
3446: }
3447: }
|