Statistics
| Revision:

root / import / ext3D / trunk / install-extension3d / IzPack / src / lib / com / izforge / izpack / panels / UserInputPanel.java @ 15280

History | View | Annotate | Download (93.4 KB)

1
/*
2
 * $Id: UserInputPanel.java,v 1.1 2006/06/14 07:29:07 cesar Exp $
3
 * Copyright (C) 2002 Elmar Grom
4
 *
5
 * File :               UserInputPanel.java
6
 * Description :        A panel to collect input form the end user.
7
 * Author's email :     elmar@grom.net
8
 * Author's Website :   http://www.izforge.com
9
 *
10
 * This program is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU General Public License
12
 * as published by the Free Software Foundation; either version 2
13
 * of the License, or any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23
 */
24

    
25
package   com.izforge.izpack.panels;
26

    
27
import java.awt.Color;
28
import java.awt.Font;
29
import java.awt.event.ActionEvent;
30
import java.awt.event.ActionListener;
31
import java.io.File;
32
import java.io.InputStream;
33
import java.text.MessageFormat;
34
import java.util.HashMap;
35
import java.util.HashSet;
36
import java.util.Iterator;
37
import java.util.Map;
38
import java.util.StringTokenizer;
39
import java.util.Vector;
40

    
41
import javax.swing.BorderFactory;
42
import javax.swing.ButtonGroup;
43
import javax.swing.JButton;
44
import javax.swing.JCheckBox;
45
import javax.swing.JComboBox;
46
import javax.swing.JComponent;
47
import javax.swing.JFileChooser;
48
import javax.swing.JLabel;
49
import javax.swing.JOptionPane;
50
import javax.swing.JPanel;
51
import javax.swing.JPasswordField;
52
import javax.swing.JRadioButton;
53
import javax.swing.JTextField;
54

    
55
import net.n3.nanoxml.NonValidator;
56
import net.n3.nanoxml.StdXMLBuilder;
57
import net.n3.nanoxml.StdXMLParser;
58
import net.n3.nanoxml.StdXMLReader;
59
import net.n3.nanoxml.XMLElement;
60

    
61
import com.izforge.izpack.LocaleDatabase;
62
import com.izforge.izpack.Pack;
63
import com.izforge.izpack.gui.ButtonFactory;
64
import com.izforge.izpack.gui.TwoColumnConstraints;
65
import com.izforge.izpack.gui.TwoColumnLayout;
66
import com.izforge.izpack.installer.InstallData;
67
import com.izforge.izpack.installer.InstallerFrame;
68
import com.izforge.izpack.installer.IzPanel;
69
import com.izforge.izpack.installer.ResourceManager;
70
import com.izforge.izpack.installer.VariableSubstitutor;
71
import com.izforge.izpack.util.MultiLineLabel;
72
import com.izforge.izpack.util.OsConstraint;
73
import com.izforge.izpack.util.OsVersion;
74

    
75
/*---------------------------------------------------------------------------*/
76
/**
77
 * This panel is designed to collect user input during the installation
78
 * process. The panel is initially blank and is populated with input elements
79
 * based on the XML specification in a resource file.
80
 *
81
 *
82
 * @version  0.0.1 / 10/19/02
83
 * @author   getDirectoryCreated
84
 */
85
/*---------------------------------------------------------------------------*/
86
/*$
87
 * @design
88
 *
89
 * Each field is specified in its own node, containing attributes and data.
90
 * When this class is instantiated, the specification is read and analyzed.
91
 * Each field node is processed based on its type. An specialized member
92
 * function is called for each field type that creates the necessary UI
93
 * elements. All UI elements are stored in the uiElements vector. Elements
94
 * are packaged in an object array that must follow this pattern:
95
 *
96
 * index 0 - a String object, that specifies the field type. This is
97
 *           identical to the string used to identify the field type
98
 *           in the XML file.
99
 * index 1 - a String object that contains the variable name for substitution.
100
 * index 2 - the constraints object that should be used for positioning the
101
 *           UI element
102
 * index 3 - the UI element itself
103
 * index 4 - a Vector containg a list of pack for which the item should be
104
 *           created. This is used by buildUI() to decide if the item should
105
 *           be added to the UI.
106
 *
107
 * In some cases additional entries are used. The use depends on the specific
108
 * needs of the type of input field.
109
 *
110
 * When the panel is activated, the method buildUI() walks the list of UI
111
 * elements adds them to the panel together with the matching constraint.
112
 *
113
 * When an attempt is made to move on to another panel, the method readInput()
114
 * walks the list of UI elements again and calls specialized methods that
115
 * know how to read the user input from each of the UI elemnts and set the
116
 * associated varaible.
117
 *
118
 * The actual variable substitution is not performed by this panel but by
119
 * the variable substitutor.
120
 *
121
 * To Do:
122
 * ------
123
 * * make sure all header documentation is complete and correct
124
 *--------------------------------------------------------------------------*/
125
public class UserInputPanel extends IzPanel
126
{
127
  // ------------------------------------------------------------------------
128
  // Constant Definitions
129
  // ------------------------------------------------------------------------
130

    
131
  // The constants beginning with 'POS_' define locations in the object arrays
132
  // that used to hold all information for the individual fields. Some data is
133
  // not required for all field types. If this happens withing the array, that
134
  // location must be padded with 'null'. At the end of the array it can be
135
  // omitted. The data stored in this way is in most cases only known by
136
  // convention between the add and the associated read method. the following
137
  // positions are also used by other service methods in this class and must
138
  // not be used for other purposes:
139
  // - POS_DISPLAYED
140
  // - POS_TYPE
141
  // - POS_CONSTRAINTS
142
  // - POS_PACKS
143

    
144
  private static final int    POS_DISPLAYED                 = 0;
145
  private static final int    POS_TYPE                      = 1;
146
  private static final int    POS_VARIABLE                  = 2;
147
  private static final int    POS_CONSTRAINTS               = 3;
148
  private static final int    POS_FIELD                     = 4;
149
  private static final int    POS_PACKS                     = 5;
150
  private static final int    POS_OS                     = 6;
151
  private static final int    POS_TRUE                      = 7;
152
  private static final int    POS_FALSE                     = 8;
153
  private static final int    POS_MESSAGE                   = 9;
154
  private static final int    POS_GROUP                     = 10;
155

    
156
  /** The name of the XML file that specifies the panel layout */
157
  private static final String SPEC_FILE_NAME                = "userInputSpec.xml";
158
  private static final String LANG_FILE_NAME                = "userInputLang.xml";
159

    
160

    
161
  /** how the spec node for a specific panel is identified */
162
  private static final String NODE_ID                       = "panel";
163
  private static final String FIELD_NODE_ID                 = "field";
164
  private static final String INSTANCE_IDENTIFIER           = "order";
165
  private static final String TYPE                          = "type";
166
  private static final String DESCRIPTION                   = "description";
167
  private static final String VARIABLE                      = "variable";
168
  private static final String TEXT                          = "txt";
169
  private static final String KEY                           = "id";
170
  private static final String SPEC                          = "spec";
171
  private static final String SET                           = "set";
172
  private static final String TRUE                          = "true";
173
  private static final String FALSE                         = "false";
174
  private static final String ALIGNMENT                     = "align";
175
  private static final String LEFT                          = "left";
176
  private static final String CENTER                        = "center";
177
  private static final String RIGHT                         = "right";
178
  private static final String TOP                           = "top";
179
  private static final String BOTTOM                        = "bottom";
180
  private static final String ITALICS                       = "italic";
181
  private static final String BOLD                          = "bold";
182
  private static final String SIZE                          = "size";
183
  private static final String VALIDATOR                     = "validator";
184
  private static final String PROCESSOR                     = "processor";
185
  private static final String CLASS                         = "class";
186

    
187
  private static final String FIELD_LABEL                   = "label";
188

    
189
  private static final String TITLE_FIELD                   = "title";
190

    
191
  private static final String TEXT_FIELD                    = "text";
192
  private static final String TEXT_SIZE                     = "size";
193
  private static final String STATIC_TEXT                   = "staticText";
194

    
195
  private static final String COMBO_FIELD                   = "combo";
196
  private static final String COMBO_CHOICE                  = "choice";
197
  private static final String COMBO_VALUE                   = "value";
198

    
199
  private static final String RADIO_FIELD                   = "radio";
200
  private static final String RADIO_CHOICE                  = "choice";
201
  private static final String RADIO_VALUE                   = "value";
202

    
203
  private static final String SPACE_FIELD                   = "space";
204
  private static final String DIVIDER_FIELD                 = "divider";
205
  private static final String CHECK_FIELD                   = "check";
206

    
207
  private static final String RULE_FIELD                    = "rule";
208
  private static final String RULE_LAYOUT                   = "layout";
209
  private static final String RULE_SEPARATOR                = "separator";
210
  private static final String RULE_RESULT_FORMAT            = "resultFormat";
211
  private static final String RULE_PLAIN_STRING             = "plainString";
212
  private static final String RULE_DISPLAY_FORMAT           = "displayFormat";
213
  private static final String RULE_SPECIAL_SEPARATOR        = "specialSeparator";
214
  private static final String RULE_ENCRYPTED                = "processed";
215
  private static final String RULE_PARAM_NAME               = "name";
216
  private static final String RULE_PARAM_VALUE              = "value";
217
  private static final String RULE_PARAM                    = "param";
218

    
219
  private static final String PWD_FIELD                     = "password";
220
  private static final String PWD_INPUT                     = "pwd";
221
  private static final String PWD_SIZE                      = "size";
222

    
223
  private static final String SEARCH_FIELD                  = "search";
224
  // internal value for the button used to trigger autodetection
225
  private static final String SEARCH_BUTTON_FIELD           = "autodetect";
226
  private static final String SEARCH_CHOICE                 = "choice";
227
  private static final String SEARCH_FILENAME               = "filename";
228
  private static final String SEARCH_RESULT                 = "result";
229
  private static final String SEARCH_VALUE                  = "value";
230
  private static final String SEARCH_TYPE                   = "type";
231
  private static final String SEARCH_FILE                   = "file";
232
  private static final String SEARCH_DIRECTORY              = "directory";
233
  private static final String SEARCH_PARENTDIR              = "parentdir";
234
  private static final String SEARCH_CHECKFILENAME          = "checkfilename";
235

    
236
  private static final String PACKS                         = "createForPack";
237
  private static final String NAME                          = "name";
238

    
239
  private static final String OS = "os";
240
  private static final String FAMILY = "family";
241

    
242

    
243
  // ------------------------------------------------------------------------
244
  // Variable Declarations
245
  // ------------------------------------------------------------------------
246
  private static int          instanceCount   = 0;
247
  protected      int          instanceNumber  = 0;
248
  private        boolean      uiBuilt         = false;
249

    
250
  /** If there is a possibility that some UI elements will not get added we
251
      can not allow to go back to the PacksPanel, because the process of
252
      building the UI is not reversable. This variable keeps track if any
253
      packs have been defined and will be used to make a decision for
254
      locking the 'previous' button. */
255
  private         boolean     packsDefined    = false;
256

    
257
  private InstallerFrame      parentFrame;
258
  /** The parsed result from reading the XML specification from the file */
259
  private XMLElement          spec;
260
  private boolean             haveSpec = false;
261

    
262
  /** Holds the references to all of the UI elements */
263
  private Vector              uiElements      = new Vector ();
264
  /** Holds the references to all radio button groups */
265
  private Vector              buttonGroups    = new Vector ();
266
  /** Holds the references to all password field groups */
267
  private Vector              passwordGroups  = new Vector ();
268
  /** used for temporary storage of references to password groups that
269
      have already been read in a given read cycle. */
270
  private Vector              passwordGroupsRead  = new Vector ();
271
  /** Used to track search fields. Contains SearchField references. */
272
  private Vector              searchFields = new Vector();
273

    
274
  /** Holds all user inputs for use in automated installation */
275
  private Vector              entries         = new Vector ();
276

    
277
  private TwoColumnLayout     layout;
278
  private LocaleDatabase      langpack        = null;
279

    
280

    
281
 /*--------------------------------------------------------------------------*/
282
 // This method can be used to search for layout problems. If this class is
283
 // compiled with this method uncommented, the layout guides will be shown
284
 // on the panel, making it possible to see if all components are placed
285
 // correctly.
286
 /*--------------------------------------------------------------------------*/
287
//  public void paint (Graphics graphics)
288
//  {
289
//    super.paint (graphics);
290
//    layout.showRules ((Graphics2D)graphics, Color.red);
291
//  }
292
 /*--------------------------------------------------------------------------*/
293
 /**
294
  * Constructs a <code>UserInputPanel</code>.
295
  *
296
  * @param     parent       reference to the application frame
297
  * @param     installData  shared information about the installation
298
  */
299
 /*--------------------------------------------------------------------------*/
300
  public UserInputPanel (InstallerFrame parent,
301
                         InstallData    installData)
302

    
303
  {
304
    super (parent, installData);
305

    
306
    instanceNumber = instanceCount++;
307
    this.parentFrame = parent;
308

    
309
    // ----------------------------------------------------
310
    // ----------------------------------------------------
311
    layout = new TwoColumnLayout (10, 5, 30, 25, TwoColumnLayout.LEFT);
312
    setLayout (layout);
313

    
314
    // ----------------------------------------------------
315
    // get a locale database
316
    // ----------------------------------------------------
317
    try
318
    {
319
      //this.langpack = parent.langpack;
320

    
321
      String resource = LANG_FILE_NAME+"_"+idata.localeISO3;
322
      this.langpack = new LocaleDatabase (ResourceManager.getInstance().getInputStream (resource));
323
    }
324
    catch (Throwable exception)
325
    {}
326

    
327
    // ----------------------------------------------------
328
    // read the specifications
329
    // ----------------------------------------------------
330
    try
331
    {
332
      readSpec ();
333
    }
334
    catch (Throwable exception)
335
    {
336
      // log the problem
337
      exception.printStackTrace ();
338
    }
339

    
340
    if (!haveSpec)
341
    {
342
      // return if we could not read the spec. further
343
      // processing will only lead to problems. In this
344
      // case we must skip the panel when it gets activated.
345
      return;
346
    }
347

    
348
    // ----------------------------------------------------
349
    // process all field nodes. Each field node is analyzed
350
    // for its type, then an appropriate memeber function
351
    // is called that will create the correct UI elements.
352
    // ----------------------------------------------------
353
    Vector fields = spec.getChildrenNamed (FIELD_NODE_ID);
354

    
355
    for (int i = 0; i < fields.size (); i++)
356
    {
357
      XMLElement  field     = (XMLElement)fields.elementAt (i);
358
      String      attribute = field.getAttribute (TYPE);
359

    
360
      if (attribute != null)
361
      {
362
        if (attribute.equals (RULE_FIELD))
363
        {
364
          addRuleField (field);
365
        }
366
        else if (attribute.equals (TEXT_FIELD))
367
        {
368
          addTextField (field);
369
        }
370
        else if (attribute.equals (COMBO_FIELD))
371
        {
372
          addComboBox (field);
373
        }
374
        else if (attribute.equals (RADIO_FIELD))
375
        {
376
          addRadioButton (field);
377
        }
378
        else if (attribute.equals (PWD_FIELD))
379
        {
380
          addPasswordField (field);
381
        }
382
        else if (attribute.equals (SPACE_FIELD))
383
        {
384
          addSpace (field);
385
        }
386
        else if (attribute.equals (DIVIDER_FIELD))
387
        {
388
          addDivider (field);
389
        }
390
        else if (attribute.equals (CHECK_FIELD))
391
        {
392
          addCheckBox (field);
393
        }
394
        else if (attribute.equals (STATIC_TEXT))
395
        {
396
          addText (field);
397
        }
398
        else if (attribute.equals (TITLE_FIELD))
399
        {
400
          addTitle (field);
401
        }
402
        else if (attribute.equals (SEARCH_FIELD))
403
        {
404
          addSearch (field);
405
        }
406
      }
407
    }
408
  }
409

    
410
 /*--------------------------------------------------------------------------*/
411
 /**
412
  * Indicates wether the panel has been validated or not. The installer won't
413
  * let the user go further through the installation process until the panel
414
  * is validated. Default behavior is to return true.
415
  *
416
  * @return    A boolean stating wether the panel has been validated or not.
417
  */
418
 /*--------------------------------------------------------------------------*/
419
  public boolean isValidated ()
420
  {
421
    return (readInput ());
422
  }
423
 /*--------------------------------------------------------------------------*/
424
 /**
425
  * This method is called when the panel becomes active.
426
  */
427
 /*--------------------------------------------------------------------------*/
428
  public void panelActivate ()
429
  {
430
    if (spec == null)
431
    {
432
      // TODO: translate
433
      emitError("User input specification could not be found.",
434
          "The specification for the user input panel could not be found. Please contact the packager.");
435
      parentFrame.skipPanel();
436
    }
437

    
438
    Vector forPacks = spec.getChildrenNamed (PACKS);
439
    Vector forOs = spec.getChildrenNamed(OS);
440

    
441
    if (!itemRequiredFor (forPacks) || !itemRequiredForOs(forOs))
442
    {
443
      parentFrame.skipPanel ();
444
      return;
445
    }
446
    if (!haveSpec)
447
    {
448
      parentFrame.skipPanel ();
449
      return;
450
    }
451
   // if (uiBuilt)
452
    //{
453
     // return;
454
    //}
455

    
456
    buildUI ();
457
    uiBuilt = true;
458

    
459
    if (packsDefined)
460
    {
461
      parentFrame.lockPrevButton ();
462
    }
463
  }
464
 /*--------------------------------------------------------------------------*/
465
 /**
466
  * Asks the panel to set its own XML data that can be brought back for an
467
  * automated installation process. Use it as a blackbox if your panel needs
468
  * to do something even in automated mode.
469
  *
470
  * @param     panelRoot    The XML root element of the panels blackbox tree.
471
  */
472
 /*--------------------------------------------------------------------------*/
473
  public void makeXMLData (XMLElement panelRoot)
474
  {
475
                Map entryMap = new HashMap();
476

    
477
                for (int i = 0; i < entries.size (); i++)
478
                {
479
                        TextValuePair pair = (TextValuePair)entries.elementAt(i);
480
                        entryMap.put( pair.toString(), pair.getValue() );
481
                }
482

    
483
                new UserInputPanelAutomationHelper(entryMap).makeXMLData(idata, panelRoot);
484
  }
485

    
486
 /*--------------------------------------------------------------------------*/
487
 /**
488
  * Builds the UI and makes it ready for display
489
  */
490
 /*--------------------------------------------------------------------------*/
491
  private void buildUI ()
492
  {
493
    Object [] uiElement;
494

    
495
    for (int i = 0; i < uiElements.size (); i++)
496
    {
497
      uiElement = (Object [])uiElements.elementAt (i);
498

    
499
      if (itemRequiredFor ((Vector)uiElement [POS_PACKS]) && itemRequiredForOs((Vector) uiElement[POS_OS]) )
500
      {
501
        try
502
        {
503
                if (uiElement [POS_DISPLAYED] == null || uiElement [POS_DISPLAYED].toString().equals("false"))
504
                {
505
                  add ((JComponent)uiElement [POS_FIELD], uiElement [POS_CONSTRAINTS]);
506
                }
507
          
508
                uiElement [POS_DISPLAYED] = Boolean.valueOf (true);
509
                uiElements.remove(i);
510
                uiElements.add(i, uiElement);          
511
        }
512
        catch (Throwable exception)
513
        {
514
          System.out.println ("Internal format error in field: " + uiElement [POS_TYPE].toString ());  // !!! logging
515
        }
516
      }
517
      else
518
      {
519
              try
520
              {
521
                if (uiElement [POS_DISPLAYED] != null && uiElement [POS_DISPLAYED].toString().equals("true"))
522
                {
523
                  remove((JComponent)uiElement [POS_FIELD]);
524
                }
525
              }
526
              catch (Throwable exception)
527
              {
528
                System.out.println ("Internal format error in field: " + uiElement [POS_TYPE].toString ());  // !!! logging
529
              }
530
        uiElement [POS_DISPLAYED] = Boolean.valueOf (false);
531
        uiElements.remove(i);
532
        uiElements.add(i, uiElement);
533
      }
534
    }
535
  }
536
 /*--------------------------------------------------------------------------*/
537
 /**
538
  * Reads the input data from all UI elements and sets the associated variables.
539
  *
540
  * @return    <code>true</code> if the operation is successdul, otherwise
541
  *            <code>false</code>.
542
  */
543
 /*--------------------------------------------------------------------------*/
544
  private boolean readInput ()
545
  {
546
    boolean     success;
547
    String      fieldType = null;
548
    Object []   field     = null;
549

    
550
    passwordGroupsRead.clear ();
551
    // ----------------------------------------------------
552
    // cycle through all but the password fields and read
553
    // their contents
554
    // ----------------------------------------------------
555
    for (int i = 0; i < uiElements.size (); i++)
556
    {
557
      field     = (Object [])uiElements.elementAt (i);
558

    
559
      if ((field != null) && (((Boolean)field [POS_DISPLAYED]).booleanValue ()))
560
      {
561
        fieldType = (String)(field [POS_TYPE]);
562

    
563
        // ------------------------------------------------
564
        if (fieldType.equals (RULE_FIELD))
565
        {
566
          success = readRuleField (field);
567
          if (!success)
568
          {
569
            return (false);
570
          }
571
        }
572

    
573
        // ------------------------------------------------
574
        if (fieldType.equals (PWD_FIELD))
575
        {
576
          success = readPasswordField (field);
577
          if (!success)
578
          {
579
            return (false);
580
          }
581
        }
582

    
583
        // ------------------------------------------------
584
        else if (fieldType.equals (TEXT_FIELD))
585
        {
586
          success = readTextField (field);
587
          if (!success)
588
          {
589
            return (false);
590
          }
591
        }
592

    
593
        // ------------------------------------------------
594
        else if (fieldType.equals (COMBO_FIELD))
595
        {
596
          success = readComboBox (field);
597
          if (!success)
598
          {
599
            return (false);
600
          }
601
        }
602

    
603
        // ------------------------------------------------
604
        else if (fieldType.equals (RADIO_FIELD))
605
        {
606
          success = readRadioButton (field);
607
          if (!success)
608
          {
609
            return (false);
610
          }
611
        }
612

    
613
        // ------------------------------------------------
614
        else if (fieldType.equals (CHECK_FIELD))
615
        {
616
          success = readCheckBox (field);
617
          if (!success)
618
          {
619
            return (false);
620
          }
621
        }
622
        else if (fieldType.equals (SEARCH_FIELD))
623
        {
624
          success = readSearch (field);
625
          if (!success)
626
          {
627
            return (false);
628
          }
629
        }
630
      }
631
    }
632

    
633
    return (true);
634
  }
635
 /*--------------------------------------------------------------------------*/
636
 /**
637
  * Reads the XML specification for the panel layout. The result is
638
  * stored in spec.
639
  *
640
  * @exception Exception for any problems in reading the specification
641
  */
642
 /*--------------------------------------------------------------------------*/
643
  private void readSpec () throws Exception
644
  {
645
    InputStream input = null;
646
    XMLElement  data;
647
    Vector      specElements;
648
    String      attribute;
649
    String      instance = Integer.toString (instanceNumber);
650

    
651
    try
652
    {
653
      input = parentFrame.getResource (SPEC_FILE_NAME);
654
    }
655
    catch (Exception exception)
656
    {
657
      haveSpec = false;
658
      return;
659
    }
660
    if (input == null)
661
    {
662
      haveSpec = false;
663
      return;
664
    }
665

    
666
    // initialize the parser
667
    StdXMLParser parser = new StdXMLParser ();
668
    parser.setBuilder   (new StdXMLBuilder ());
669
    parser.setValidator (new NonValidator ());
670
    parser.setReader    (new StdXMLReader (input));
671

    
672
    // get the data
673
    data = (XMLElement) parser.parse ();
674

    
675
    // extract the spec to this specific panel instance
676
    if (data.hasChildren ())
677
    {
678
      specElements = data.getChildrenNamed (NODE_ID);
679
      for (int i = 0; i < specElements.size (); i++)
680
      {
681
        data      = (XMLElement)specElements.elementAt (i);
682
        attribute = data.getAttribute (INSTANCE_IDENTIFIER);
683

    
684
        if (instance.equals (attribute))
685
        {
686
          // use the current element as spec
687
          spec = data;
688
          // close the stream
689
          input.close ();
690
          haveSpec = true;
691
          return;
692
        }
693
      }
694

    
695
      haveSpec = false;
696
      return;
697
    }
698

    
699
    haveSpec = false;
700
  }
701
 /*--------------------------------------------------------------------------*/
702
 /**
703
  * Adds the title to the panel. There can only be one title, if mutiple
704
  * titles are defined, they keep overwriting what has already be defined,
705
  * so that the last definition is the one that prevails.
706
  *
707
  * @param     spec  a <code>XMLElement</code> containing the specification
708
  *                  for the title.
709
  */
710
 /*--------------------------------------------------------------------------*/
711
  private void addTitle (XMLElement spec)
712
  {
713
    String  title       = getText       (spec);
714
    boolean italic      = getBoolean    (spec, ITALICS, false);
715
    boolean bold        = getBoolean    (spec, BOLD, false);
716
    float   multiplier  = getFloat      (spec, SIZE, 2.0f);
717
    int     justify     = getAlignment  (spec);
718

    
719
    if (title != null)
720
    {
721
      JLabel label = new JLabel (title);
722
      Font   font  = label.getFont ();
723
      float  size  = font.getSize ();
724
      int    style = 0;
725

    
726
      if (bold)
727
      {
728
        style = style + Font.BOLD;
729
      }
730
      if (italic)
731
      {
732
        style = style + Font.ITALIC;
733
      }
734

    
735
      font = font.deriveFont (style, (size * multiplier));
736
      label.setFont (font);
737
      label.setAlignmentX (0);
738

    
739
      TwoColumnConstraints constraints = new TwoColumnConstraints ();
740
      constraints.align     = justify;
741
      constraints.position  = TwoColumnConstraints.NORTH;
742

    
743
      add (label, constraints);
744
    }
745
  }
746
 /*--------------------------------------------------------------------------*/
747
 /**
748
  * Adds a rule field to the list of UI elements.
749
  *
750
  * @param     spec  a <code>XMLElement</code> containing the specification
751
  *                  for the rule field.
752
  */
753
 /*--------------------------------------------------------------------------*/
754
  private void addRuleField (XMLElement spec)
755
  {
756
    Vector forPacks = spec.getChildrenNamed (PACKS);
757
        Vector forOs = spec.getChildrenNamed(OS);
758
    XMLElement      element       = spec.getFirstChildNamed (SPEC);
759
    String          variable      = spec.getAttribute (VARIABLE);
760
    RuleInputField  field         = null;
761
    JLabel          label;
762
    String          layout;
763
    String          set;
764
    String          separator;
765
    String          format;
766
    String          validator     = null;
767
    String          message       = null;
768
        boolean         hasParams        = false;
769
        String          paramName        = null;
770
        String          paramValue       = null;
771
        HashMap         validateParamMap = null;
772
        Vector          validateParams   = null;
773
    String          processor     = null;
774
    int             resultFormat  = RuleInputField.DISPLAY_FORMAT;
775

    
776
    // ----------------------------------------------------
777
    // extract the specification details
778
    // ----------------------------------------------------
779
    if (element != null)
780
    {
781
      label     = new JLabel (getText (element));
782
      layout    = element.getAttribute (RULE_LAYOUT);
783
      set       = element.getAttribute (SET);
784

    
785
      // retrieve value of variable if not specified
786
      // (does not work here because of special format for set attribute)
787
      //if (set == null)
788
      //{
789
      //  set = idata.getVariable (variable);
790
      //}
791

    
792
      separator = element.getAttribute (RULE_SEPARATOR);
793
      format    = element.getAttribute (RULE_RESULT_FORMAT);
794

    
795
      if (format != null)
796
      {
797
        if (format.equals (RULE_PLAIN_STRING))
798
        {
799
          resultFormat = RuleInputField.PLAIN_STRING;
800
        }
801
        else if (format.equals (RULE_DISPLAY_FORMAT))
802
        {
803
          resultFormat = RuleInputField.DISPLAY_FORMAT;
804
        }
805
        else if (format.equals (RULE_SPECIAL_SEPARATOR))
806
        {
807
          resultFormat = RuleInputField.SPECIAL_SEPARATOR;
808
        }
809
        else if (format.equals (RULE_ENCRYPTED))
810
        {
811
          resultFormat = RuleInputField.ENCRYPTED;
812
        }
813
      }
814
    }
815
    // ----------------------------------------------------
816
    // if there is no specification element, return without
817
    // doing anything.
818
    // ----------------------------------------------------
819
    else
820
    {
821
      return;
822
    }
823

    
824
    // ----------------------------------------------------
825
    // get the description and add it to the list of UI
826
    // elements if it exists.
827
    // ----------------------------------------------------
828
    element = spec.getFirstChildNamed (DESCRIPTION);
829
    addDescription (element, forPacks, forOs);
830

    
831
    // ----------------------------------------------------
832
    // get the validator and processor if they are defined
833
    // ----------------------------------------------------
834
    element = spec.getFirstChildNamed (VALIDATOR);
835
    if (element != null)
836
    {
837
      validator = element.getAttribute (CLASS);
838
      message   = getText (element);
839
      // ----------------------------------------------------------
840
      // check and see if we have any parameters for this validator.
841
      // If so, then add them to validateParamMap.
842
      // ----------------------------------------------------------
843
      validateParams = element.getChildrenNamed(RULE_PARAM);
844
      if (validateParams != null
845
          && validateParams.size() > 0
846
          && validateParamMap == null)
847
      {
848

    
849
        validateParamMap = new HashMap();
850
        hasParams = true;
851

    
852
      }
853

    
854
      for (Iterator it = validateParams.iterator(); it.hasNext();)
855
      {
856
        element = (XMLElement) it.next();
857
        paramName = element.getAttribute(RULE_PARAM_NAME);
858
        paramValue = element.getAttribute(RULE_PARAM_VALUE);
859
        validateParamMap.put(paramName, paramValue);
860
      }
861
    }
862

    
863
    element = spec.getFirstChildNamed (PROCESSOR);
864
    if (element != null)
865
    {
866
      processor = element.getAttribute (CLASS);
867
    }
868

    
869
    // ----------------------------------------------------
870
    // create an instance of RuleInputField based on the
871
    // extracted specifications, then add it to the list
872
    // of UI elements.
873
    // ----------------------------------------------------
874
    if (hasParams)
875
    {
876
      field =
877
        new RuleInputField(
878
          layout,
879
          set,
880
          separator,
881
          validator,
882
          validateParamMap,
883
          processor,
884
          resultFormat,
885
          getToolkit());
886
    }
887
    else
888
    {
889
      field =
890
        new RuleInputField(
891
          layout,
892
          set,
893
          separator,
894
          validator,
895
          processor,
896
          resultFormat,
897
          getToolkit ());
898

    
899
    }
900
    TwoColumnConstraints constraints = new TwoColumnConstraints ();
901
    constraints.position              = TwoColumnConstraints.WEST;
902

    
903
    uiElements.add (new Object [] {null, FIELD_LABEL, null, constraints, label, forPacks, forOs});
904

    
905
    TwoColumnConstraints constraints2 = new TwoColumnConstraints ();
906
    constraints2.position             = TwoColumnConstraints.EAST;
907

    
908
    uiElements.add (new Object [] {null, RULE_FIELD, variable, constraints2, field, forPacks, forOs, null, null, message});
909
  }
910
 /*--------------------------------------------------------------------------*/
911
 /**
912
  * Reads the data from the rule input field and sets the associated variable.
913
  *
914
  * @param     field  the object array that holds the details of the field.
915
  *
916
  * @return    <code>true</code> if there was no problem reading the data or
917
  *            if there was an irrecovarable problem. If there was a problem
918
  *            that can be corrected by the operator, an error dialog is
919
  *            popped up and <code>false</code> is returned.
920
  */
921
 /*--------------------------------------------------------------------------*/
922
  private boolean readRuleField (Object [] field)
923
  {
924
    RuleInputField  ruleField = null;
925
    String          variable  = null;
926

    
927
    try
928
    {
929
      ruleField = (RuleInputField)field [POS_FIELD];
930
      variable  = (String)field [POS_VARIABLE];
931
    }
932
    catch (Throwable exception)
933
    {
934
      return (true);
935
    }
936
    if ((variable == null) || (ruleField == null))
937
    {
938
      return (true);
939
    }
940

    
941
    boolean success = ruleField.validateContents ();
942
    if (!success)
943
    {
944
        String message = "";
945
        try{
946
                message = langpack.getString( (String)field [POS_MESSAGE]);
947
                if (message.equals("")){
948
                        message = (String)field [POS_MESSAGE];
949
                }
950
        }catch (Throwable t){
951
                        message = (String)field [POS_MESSAGE];
952
        }
953
      JOptionPane.showMessageDialog (parentFrame,
954
                                     message,
955
                                     parentFrame.langpack.getString ("UserInputPanel.error.caption"),
956
                                     JOptionPane.WARNING_MESSAGE);
957
      return (false);
958
    }
959

    
960
    idata.setVariable (variable, ruleField.getText ());
961
    entries.add (new TextValuePair (variable, ruleField.getText ()));
962
    return (true);
963
  }
964
 /*--------------------------------------------------------------------------*/
965
 /**
966
  * Adds a text field to the list of UI elements
967
  *
968
  * @param     spec  a <code>XMLElement</code> containing the specification
969
  *                  for the text field.
970
  */
971
 /*--------------------------------------------------------------------------*/
972
  private void addTextField (XMLElement spec)
973
  {
974
    Vector      forPacks = spec.getChildrenNamed (PACKS);
975
        Vector forOs = spec.getChildrenNamed(OS);
976
    XMLElement  element  = spec.getFirstChildNamed (SPEC);
977
    JLabel      label;
978
    String      set;
979
    int         size;
980

    
981
    String      variable = spec.getAttribute (VARIABLE);
982
    if ((variable == null) || (variable.length () == 0))
983
    {
984
      return;
985
    }
986

    
987
    // ----------------------------------------------------
988
    // extract the specification details
989
    // ----------------------------------------------------
990
    if (element != null)
991
    {
992
      label = new JLabel (getText (element));
993
      set   = element.getAttribute (SET);
994
      if (set == null)
995
      {
996
        set = idata.getVariable (variable);
997
        if (set == null)
998
        {
999
          set = "";
1000
        }
1001
      }
1002
      try
1003
      {
1004
        size = Integer.parseInt (element.getAttribute (TEXT_SIZE));
1005
      }
1006
      catch (Throwable exception)
1007
      {
1008
        size = 1;
1009
      }
1010
    }
1011
    // ----------------------------------------------------
1012
    // if there is no specification element, return without
1013
    // doing anything.
1014
    // ----------------------------------------------------
1015
    else
1016
    {
1017
      return;
1018
    }
1019

    
1020
    // ----------------------------------------------------
1021
    // get the description and add it to the list UI
1022
    // elements if it exists.
1023
    // ----------------------------------------------------
1024
    element = spec.getFirstChildNamed (DESCRIPTION);
1025
    addDescription (element, forPacks, forOs);
1026

    
1027
    // ----------------------------------------------------
1028
    // construct the UI element and add it to the list
1029
    // ----------------------------------------------------
1030
    JTextField field = new JTextField (set, size);
1031
    field.setCaretPosition (0);
1032

    
1033
    TwoColumnConstraints constraints = new TwoColumnConstraints ();
1034
    constraints.position  = TwoColumnConstraints.WEST;
1035

    
1036
    uiElements.add (new Object [] {null, FIELD_LABEL, null, constraints, label, forPacks, forOs});
1037

    
1038
    TwoColumnConstraints constraints2 = new TwoColumnConstraints ();
1039
    constraints2.position  = TwoColumnConstraints.EAST;
1040

    
1041
    uiElements.add (new Object [] {null, TEXT_FIELD, variable, constraints2, field, forPacks, forOs});
1042
  }
1043
 /*--------------------------------------------------------------------------*/
1044
 /**
1045
  * Reads data from the text field and sets the associated variable.
1046
  *
1047
  * @param     field  the object array that holds the details of the field.
1048
  *
1049
  * @return    <code>true</code> if there was no problem reading the data or
1050
  *            if there was an irrecovarable problem. If there was a problem
1051
  *            that can be corrected by the operator, an error dialog is
1052
  *            popped up and <code>false</code> is returned.
1053
  */
1054
 /*--------------------------------------------------------------------------*/
1055
  private boolean readTextField (Object [] field)
1056
  {
1057
    JTextField  textField = null;
1058
    String      variable  = null;
1059
    String      value     = null;
1060

    
1061
    try
1062
    {
1063
      textField = (JTextField)field [POS_FIELD];
1064
      variable  = (String)field [POS_VARIABLE];
1065
      value     = textField.getText ();
1066
    }
1067
    catch (Throwable exception)
1068
    {
1069
      return (true);
1070
    }
1071
    if ((variable == null) || (value == null))
1072
    {
1073
      return (true);
1074
    }
1075

    
1076
    idata.setVariable(variable, value);
1077
    entries.add (new TextValuePair (variable, value));
1078
    return (true);
1079
  }
1080
 /*--------------------------------------------------------------------------*/
1081
 /**
1082
  * Adds a combo box to the list of UI elements. <br>
1083
  * This is a complete example of a valid XML specification
1084
  * <pre>
1085
  * <field type="combo" variable="testVariable">
1086
  *   <description text="Description for the combo box" id="a key for translated text"/>
1087
  *   <spec text="label" id="key for the label"/>
1088
  *     <choice text="choice 1" id="" value="combo box 1"/>
1089
  *     <choice text="choice 2" id="" value="combo box 2" set="true"/>
1090
  *     <choice text="choice 3" id="" value="combo box 3"/>
1091
  *     <choice text="choice 4" id="" value="combo box 4"/>
1092
  *   </spec>
1093
  * </field>
1094
  * </pre>
1095
  * @param     spec  a <code>XMLElement</code> containing the specification
1096
  *                  for the combo box.
1097
  */
1098
 /*--------------------------------------------------------------------------*/
1099
  private void addComboBox (XMLElement spec)
1100
  {
1101
    Vector        forPacks  = spec.getChildrenNamed (PACKS);
1102
        Vector forOs = spec.getChildrenNamed(OS);
1103
    XMLElement    element   = spec.getFirstChildNamed (SPEC);
1104
    String        variable  = spec.getAttribute (VARIABLE);
1105
    TextValuePair listItem  = null;
1106
    JComboBox     field     = new JComboBox ();
1107
    JLabel        label;
1108

    
1109
    // ----------------------------------------------------
1110
    // extract the specification details
1111
    // ----------------------------------------------------
1112
    if (element != null)
1113
    {
1114
      label = new JLabel (getText (element));
1115

    
1116
      Vector choices = element.getChildrenNamed (COMBO_CHOICE);
1117

    
1118
      if (choices == null)
1119
      {
1120
        return;
1121
      }
1122

    
1123
      for (int i = 0; i < choices.size (); i++)
1124
      {
1125
        String processorClass = ((XMLElement)choices.elementAt (i)).getAttribute("processor");
1126

    
1127
        if (!"".equals(processorClass))
1128
        {
1129
                        String choiceValues = "";
1130
                try
1131
                {
1132
                                choiceValues = ((Processor) Class.forName(processorClass).newInstance()).process(null);
1133
                }
1134
                catch (Throwable t)
1135
                {
1136
                        t.printStackTrace();
1137
                }
1138
                        String set    = ((XMLElement)choices.elementAt (i)).getAttribute (SET);
1139
                        if (set == null)
1140
                        {
1141
                                set = "";
1142
                        }
1143
                StringTokenizer tokenizer = new StringTokenizer(choiceValues, ":");
1144
                int counter = 0;
1145
                while (tokenizer.hasMoreTokens()){
1146
                        String token = tokenizer.nextToken();
1147
                        listItem = new TextValuePair(token, token);
1148
                        field.addItem(listItem);
1149
                                if (set.equals(token)){
1150
                                        field.setSelectedIndex (field.getItemCount()-1);
1151
                                }
1152
                        counter++;
1153
                }
1154
        }
1155
        else
1156
        {
1157
                listItem = new TextValuePair (getText ((XMLElement)choices.elementAt (i)),
1158
                                          ((XMLElement)choices.elementAt (i)).getAttribute (COMBO_VALUE));
1159
                        field.addItem (listItem);
1160
                        String set    = ((XMLElement)choices.elementAt (i)).getAttribute (SET);
1161
                        if (set != null)
1162
                        {
1163
                          if (set.equals (TRUE))
1164
                          {
1165
                                field.setSelectedIndex (i);
1166
                          }
1167
                        }
1168
        }
1169

    
1170

    
1171

    
1172
      }
1173
    }
1174
    // ----------------------------------------------------
1175
    // if there is no specification element, return without
1176
    // doing anything.
1177
    // ----------------------------------------------------
1178
    else
1179
    {
1180
      return;
1181
    }
1182

    
1183
    // ----------------------------------------------------
1184
    // get the description and add it to the list of UI
1185
    // elements if it exists.
1186
    // ----------------------------------------------------
1187
    element = spec.getFirstChildNamed (DESCRIPTION);
1188
    addDescription (element, forPacks, forOs);
1189

    
1190
    TwoColumnConstraints constraints = new TwoColumnConstraints ();
1191
    constraints.position  = TwoColumnConstraints.WEST;
1192

    
1193
    uiElements.add (new Object [] {null, FIELD_LABEL, null, constraints, label, forPacks, forOs});
1194

    
1195
    TwoColumnConstraints constraints2 = new TwoColumnConstraints ();
1196
    constraints2.position  = TwoColumnConstraints.EAST;
1197

    
1198
    uiElements.add (new Object [] {null, COMBO_FIELD, variable, constraints2, field, forPacks, forOs});
1199
  }
1200
 /*--------------------------------------------------------------------------*/
1201
 /**
1202
  * Reads the content of the combobox field and substitutes the associated
1203
  * variable.
1204
  *
1205
  * @param     field  the object array that holds the details of the field.
1206
  *
1207
  * @return    <code>true</code> if there was no problem reading the data or
1208
  *            if there was an irrecovarable problem. If there was a problem
1209
  *            that can be corrected by the operator, an error dialog is
1210
  *            popped up and <code>false</code> is returned.
1211
  */
1212
 /*--------------------------------------------------------------------------*/
1213
  private boolean readComboBox (Object [] field)
1214
  {
1215
    String variable;
1216
    String value;
1217
    JComboBox comboBox;
1218

    
1219
    try
1220
    {
1221
      variable  = (String)field [POS_VARIABLE];
1222
      comboBox  = (JComboBox)field [POS_FIELD];
1223
      value     = ((TextValuePair)comboBox.getSelectedItem ()).getValue ();
1224
    }
1225
    catch (Throwable exception)
1226
    {
1227
      return true;
1228
    }
1229
    if ((variable == null) || (value == null))
1230
    {
1231
      return true;
1232
    }
1233

    
1234
    idata.setVariable(variable, value);
1235
    entries.add (new TextValuePair (variable, value));
1236
    return true;
1237
  }
1238
 /*--------------------------------------------------------------------------*/
1239
 /**
1240
  * Adds a radio button set to the list of UI elements. <br>
1241
  * This is a complete example of a valid XML specification
1242
  * <pre>
1243
  * <field type="radio" variable="testVariable">
1244
  *   <description text="Description for the radio buttons" id="a key for translated text"/>
1245
  *   <spec text="label" id="key for the label"/>
1246
  *     <choice text="radio 1" id="" value=""/>
1247
  *     <choice text="radio 2" id="" value="" set="true"/>
1248
  *     <choice text="radio 3" id="" value=""/>
1249
  *     <choice text="radio 4" id="" value=""/>
1250
  *     <choice text="radio 5" id="" value=""/>
1251
  *   </spec>
1252
  * </field>
1253
  * </pre>
1254
  *
1255
  * @param     spec  a <code>XMLElement</code> containing the specification
1256
  *                  for the radio button set.
1257
  */
1258
 /*--------------------------------------------------------------------------*/
1259
  private void addRadioButton (XMLElement spec)
1260
  {
1261
    Vector forPacks = spec.getChildrenNamed (PACKS);
1262
        Vector forOs = spec.getChildrenNamed(OS);
1263
    String                variable    = spec.getAttribute (VARIABLE);
1264
    String                value       = null;
1265

    
1266
    XMLElement            element     = null;
1267
    JLabel                label;
1268

    
1269
    ButtonGroup           group       = new ButtonGroup ();
1270

    
1271
    TwoColumnConstraints  constraints = new TwoColumnConstraints ();
1272
    constraints.position              = TwoColumnConstraints.BOTH;
1273
    constraints.indent                = true;
1274
    constraints.stretch               = true;
1275

    
1276
    // ----------------------------------------------------
1277
    // get the description and add it to the list of UI
1278
    // elements if it exists.
1279
    // ----------------------------------------------------
1280
    element = spec.getFirstChildNamed (DESCRIPTION);
1281
    addDescription (element, forPacks, forOs);
1282

    
1283
    // ----------------------------------------------------
1284
    // extract the specification details
1285
    // ----------------------------------------------------
1286
    element = spec.getFirstChildNamed (SPEC);
1287

    
1288
    if (element != null)
1289
    {
1290
      // TODO: label is never added to the UI
1291
      label = new JLabel (getText (element));
1292

    
1293
      Vector choices = element.getChildrenNamed (RADIO_CHOICE);
1294

    
1295
      if (choices == null)
1296
      {
1297
        return;
1298
      }
1299

    
1300
      // --------------------------------------------------
1301
      // process each choice element
1302
      // --------------------------------------------------
1303
      for (int i = 0; i < choices.size (); i++)
1304
      {
1305
        JRadioButton choice   = new JRadioButton ();
1306
        choice.setText          (getText ((XMLElement)choices.elementAt (i)));
1307
        value                 = (((XMLElement)choices.elementAt (i)).getAttribute (RADIO_VALUE));
1308

    
1309
        group.add (choice);
1310

    
1311
        String set    = ((XMLElement)choices.elementAt (i)).getAttribute (SET);
1312
        if (set != null)
1313
        {
1314
          if (set.equals (TRUE))
1315
          {
1316
            choice.setSelected (true);
1317
          }
1318
        }
1319

    
1320
        buttonGroups.add (group);
1321
        uiElements.add (new Object [] {null, RADIO_FIELD, variable, constraints, choice, forPacks, forOs, value, null, null, group});
1322
      }
1323
    }
1324
  }
1325
 /*--------------------------------------------------------------------------*/
1326
 /**
1327
  * Reads the content of the radio button field and substitutes the associated
1328
  * variable.
1329
  *
1330
  * @param     field  the object array that holds the details of the field.
1331
  *
1332
  * @return    <code>true</code> if there was no problem reading the data or
1333
  *            if there was an irrecovarable problem. If there was a problem
1334
  *            that can be corrected by the operator, an error dialog is
1335
  *            popped up and <code>false</code> is returned.
1336
  */
1337
 /*--------------------------------------------------------------------------*/
1338
  private boolean readRadioButton (Object [] field)
1339
  {
1340
    String variable     = null;
1341
    String value        = null;
1342
    JRadioButton button = null;
1343

    
1344
    try
1345
    {
1346
      button   = (JRadioButton)field [POS_FIELD];
1347

    
1348
      if (!button.isSelected ())
1349
      {
1350
        return (true);
1351
      }
1352

    
1353
      variable = (String)field [POS_VARIABLE];
1354
      value    = (String)field [POS_TRUE];
1355
    }
1356
    catch (Throwable exception)
1357
    {
1358
      return (true);
1359
    }
1360

    
1361
    idata.setVariable (variable, value);
1362
    entries.add (new TextValuePair (variable, value));
1363
    return (true);
1364
  }
1365
 /*--------------------------------------------------------------------------*/
1366
 /**
1367
  * Adds one or more password fields to the list of UI elements. <br>
1368
  * This is a complete example of a valid XML specification
1369
  * <pre>
1370
  * <field type="password" variable="testVariable">
1371
  *   <description align="left" txt="Please enter your password" id="a key for translated text"/>
1372
  *   <spec>
1373
  *     <pwd txt="Password" id="key for the label" size="10" set=""/>
1374
  *     <pwd txt="Retype password" id="another key for the label" size="10" set=""/>
1375
  *   </spec>
1376
  *   <validator class="com.izforge.sample.PWDValidator" txt="Both versions of the password must match" id="key for the error text"/>
1377
  *   <processor class="com.izforge.sample.PWDEncryptor"/>
1378
  * </field>
1379
  * </pre>
1380
  *
1381
  * @param     spec  a <code>XMLElement</code> containing the specification
1382
  *                  for the set of password fields.
1383
  */
1384
 /*--------------------------------------------------------------------------*/
1385
  private void addPasswordField (XMLElement spec)
1386
  {
1387
    Vector        forPacks  = spec.getChildrenNamed (PACKS);
1388
        Vector forOs = spec.getChildrenNamed(OS);
1389
    String        variable  = spec.getAttribute (VARIABLE);
1390
    String        validator = null;
1391
    String        message   = null;
1392
    String        processor = null;
1393
    XMLElement    element   = null;
1394
    PasswordGroup group     = null;
1395
    int           size      = 0;
1396

    
1397
    // ----------------------------------------------------
1398
    // get the description and add it to the list of UI
1399
    // elements if it exists.
1400
    // ----------------------------------------------------
1401
    element = spec.getFirstChildNamed (DESCRIPTION);
1402
    addDescription (element, forPacks, forOs);
1403

    
1404
    // ----------------------------------------------------
1405
    // get the validator and processor if they are defined
1406
    // ----------------------------------------------------
1407
    element = spec.getFirstChildNamed (VALIDATOR);
1408
    if (element != null)
1409
    {
1410
      validator = element.getAttribute (CLASS);
1411
      message   = getText (element);
1412
    }
1413

    
1414
    element = spec.getFirstChildNamed (PROCESSOR);
1415
    if (element != null)
1416
    {
1417
      processor = element.getAttribute (CLASS);
1418
    }
1419

    
1420
    group = new PasswordGroup (validator,
1421
                               processor);
1422

    
1423
    // ----------------------------------------------------
1424
    // extract the specification details
1425
    // ----------------------------------------------------
1426
    element = spec.getFirstChildNamed (SPEC);
1427

    
1428
    if (element != null)
1429
    {
1430
      Vector inputs = element.getChildrenNamed (PWD_INPUT);
1431

    
1432
      if (inputs == null)
1433
      {
1434
        return;
1435
      }
1436

    
1437
      // --------------------------------------------------
1438
      // process each input field
1439
      // --------------------------------------------------
1440
      XMLElement fieldSpec;
1441
      for (int i = 0; i < inputs.size (); i++)
1442
      {
1443
        fieldSpec     = (XMLElement)inputs.elementAt (i);
1444
        String set    = fieldSpec.getAttribute (SET);
1445
        JLabel label  = new JLabel (getText (fieldSpec));
1446
        try
1447
        {
1448
          size = Integer.parseInt (fieldSpec.getAttribute (PWD_SIZE));
1449
        }
1450
        catch (Throwable exception)
1451
        {
1452
          size = 1;
1453
        }
1454

    
1455
        // ----------------------------------------------------
1456
        // construct the UI element and add it to the list
1457
        // ----------------------------------------------------
1458
        JPasswordField field = new JPasswordField (set, size);
1459
        field.setCaretPosition (0);
1460

    
1461
        TwoColumnConstraints constraints = new TwoColumnConstraints ();
1462
        constraints.position  = TwoColumnConstraints.WEST;
1463

    
1464
        uiElements.add (new Object [] {null, FIELD_LABEL, null, constraints, label, forPacks, forOs});
1465

    
1466
        TwoColumnConstraints constraints2 = new TwoColumnConstraints ();
1467
        constraints2.position  = TwoColumnConstraints.EAST;
1468

    
1469
        uiElements.add (new Object [] {null, PWD_FIELD, variable, constraints2, field, forPacks, forOs, null, null, message, group});
1470
        group.addField (field);
1471
      }
1472
    }
1473

    
1474
    passwordGroups.add (group);
1475
  }
1476
 /*--------------------------------------------------------------------------*/
1477
 /**
1478
  * Reads the content of the password field and substitutes the associated
1479
  * variable.
1480
  *
1481
  * @param     field  a password group that manages one or more passord fields.
1482
  *
1483
  * @return    <code>true</code> if there was no problem reading the data or
1484
  *            if there was an irrecovarable problem. If there was a problem
1485
  *            that can be corrected by the operator, an error dialog is
1486
  *            popped up and <code>false</code> is returned.
1487
  */
1488
 /*--------------------------------------------------------------------------*/
1489
  private boolean readPasswordField (Object [] field)
1490
  {
1491
    PasswordGroup   group     = null;
1492
    String          variable  = null;
1493
    String          message   = null;
1494

    
1495
    try
1496
    {
1497
      group         = (PasswordGroup)field [POS_GROUP];
1498
      variable      = (String)field [POS_VARIABLE];
1499
      message       = (String)field [POS_MESSAGE];
1500
    }
1501
    catch (Throwable exception)
1502
    {
1503
      return (true);
1504
    }
1505
    if ((variable == null) || (passwordGroupsRead.contains (group)))
1506
    {
1507
      return (true);
1508
    }
1509
    passwordGroups.add (group);
1510

    
1511

    
1512
    boolean success = group.validateContents ();
1513

    
1514
    if (!success)
1515
    {
1516
      JOptionPane.showMessageDialog (parentFrame,
1517
                                     message,
1518
                                     parentFrame.langpack.getString ("UserInputPanel.error.caption"),
1519
                                     JOptionPane.WARNING_MESSAGE);
1520
      return (false);
1521
    }
1522

    
1523
    idata.setVariable(variable, group.getPassword ());
1524
    entries.add (new TextValuePair (variable, group.getPassword ()));
1525
    return (true);
1526
  }
1527
 /*--------------------------------------------------------------------------*/
1528
 /**
1529
  * Adds a chackbox to the list of UI elements.
1530
  *
1531
  * @param     spec  a <code>XMLElement</code> containing the specification
1532
  *                  for the checkbox.
1533
  */
1534
 /*--------------------------------------------------------------------------*/
1535
  private void addCheckBox (XMLElement spec)
1536
  {
1537
    Vector      forPacks    = spec.getChildrenNamed (PACKS);
1538
        Vector forOs = spec.getChildrenNamed(OS);
1539
    String      label       = "";
1540
    String      set         = null;
1541
    String      trueValue   = null;
1542
    String      falseValue  = null;
1543
    String      variable    = spec.getAttribute (VARIABLE);
1544
    XMLElement  detail      = spec.getFirstChildNamed (SPEC);
1545

    
1546
    if (variable == null)
1547
    {
1548
      return;
1549
    }
1550

    
1551
    if (detail != null)
1552
    {
1553
      label       = getText (detail);
1554
      set         = detail.getAttribute (SET);
1555
      trueValue   = detail.getAttribute (TRUE);
1556
      falseValue  = detail.getAttribute (FALSE);
1557
    }
1558

    
1559
    JCheckBox   checkbox  = new JCheckBox (label);
1560

    
1561
    if (set != null)
1562
    {
1563
      if (set.equals (FALSE))
1564
      {
1565
        checkbox.setSelected (false);
1566
      }
1567
      if (set.equals (TRUE))
1568
      {
1569
        checkbox.setSelected (true);
1570
      }
1571
    }
1572

    
1573
    // ----------------------------------------------------
1574
    // get the description and add it to the list of UI
1575
    // elements if it exists.
1576
    // ----------------------------------------------------
1577
    XMLElement element = spec.getFirstChildNamed (DESCRIPTION);
1578
    addDescription (element, forPacks, forOs);
1579

    
1580
    TwoColumnConstraints constraints = new TwoColumnConstraints ();
1581
    constraints.position  = TwoColumnConstraints.BOTH;
1582
    constraints.stretch   = true;
1583
    constraints.indent    = true;
1584

    
1585
    uiElements.add (new Object [] {null, CHECK_FIELD, variable, constraints, checkbox, forPacks, forOs, trueValue, falseValue});
1586
  }
1587
 /*--------------------------------------------------------------------------*/
1588
 /**
1589
  * Reads the content of the checkbox field and substitutes the associated
1590
  * variable.
1591
  *
1592
  * @param     field  the object array that holds the details of the field.
1593
  *
1594
  * @return    <code>true</code> if there was no problem reading the data or
1595
  *            if there was an irrecovarable problem. If there was a problem
1596
  *            that can be corrected by the operator, an error dialog is
1597
  *            popped up and <code>false</code> is returned.
1598
  */
1599
 /*--------------------------------------------------------------------------*/
1600
  private boolean readCheckBox (Object [] field)
1601
  {
1602
    String    variable    = null;
1603
    String    trueValue   = null;
1604
    String    falseValue  = null;
1605
    JCheckBox box         = null;
1606

    
1607
    try
1608
    {
1609
      box         = (JCheckBox)field [POS_FIELD];
1610
      variable    = (String)field [POS_VARIABLE];
1611
      trueValue   = (String)field [POS_TRUE];
1612
      if (trueValue == null)
1613
      {
1614
        trueValue = "";
1615
      }
1616

    
1617
      falseValue  = (String)field [POS_FALSE];
1618
      if (falseValue == null)
1619
      {
1620
        falseValue = "";
1621
      }
1622
    }
1623
    catch (Throwable exception)
1624
    {
1625
      return (true);
1626
    }
1627

    
1628
    if (box.isSelected ())
1629
    {
1630
      idata.setVariable (variable, trueValue);
1631
      entries.add (new TextValuePair (variable, trueValue));
1632
    }
1633
    else
1634
    {
1635
      idata.setVariable(variable, falseValue);
1636
      entries.add (new TextValuePair (variable, falseValue));
1637
    }
1638

    
1639
    return (true);
1640
  }
1641
 /*--------------------------------------------------------------------------*/
1642
 /**
1643
  * Adds a search field to the list of UI elements. <p>
1644
  * This is a complete example of a valid XML specification
1645
  * <pre>
1646
  * <field type="search" variable="testVariable">
1647
  *   <description text="Description for the search field" id="a key for translated text"/>
1648
  *   <spec text="label" id="key for the label" filename="the_file_to_search" result="directory" /> <!-- values for result: directory, file -->
1649
  *     <choice dir="directory1" set="true" /> <!-- default value -->
1650
  *     <choice dir="dir2" />
1651
  *   </spec>
1652
  * </field>
1653
  * </pre>
1654
  * @param     spec  a <code>XMLElement</code> containing the specification
1655
  *                  for the search field
1656
  */
1657
 /*--------------------------------------------------------------------------*/
1658
  private void addSearch (XMLElement spec)
1659
  {
1660
    Vector        forPacks    = spec.getChildrenNamed (PACKS);
1661
    Vector        forOs       = spec.getChildrenNamed(OS);
1662
    XMLElement    element     = spec.getFirstChildNamed (SPEC);
1663
    String        variable    = spec.getAttribute (VARIABLE);
1664
    String        filename    = null;
1665
    String        check_filename = null;
1666
    int           search_type = 0;
1667
    int           result_type = 0;
1668
    JComboBox     combobox    = new JComboBox ();
1669
    JLabel        label       = null;
1670

    
1671
    //System.out.println ("adding search combobox, variable "+variable);
1672

    
1673
    // allow the user to enter something
1674
    combobox.setEditable (true);
1675

    
1676
    // ----------------------------------------------------
1677
    // extract the specification details
1678
    // ----------------------------------------------------
1679
    if (element != null)
1680
    {
1681
      label = new JLabel (getText (element));
1682

    
1683
      // search type is optional (default: file)
1684
      search_type = SearchField.TYPE_FILE;
1685

    
1686
      String search_type_str = element.getAttribute (SEARCH_TYPE);
1687

    
1688
      if (search_type_str != null)
1689
      {
1690
        if (search_type_str.equals (SEARCH_FILE))
1691
        {
1692
          search_type = SearchField.TYPE_FILE;
1693
        }
1694
        else if (search_type_str.equals (SEARCH_DIRECTORY))
1695
        {
1696
          search_type = SearchField.TYPE_DIRECTORY;
1697
        }
1698
      }
1699

    
1700
      // result type is mandatory too
1701
      String result_type_str = element.getAttribute (SEARCH_RESULT);
1702

    
1703
      if (result_type_str == null)
1704
      {
1705
        return;
1706
      }
1707
      else if (result_type_str.equals (SEARCH_FILE))
1708
      {
1709
        result_type = SearchField.RESULT_FILE;
1710
      }
1711
      else if (result_type_str.equals (SEARCH_DIRECTORY))
1712
      {
1713
        result_type = SearchField.RESULT_DIRECTORY;
1714
      }
1715
      else if (result_type_str.equals (SEARCH_PARENTDIR))
1716
      {
1717
        result_type = SearchField.RESULT_PARENTDIR;
1718
      }
1719
      else
1720
      {
1721
        return;
1722
      }
1723

    
1724
      // might be missing - null is okay
1725
      filename = element.getAttribute (SEARCH_FILENAME);
1726

    
1727
      check_filename = element.getAttribute (SEARCH_CHECKFILENAME);
1728

    
1729
      Vector choices = element.getChildrenNamed (SEARCH_CHOICE);
1730

    
1731
      if (choices == null)
1732
      {
1733
        return;
1734
      }
1735

    
1736
      for (int i = 0; i < choices.size (); i++)
1737
      {
1738
        XMLElement choice_el = (XMLElement)choices.elementAt (i);
1739

    
1740
        if (! OsConstraint.oneMatchesCurrentSystem(choice_el))
1741
          continue;
1742

    
1743
        String value = choice_el.getAttribute (SEARCH_VALUE);
1744

    
1745
        combobox.addItem (value);
1746

    
1747
        String set    = ((XMLElement)choices.elementAt (i)).getAttribute (SET);
1748
        if (set != null)
1749
        {
1750
          if (set.equals (TRUE))
1751
          {
1752
            combobox.setSelectedIndex (i);
1753
          }
1754
        }
1755
      }
1756
    }
1757
    // ----------------------------------------------------
1758
    // if there is no specification element, return without
1759
    // doing anything.
1760
    // ----------------------------------------------------
1761
    else
1762
    {
1763
      return;
1764
    }
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
    TwoColumnConstraints westconstraint1 = new TwoColumnConstraints ();
1774
    westconstraint1.position  = TwoColumnConstraints.WEST;
1775

    
1776
    uiElements.add (new Object [] {null, FIELD_LABEL, null, westconstraint1, label, forPacks, forOs});
1777

    
1778
    TwoColumnConstraints eastconstraint1 = new TwoColumnConstraints ();
1779
    eastconstraint1.position  = TwoColumnConstraints.EAST;
1780

    
1781
    StringBuffer tooltiptext = new StringBuffer ();
1782

    
1783
    if ((filename != null) && (filename.length() > 0))
1784
    {
1785
      tooltiptext.append (
1786
        MessageFormat.format (parentFrame.langpack.getString ("UserInputPanel.search.location"),
1787
            new String[] { filename} ));
1788
    }
1789

    
1790
    boolean showAutodetect = (check_filename != null) && (check_filename.length() > 0);
1791
    if (showAutodetect)
1792
    {
1793
      tooltiptext.append (
1794
        MessageFormat.format (parentFrame.langpack.getString ("UserInputPanel.search.location.checkedfile"),
1795
          new String[] { check_filename } ));
1796
    }
1797

    
1798
    if (tooltiptext.length() > 0)
1799
      combobox.setToolTipText (tooltiptext.toString());
1800

    
1801
    uiElements.add (new Object [] {null, SEARCH_FIELD, variable, eastconstraint1, combobox, forPacks, forOs});
1802

    
1803
    JPanel buttonPanel = new JPanel ();
1804
    buttonPanel.setLayout (new com.izforge.izpack.gui.FlowLayout (com.izforge.izpack.gui.FlowLayout.LEADING));
1805

    
1806
    JButton autodetectButton = ButtonFactory.createButton (parentFrame.langpack.getString ("UserInputPanel.search.autodetect"), idata.buttonsHColor);
1807
    autodetectButton.setVisible(showAutodetect);
1808

    
1809
    autodetectButton.setToolTipText (parentFrame.langpack.getString ("UserInputPanel.search.autodetect.tooltip"));
1810

    
1811
    buttonPanel.add (autodetectButton);
1812

    
1813
    JButton browseButton = ButtonFactory.createButton (parentFrame.langpack.getString ("UserInputPanel.search.browse"), idata.buttonsHColor);
1814

    
1815
    buttonPanel.add (browseButton);
1816

    
1817
    TwoColumnConstraints eastonlyconstraint = new TwoColumnConstraints ();
1818
    eastonlyconstraint.position  = TwoColumnConstraints.EASTONLY;
1819

    
1820
    uiElements.add (new Object [] {null, SEARCH_BUTTON_FIELD, null, eastonlyconstraint, buttonPanel, forPacks, forOs});
1821

    
1822
    searchFields.add (new SearchField (filename, check_filename, parentFrame, combobox, autodetectButton, browseButton, search_type, result_type));
1823
  }
1824
 /*--------------------------------------------------------------------------*/
1825
 /**
1826
  * Reads the content of the search field and substitutes the associated
1827
  * variable.
1828
  *
1829
  * @param     field  the object array that holds the details of the field.
1830
  *
1831
  * @return    <code>true</code> if there was no problem reading the data or
1832
  *            if there was an irrecovarable problem. If there was a problem
1833
  *            that can be corrected by the operator, an error dialog is
1834
  *            popped up and <code>false</code> is returned.
1835
  */
1836
 /*--------------------------------------------------------------------------*/
1837
  private boolean readSearch (Object [] field)
1838
  {
1839
    String variable = null;
1840
    String value    = null;
1841
    JComboBox comboBox = null;
1842

    
1843
    try
1844
    {
1845
      variable  = (String)field [POS_VARIABLE];
1846
      comboBox  = (JComboBox)field [POS_FIELD];
1847
      for (int i = 0; i < this.searchFields.size(); ++i)
1848
      {
1849
        SearchField sf = (SearchField)this.searchFields.elementAt (i);
1850
        if (sf.belongsTo (comboBox))
1851
        {
1852
          value = sf.getResult ();
1853
          break;
1854
        }
1855
      }
1856
    }
1857
    catch (Throwable exception)
1858
    {
1859
      return (true);
1860
    }
1861
    if ((variable == null) || (value == null))
1862
    {
1863
      return (true);
1864
    }
1865

    
1866
    idata.setVariable(variable, value);
1867
    entries.add (new TextValuePair (variable, value));
1868
    return (true);
1869
  }
1870
 /*--------------------------------------------------------------------------*/
1871
 /**
1872
  * Adds text to the list of UI elements
1873
  *
1874
  * @param     spec  a <code>XMLElement</code> containing the specification
1875
  *                  for the text.
1876
  */
1877
 /*--------------------------------------------------------------------------*/
1878
  private void addText (XMLElement spec)
1879
  {
1880
    Vector forPacks = spec.getChildrenNamed (PACKS);
1881
        Vector forOs = spec.getChildrenNamed(OS);
1882

    
1883
    addDescription (spec, forPacks, forOs);
1884
  }
1885
 /*--------------------------------------------------------------------------*/
1886
 /**
1887
  * Adds a dummy field to the list of UI elements to act as spacer.
1888
  *
1889
  * @param     spec  a <code>XMLElement</code> containing other specifications.
1890
  *                  At present this information is not used but might be in
1891
  *                  future versions.
1892
  */
1893
 /*--------------------------------------------------------------------------*/
1894
  private void addSpace (XMLElement spec)
1895
  {
1896
    Vector forPacks = spec.getChildrenNamed (PACKS);
1897
        Vector forOs = spec.getChildrenNamed(OS);
1898
    JPanel panel    = new JPanel ();
1899

    
1900
    TwoColumnConstraints constraints = new TwoColumnConstraints ();
1901
    constraints.position  = TwoColumnConstraints.BOTH;
1902
    constraints.stretch   = true;
1903

    
1904
    uiElements.add (new Object [] {null, SPACE_FIELD, null, constraints, panel, forPacks, forOs});
1905
  }
1906
 /*--------------------------------------------------------------------------*/
1907
 /**
1908
  * Adds a dividing line to the list of UI elements act as separator.
1909
  *
1910
  * @param     spec  a <code>XMLElement</code> containing additional
1911
  *                  specifications.
1912
  */
1913
 /*--------------------------------------------------------------------------*/
1914
  private void addDivider (XMLElement spec)
1915
  {
1916
    Vector forPacks   = spec.getChildrenNamed (PACKS);
1917
        Vector forOs = spec.getChildrenNamed(OS);
1918
    JPanel panel      = new JPanel ();
1919
    String alignment  = spec.getAttribute (ALIGNMENT);
1920

    
1921
    if (alignment != null)
1922
    {
1923
      if (alignment.equals (TOP))
1924
      {
1925
        panel.setBorder (BorderFactory.createMatteBorder (1, 0, 0, 0, Color.gray));
1926
      }
1927
      else
1928
      {
1929
        panel.setBorder (BorderFactory.createMatteBorder (0, 0, 1, 0, Color.gray));
1930
      }
1931
    }
1932
    else
1933
    {
1934
      panel.setBorder (BorderFactory.createMatteBorder (0, 0, 1, 0, Color.gray));
1935
    }
1936

    
1937
    TwoColumnConstraints constraints = new TwoColumnConstraints ();
1938
    constraints.position  = TwoColumnConstraints.BOTH;
1939
    constraints.stretch   = true;
1940

    
1941
    uiElements.add (new Object [] {null, DIVIDER_FIELD, null, constraints, panel, forPacks, forOs});
1942
  }
1943
 /*--------------------------------------------------------------------------*/
1944
 /**
1945
  * Adds a description to the list of UI elements.
1946
  *
1947
  * @param     spec  a <code>XMLElement</code> containing the specification
1948
  *                  for the description.
1949
  */
1950
 /*--------------------------------------------------------------------------*/
1951
  private void addDescription (XMLElement spec,
1952
                               Vector     forPacks, Vector forOs)
1953
  {
1954
    String               description;
1955
    TwoColumnConstraints constraints = new TwoColumnConstraints ();
1956
    constraints.position  = TwoColumnConstraints.BOTH;
1957
    constraints.stretch   = true;
1958

    
1959
    if (spec != null)
1960
    {
1961
      description = getText (spec);
1962

    
1963
      // if we have a description, add it to the UI elements
1964
      if (description != null)
1965
      {
1966
        String  alignment = spec.getAttribute (ALIGNMENT);
1967
        int     justify   = MultiLineLabel.LEFT;
1968

    
1969
        if (alignment != null)
1970
        {
1971
          if (alignment.equals (LEFT))
1972
          {
1973
            justify     = MultiLineLabel.LEFT;
1974
          }
1975
          else if (alignment.equals (CENTER))
1976
          {
1977
            justify     = MultiLineLabel.CENTER;
1978
          }
1979
          else if (alignment.equals (RIGHT))
1980
          {
1981
            justify     = MultiLineLabel.RIGHT;
1982
          }
1983
        }
1984

    
1985
        MultiLineLabel label = new MultiLineLabel (description, justify);
1986

    
1987
        uiElements.add (new Object [] {null, DESCRIPTION, null, constraints, label, forPacks, forOs});
1988
      }
1989
    }
1990
  }
1991
 /*--------------------------------------------------------------------------*/
1992
 /**
1993
  * Retrieves the value of a boolean attribute. If the attribute is found and
1994
  * the values equals the value of the constant <code>TRUE</code> then true
1995
  * is returned. If it equals <code>FALSE</code> the false is returned. In
1996
  * all other cases, including when the attribute is not found, the default
1997
  * value is returned.
1998
  *
1999
  * @param     element        the <code>XMLElement</code> to search for the
2000
  *                           attribute.
2001
  * @param     attribute      the attribute to search for
2002
  * @param     defaultValue   the default value to use if the attribute does
2003
  *                           not exist or a illegal value was discovered.
2004
  *
2005
  * @return    <code>true</code> if the attribute is found and the value
2006
  *            equals the the constant <code>TRUE</code>. <<code> if the
2007
  *            attribute is <code>FALSE</code>. In all other cases the
2008
  *            default value is returned.
2009
  */
2010
 /*--------------------------------------------------------------------------*/
2011
  private boolean getBoolean (XMLElement element,
2012
                              String     attribute,
2013
                              boolean    defaultValue)
2014
  {
2015
    boolean result = defaultValue;
2016

    
2017
    if ((attribute != null) && (attribute.length () > 0))
2018
    {
2019
      String value = element.getAttribute (attribute);
2020

    
2021
      if (value != null)
2022
      {
2023
        if (value.equals (TRUE))
2024
        {
2025
          result = true;
2026
        }
2027
        else if (value.equals (FALSE))
2028
        {
2029
          result = false;
2030
        }
2031
      }
2032
    }
2033

    
2034
    return (result);
2035
  }
2036
 /*--------------------------------------------------------------------------*/
2037
 /**
2038
  * Retrieves the value of an integer attribute. If the attribute is not
2039
  * found or the value is non-numeric then the default value is returned.
2040
  *
2041
  * @param     element      the <code>XMLElement</code> to search for the
2042
  *                         attribute.
2043
  * @param     attribute    the attribute to search for
2044
  * @param     defaultValue the default value to use in case the attribute
2045
  *                         does not exist.
2046
  *
2047
  * @return    the value of the attribute. If the attribute is not found or
2048
  *            the content is not a legal integer, then the default value is
2049
  *            returned.
2050
  */
2051
 /*--------------------------------------------------------------------------*/
2052
  private int getInt (XMLElement  element,
2053
                      String      attribute,
2054
                      int         defaultValue)
2055
  {
2056
    int result = defaultValue;
2057

    
2058
    if ((attribute != null) && (attribute.length () > 0))
2059
    {
2060
      try
2061
      {
2062
        result = Integer.parseInt (element.getAttribute (attribute));
2063
      }
2064
      catch (Throwable exception)
2065
      {}
2066
    }
2067

    
2068
    return (result);
2069
  }
2070
 /*--------------------------------------------------------------------------*/
2071
 /**
2072
  * Retrieves the value of a floating point attribute. If the attribute is not
2073
  * found or the value is non-numeric then the default value is returned.
2074
  *
2075
  * @param     element      the <code>XMLElement</code> to search for the
2076
  *                         attribute.
2077
  * @param     attribute    the attribute to search for
2078
  * @param     defaultValue the default value to use in case the attribute
2079
  *                         does not exist.
2080
  *
2081
  * @return    the value of the attribute. If the attribute is not found or
2082
  *            the content is not a legal integer, then the default value is
2083
  *            returned.
2084
  */
2085
 /*--------------------------------------------------------------------------*/
2086
  private float getFloat (XMLElement  element,
2087
                          String      attribute,
2088
                          float       defaultValue)
2089
  {
2090
    float result = defaultValue;
2091

    
2092
    if ((attribute != null) && (attribute.length () > 0))
2093
    {
2094
      try
2095
      {
2096
        result = Float.parseFloat (element.getAttribute (attribute));
2097
      }
2098
      catch (Throwable exception)
2099
      {}
2100
    }
2101

    
2102
    return (result);
2103
  }
2104
 /*--------------------------------------------------------------------------*/
2105
 /**
2106
  * Extracts the text from an <code>XMLElement</code>. The text must be
2107
  * defined in the resource file under the key defined in the <code>id</code>
2108
  * attribute or as value of the attribute <code>text</code>.
2109
  *
2110
  * @param     element  the <code>XMLElement</code> from which to extract
2111
  *                     the text.
2112
  *
2113
  * @return    The text defined in the <code>XMLElement</code>. If no text
2114
  *            can be located, <code>null</code> is returned.
2115
  */
2116
 /*--------------------------------------------------------------------------*/
2117
  private String getText (XMLElement element)
2118
  {
2119
    if (element == null)
2120
    {
2121
      return (null);
2122
    }
2123

    
2124
    String key  = element.getAttribute (KEY);
2125
    String text = null;
2126

    
2127
    if ((key != null) && (langpack != null))
2128
    {
2129
      try
2130
      {
2131
        text = langpack.getString (key);
2132
      }
2133
      catch (Throwable exception)
2134
      {
2135
        text = null;
2136
      }
2137
    }
2138

    
2139
    // if there is no text in the description, then
2140
    // we were unable to retrieve it form the resource.
2141
    // In this case try to get the text directly from
2142
    // the XMLElement
2143
    if (text == null)
2144
    {
2145
      text = element.getAttribute (TEXT);
2146
    }
2147

    
2148
    return (text);
2149
  }
2150
 /*--------------------------------------------------------------------------*/
2151
 /**
2152
  * Retreives the alignment setting for the <code>XMLElement</code>. The
2153
  * default value in case the <code>ALIGNMENT</code> attribute is not
2154
  * found or the value is illegal is <code>TwoColumnConstraints.LEFT</code>.
2155
  *
2156
  * @param     element  the <code>XMLElement</code> from which to extract
2157
  *                     the alignment setting.
2158
  *
2159
  * @return    the alignement setting for the <code>XMLElement</code>. The
2160
  *            value is either <code>TwoColumnConstraints.LEFT</code>,
2161
  *            <code>TwoColumnConstraints.CENTER</code> or
2162
  *            <code>TwoColumnConstraints.RIGHT</code>.
2163
  *
2164
  * @see       com.izforge.izpack.gui.TwoColumnConstraints
2165
  */
2166
 /*--------------------------------------------------------------------------*/
2167
  private int getAlignment (XMLElement element)
2168
  {
2169
    int result = TwoColumnConstraints.LEFT;
2170

    
2171
    String value = element.getAttribute (ALIGNMENT);
2172

    
2173
    if (value != null)
2174
    {
2175
      if (value.equals (LEFT))
2176
      {
2177
        result = TwoColumnConstraints.LEFT;
2178
      }
2179
      else if (value.equals (CENTER))
2180
      {
2181
        result = TwoColumnConstraints.CENTER;
2182
      }
2183
      else if (value.equals (RIGHT))
2184
      {
2185
        result = TwoColumnConstraints.RIGHT;
2186
      }
2187
    }
2188

    
2189
    return (result);
2190
  }
2191

    
2192
  /**
2193
   * Verifies if an item is required for the operating system the installer executed.
2194
   * The configuration for this feature is:
2195
   * <br/>
2196
   * &lt;os family="unix"/&gt;
2197
  * <br><br>
2198
  * <b>Note:</b><br>
2199
  * If the list of the os is empty then <code>true</code> is always
2200
  * returnd.
2201
  *
2202
  * @param os The <code>Vector</code> of <code>String</code>s. containing
2203
  * the os names
2204
  *
2205
  * @return    <code>true</code> if the item is required for the os, otherwise
2206
  * returns <code>false</code>.
2207
   */
2208
  public boolean itemRequiredForOs(Vector os)
2209
  {
2210
        if (os.size () == 0)
2211
        {
2212
          return true;
2213
        }
2214

    
2215
        for (int i = 0; i < os.size (); i++)
2216
        {
2217
                String family = ((XMLElement)os.elementAt (i)).getAttribute(FAMILY);
2218
                boolean match = false;
2219

    
2220
                if (family.equals("windows"))
2221
                {
2222
                        match = OsVersion.IS_WINDOWS;
2223
                }
2224
                else if (family.equals("mac"))
2225
                {
2226
                        match = OsVersion.IS_OSX;
2227
                }
2228
                else if (family.equals("unix"))
2229
                {
2230
      match = OsVersion.IS_UNIX;
2231
                }
2232
                return match;
2233
        }
2234
        return false;
2235
  }
2236

    
2237

    
2238
 /*--------------------------------------------------------------------------*/
2239
 /**
2240
  * Verifies if an item is required for any of the packs listed. An item is
2241
  * required for a pack in the list if that pack is actually selected for
2242
  * installation.
2243
  * <br><br>
2244
  * <b>Note:</b><br>
2245
  * If the list of selected packs is empty then <code>true</code> is always
2246
  * returnd. The same is true if the <code>packs</code> list is empty.
2247
  *
2248
  * @param     packs  a <code>Vector</code> of <code>String</code>s. Each of
2249
  *                   the strings denotes a pack for which an item
2250
  *                   should be created if the pack is actually installed.
2251
  *
2252
  * @return    <code>true</code> if the item is required for at least
2253
  *            one pack in the list, otherwise returns <code>false</code>.
2254
  */
2255
 /*--------------------------------------------------------------------------*/
2256
 /*$
2257
  * @design
2258
  *
2259
  * The information about the installed packs comes from
2260
  * InstallData.selectedPacks. This assumes that this panel is presented to
2261
  * the user AFTER the PacksPanel.
2262
  *--------------------------------------------------------------------------*/
2263
  private boolean itemRequiredFor (Vector packs)
2264
  {
2265

    
2266
    String selected;
2267
    String required;
2268

    
2269
    if (packs.size () == 0)
2270
    {
2271
      return (true);
2272
    }
2273

    
2274
    // ----------------------------------------------------
2275
    // We are getting to this point if any packs have been
2276
    // specified. This means that there is a possibility
2277
    // that some UI elements will not get added. This
2278
    // means that we can not allow to go back to the
2279
    // PacksPanel, because the process of building the
2280
    // UI is not reversable.
2281
    // ----------------------------------------------------
2282
        //packsDefined = true;
2283

    
2284
    // ----------------------------------------------------
2285
    // analyze if the any of the packs for which the item
2286
    // is required have been selected for installation.
2287
    // ----------------------------------------------------
2288
    for (int i = 0; i < idata.selectedPacks.size (); i++)
2289
    {
2290
      selected = ((Pack)idata.selectedPacks.get (i)).name;
2291

    
2292
      for (int k = 0; k < packs.size (); k++)
2293
      {
2294
        required = (String)((XMLElement)packs.elementAt (k)).getAttribute (NAME, "");
2295
        if (selected.equals (required))
2296
        {
2297
          return (true);
2298
        }
2299
      }
2300
    }
2301

    
2302
    return (false);
2303
  }
2304

    
2305
// --------------------------------------------------------------------------
2306
// Inner Classes
2307
// --------------------------------------------------------------------------
2308

    
2309
/*---------------------------------------------------------------------------*/
2310
/**
2311
 * This class can be used to associate a text string and a (text) value.
2312
 */
2313
/*---------------------------------------------------------------------------*/
2314
private static class TextValuePair
2315
{
2316
  private String text   = "";
2317
  private String value  = "";
2318

    
2319
 /*--------------------------------------------------------------------------*/
2320
 /**
2321
  * Constructs a new Text/Value pair, initialized with the text and a value.
2322
  *
2323
  * @param     text   the text that this object should represent
2324
  * @param     value  the value that should be associated with this object
2325
  */
2326
 /*--------------------------------------------------------------------------*/
2327
  public TextValuePair  (String text,
2328
                         String value)
2329
  {
2330
    this.text   = text;
2331
    this.value  = value;
2332
  }
2333
 /*--------------------------------------------------------------------------*/
2334
 /**
2335
  * Sets the text
2336
  *
2337
  * @param     text   the text for this object
2338
  */
2339
 /*--------------------------------------------------------------------------*/
2340
  public void setText (String text)
2341
  {
2342
    this.text = text;
2343
  }
2344
 /*--------------------------------------------------------------------------*/
2345
 /**
2346
  * Sets the value of this object
2347
  *
2348
  * @param     value    the value for this object
2349
  */
2350
 /*--------------------------------------------------------------------------*/
2351
  public void setValue (String value)
2352
  {
2353
    this.value = value;
2354
  }
2355
 /*--------------------------------------------------------------------------*/
2356
 /**
2357
  * This method returns the text that was set for the object
2358
  *
2359
  * @return    the object's text
2360
  */
2361
 /*--------------------------------------------------------------------------*/
2362
  public String toString ()
2363
  {
2364
    return (text);
2365
  }
2366
 /*--------------------------------------------------------------------------*/
2367
 /**
2368
  * This method returns the value that was associated with this object
2369
  *
2370
  * @return    the object's value
2371
  */
2372
 /*--------------------------------------------------------------------------*/
2373
  public String getValue ()
2374
  {
2375
    return (value);
2376
  }
2377
}
2378

    
2379

    
2380
/*---------------------------------------------------------------------------*/
2381
/**
2382
 * This class encapsulates a lot of search field functionality.
2383
 *
2384
 * A search field supports searching directories and files on the target
2385
 * system. This is a helper class to manage all data belonging to a
2386
 * search field.
2387
 */
2388
/*---------------------------------------------------------------------------*/
2389

    
2390
private class SearchField implements ActionListener
2391
{
2392
  /** used in constructor - we search for a directory. */
2393
  public static final int       TYPE_DIRECTORY = 1;
2394
  /** used in constructor - we search for a file. */
2395
  public static final int       TYPE_FILE = 2;
2396

    
2397
  /** used in constructor - result of search is the directory. */
2398
  public static final int       RESULT_DIRECTORY = 1;
2399
  /** used in constructor - result of search is the whole file name. */
2400
  public static final int       RESULT_FILE = 2;
2401
  /** used in constructor - result of search is the parent directory. */
2402
  public static final int       RESULT_PARENTDIR = 3;
2403

    
2404
  private String    filename = null;
2405
  private String    checkFilename = null;
2406
  private JButton   autodetectButton = null;
2407
  private JButton   browseButton = null;
2408
  private JComboBox pathComboBox = null;
2409
  private int       searchType = TYPE_DIRECTORY;
2410
  private int       resultType = RESULT_DIRECTORY;
2411

    
2412
  private InstallerFrame  parent = null;
2413

    
2414
  /*---------------------------------------------------------------------------*/
2415
  /**
2416
   * Constructor - initializes the object, adds it as action listener to
2417
   * the "autodetect" button.
2418
   *
2419
   * @param filename    the name of the file to search for (might be null for
2420
   *                    searching directories)
2421
   * @param checkFilename the name of the file to check when searching for directories
2422
   *                    (the checkFilename is appended to a found directory to figure out
2423
   *                     whether it is the right directory)
2424
   * @param combobox    the <code>JComboBox</code> holding the list of choices;
2425
   *                    it should be editable and contain only Strings
2426
   * @param autobutton  the autodetection button for triggering autodetection
2427
   * @param browsebutton the browse button to look for the file
2428
   * @param search_type what to search for - TYPE_FILE or TYPE_DIRECTORY
2429
   * @param result_type what to return as the result - RESULT_FILE or
2430
   *                    RESULT_DIRECTORY or RESULT_PARENTDIR
2431
   */
2432
  /*---------------------------------------------------------------------------*/
2433
  public SearchField (String filename, String checkFilename,
2434
                      InstallerFrame parent, JComboBox combobox,
2435
                      JButton autobutton, JButton browsebutton,
2436
                      int search_type, int result_type)
2437
  {
2438
    this.filename = filename;
2439
    this.checkFilename = checkFilename;
2440
    this.parent = parent;
2441
    this.autodetectButton = autobutton;
2442
    this.browseButton = browsebutton;
2443
    this.pathComboBox = combobox;
2444
    this.searchType = search_type;
2445
    this.resultType = result_type;
2446

    
2447
    this.autodetectButton.addActionListener (this);
2448
    this.browseButton.addActionListener (this);
2449

    
2450
    autodetect ();
2451
  }
2452

    
2453
  /** Check whether the given combobox belongs to this searchfield.
2454
   * This is used when reading the results.
2455
   */
2456
  public boolean belongsTo (JComboBox combobox)
2457
  {
2458
    return (this.pathComboBox == combobox);
2459
  }
2460

    
2461
  /** check whether the given path matches */
2462
  private boolean pathMatches (String path)
2463
  {
2464
    if (path != null) { // Make sure, path is not null
2465
    //System.out.println ("checking path " + path);
2466

    
2467
    File file = null;
2468

    
2469
    if ((this.filename == null) || (this.searchType == TYPE_DIRECTORY))
2470
    {
2471
      file = new File (path);
2472
    }
2473
    else
2474
    {
2475
      file = new File (path, this.filename);
2476
    }
2477

    
2478
    if (file.exists ())
2479
    {
2480

    
2481
      if (((this.searchType == TYPE_DIRECTORY) && (file.isDirectory()))
2482
          || ((this.searchType == TYPE_FILE) && (file.isFile ())))
2483
      {
2484
        // no file to check for
2485
        if (this.checkFilename == null)
2486
          return true;
2487

    
2488
        file = new File (file, this.checkFilename);
2489

    
2490
        return file.exists();
2491
      }
2492

    
2493
    }
2494

    
2495
    //System.out.println (path + " did not match");
2496
    } //end if
2497
    return false;
2498
  }
2499

    
2500
  /** perform autodetection */
2501
  public boolean autodetect ()
2502
  {
2503
      Vector items = new Vector();
2504

    
2505
      /*
2506
       * Check if the user has entered data into the ComboBox and add it to the
2507
       * Itemlist
2508
       */
2509
      String selected = (String) this.pathComboBox.getSelectedItem();
2510
      boolean found = false;
2511
      for (int x = 0; x < this.pathComboBox.getItemCount(); x++)
2512
      {
2513
         if (((String) this.pathComboBox.getItemAt(x)).equals(selected))
2514
         {
2515
            found = true;
2516
         }
2517
      }
2518
      if (!found)
2519
      {
2520
         //System.out.println("Not found in Itemlist");
2521
         this.pathComboBox.addItem(this.pathComboBox.getSelectedItem());
2522
      }
2523
      
2524
      //Checks whether a placeholder item is in the combobox
2525
      //and resolve the pathes automatically:
2526
      ///usr/lib/* searches all folders in usr/lib to find
2527
      // /usr/lib/*/lib/tools.jar
2528
      for (int i = 0; i < this.pathComboBox.getItemCount(); ++i)
2529
      {
2530
        String path = (String) this.pathComboBox.getItemAt(i);
2531

    
2532
        if (path.endsWith("*"))
2533
        {
2534
          path = path.substring(0, path.length() - 1);
2535
          File dir = new File(path);
2536

    
2537
          if (dir.isDirectory())
2538
          {
2539
            File[] subdirs = dir.listFiles();
2540
            for (int x = 0; x < subdirs.length; x++)
2541
            {
2542
              String search = subdirs[x].getAbsolutePath();
2543
              if (this.pathMatches(search))
2544
              {
2545
                items.add(search);
2546
              }
2547
            }
2548
          }
2549
        }
2550
        else
2551
        {
2552
           if (this.pathMatches(path))
2553
               {
2554
                  items.add(path);
2555
               }
2556
        }
2557
      }
2558
      // Make the enties in the vector unique
2559
      items=new Vector(new HashSet(items));
2560

    
2561
      //Now clear the combobox and add the items out of the newly
2562
      //generated vector
2563
      this.pathComboBox.removeAllItems();
2564
      VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());
2565
      for (int i = 0; i < items.size(); i++)
2566
      {
2567
        this.pathComboBox.addItem(vs.substitute((String) items.get(i), "plain"));
2568
      }
2569

    
2570
      // loop through all items
2571
      for (int i = 0; i < this.pathComboBox.getItemCount(); ++i)
2572
      {
2573
        String path = (String) this.pathComboBox.getItemAt(i);
2574

    
2575
        if (this.pathMatches(path))
2576
        {
2577
          this.pathComboBox.setSelectedIndex(i);
2578
          return true;
2579
        }
2580

    
2581
      }
2582

    
2583
      // if the user entered something else, it's not listed as an item
2584
      if (this.pathMatches((String) this.pathComboBox.getSelectedItem())) { return true; }
2585

    
2586
      return false;
2587
    }
2588

    
2589
 /*--------------------------------------------------------------------------*/
2590
 /**
2591
  * This is called if one of the buttons has bee pressed.
2592
  *
2593
  * It checks, which button caused the action and acts accordingly.
2594
  */
2595
 /*--------------------------------------------------------------------------*/
2596
  public void actionPerformed (ActionEvent event)
2597
  {
2598
    //System.out.println ("autodetection button pressed.");
2599

    
2600
    if (event.getSource () == this.autodetectButton)
2601
    {
2602
      if (! autodetect ())
2603
        JOptionPane.showMessageDialog (parent,
2604
                                       parent.langpack.getString ("UserInputPanel.search.autodetect.failed.message"),
2605
                                       parent.langpack.getString ("UserInputPanel.search.autodetect.failed.caption"),
2606
                                       JOptionPane.WARNING_MESSAGE);
2607
    }
2608
    else if (event.getSource () == this.browseButton)
2609
    {
2610
      JFileChooser chooser = new JFileChooser ();
2611

    
2612
      if (this.searchType == RESULT_DIRECTORY)
2613
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
2614

    
2615
      int result = chooser.showOpenDialog (this.parent);
2616

    
2617
      if (result == JFileChooser.APPROVE_OPTION)
2618
      {
2619
        File f = chooser.getSelectedFile();
2620

    
2621
        this.pathComboBox.setSelectedItem (f.getAbsolutePath());
2622

    
2623
        // use any given directory directly
2624
        if (! this.pathMatches(f.getAbsolutePath()))
2625
        {
2626
          JOptionPane.showMessageDialog (parent,
2627
                                         parent.langpack.getString ("UserInputPanel.search.wrongselection.message"),
2628
                                         parent.langpack.getString ("UserInputPanel.search.wrongselection.caption"),
2629
                                         JOptionPane.WARNING_MESSAGE);
2630
        }
2631
      }
2632

    
2633
    }
2634

    
2635
    // we don't care for anything more here - getResult() does the rest
2636
  }
2637

    
2638
 /*--------------------------------------------------------------------------*/
2639
 /**
2640
  * Return the result of the search according to result type.
2641
  *
2642
  * Sometimes, the whole path of the file is wanted, sometimes only the
2643
  * directory where the file is in, sometimes the parent directory.
2644
  *
2645
  * @return null on error
2646
  */
2647
 /*--------------------------------------------------------------------------*/
2648
  public String getResult ()
2649
  {
2650
    String item = (String)this.pathComboBox.getSelectedItem ();
2651
    if (item != null) item = item.trim();
2652
    String path = item;
2653

    
2654
    File f = new File (item);
2655

    
2656
    if (! f.isDirectory ())
2657
    {
2658
      path = f.getParent ();
2659
    }
2660

    
2661

    
2662
    // path now contains the final content of the combo box
2663
    if (this.resultType == RESULT_DIRECTORY)
2664
    {
2665
      return path;
2666
    }
2667
    else if (this.resultType == RESULT_FILE)
2668
    {
2669
      if (this.filename != null)
2670
      {
2671
        return path + File.separatorChar + this.filename;
2672
      }
2673
      else
2674
      {
2675
        return item;
2676
      }
2677
    }
2678
    else if (this.resultType == RESULT_PARENTDIR)
2679
    {
2680
      File dir = new File (path);
2681
      return dir.getParent ();
2682
    }
2683

    
2684
    return null;
2685
  }
2686

    
2687
} // private class SearchFile
2688

    
2689
} // public class UserInputPanel
2690
/*---------------------------------------------------------------------------*/