001/* 002 * IzPack - Copyright 2001-2005 Julien Ponge, All Rights Reserved. 003 * 004 * http://www.izforge.com/izpack/ 005 * http://developer.berlios.de/projects/izpack/ 006 * 007 * Copyright 2002 Elmar Grom 008 * 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 */ 021 022package com.izforge.izpack.panels; 023 024import java.awt.Color; 025import java.awt.Font; 026import java.awt.event.ActionEvent; 027import java.awt.event.ActionListener; 028import java.io.File; 029import java.io.InputStream; 030import java.text.MessageFormat; 031import java.util.HashMap; 032import java.util.HashSet; 033import java.util.Iterator; 034import java.util.Map; 035import java.util.StringTokenizer; 036import java.util.Vector; 037 038import javax.swing.BorderFactory; 039import javax.swing.ButtonGroup; 040import javax.swing.JButton; 041import javax.swing.JCheckBox; 042import javax.swing.JComboBox; 043import javax.swing.JComponent; 044import javax.swing.JFileChooser; 045import javax.swing.JLabel; 046import javax.swing.JOptionPane; 047import javax.swing.JPanel; 048import javax.swing.JPasswordField; 049import javax.swing.JRadioButton; 050import javax.swing.JTextField; 051 052import net.n3.nanoxml.NonValidator; 053import net.n3.nanoxml.StdXMLBuilder; 054import net.n3.nanoxml.StdXMLParser; 055import net.n3.nanoxml.StdXMLReader; 056import net.n3.nanoxml.XMLElement; 057 058import com.izforge.izpack.LocaleDatabase; 059import com.izforge.izpack.Pack; 060import com.izforge.izpack.gui.ButtonFactory; 061import com.izforge.izpack.gui.TwoColumnConstraints; 062import com.izforge.izpack.gui.TwoColumnLayout; 063import com.izforge.izpack.installer.InstallData; 064import com.izforge.izpack.installer.InstallerFrame; 065import com.izforge.izpack.installer.IzPanel; 066import com.izforge.izpack.installer.ResourceManager; 067import com.izforge.izpack.util.MultiLineLabel; 068import com.izforge.izpack.util.OsConstraint; 069import com.izforge.izpack.util.OsVersion; 070import com.izforge.izpack.util.VariableSubstitutor; 071 072/*---------------------------------------------------------------------------*/ 073/** 074 * This panel is designed to collect user input during the installation process. The panel is 075 * initially blank and is populated with input elements based on the XML specification in a resource 076 * file. 077 * 078 * 079 * @version 0.0.1 / 10/19/02 080 * @author getDirectoryCreated 081 */ 082/*---------------------------------------------------------------------------*/ 083/* 084 * $ @design 085 * 086 * Each field is specified in its own node, containing attributes and data. When this class is 087 * instantiated, the specification is read and analyzed. Each field node is processed based on its 088 * type. An specialized member function is called for each field type that creates the necessary UI 089 * elements. All UI elements are stored in the uiElements vector. Elements are packaged in an object 090 * array that must follow this pattern: 091 * 092 * index 0 - a String object, that specifies the field type. This is identical to the string used to 093 * identify the field type in the XML file. index 1 - a String object that contains the variable 094 * name for substitution. index 2 - the constraints object that should be used for positioning the 095 * UI element index 3 - the UI element itself index 4 - a Vector containg a list of pack for which 096 * the item should be created. This is used by buildUI() to decide if the item should be added to 097 * the UI. 098 * 099 * In some cases additional entries are used. The use depends on the specific needs of the type of 100 * input field. 101 * 102 * When the panel is activated, the method buildUI() walks the list of UI elements adds them to the 103 * panel together with the matching constraint. 104 * 105 * When an attempt is made to move on to another panel, the method readInput() walks the list of UI 106 * elements again and calls specialized methods that know how to read the user input from each of 107 * the UI elemnts and set the associated varaible. 108 * 109 * The actual variable substitution is not performed by this panel but by the variable substitutor. 110 * 111 * To Do: ------ * make sure all header documentation is complete and correct 112 * -------------------------------------------------------------------------- 113 */ 114public class UserInputPanel extends IzPanel 115{ 116 117 // ------------------------------------------------------------------------ 118 // Constant Definitions 119 // ------------------------------------------------------------------------ 120 121 // The constants beginning with 'POS_' define locations in the object arrays 122 // that used to hold all information for the individual fields. Some data is 123 // not required for all field types. If this happens withing the array, that 124 // location must be padded with 'null'. At the end of the array it can be 125 // omitted. The data stored in this way is in most cases only known by 126 // convention between the add and the associated read method. the following 127 // positions are also used by other service methods in this class and must 128 // not be used for other purposes: 129 // - POS_DISPLAYED 130 // - POS_TYPE 131 // - POS_CONSTRAINTS 132 // - POS_PACKS 133 134 /** 135 * 136 */ 137 private static final long serialVersionUID = 3257850965439886129L; 138 139 private static final int POS_DISPLAYED = 0; 140 141 private static final int POS_TYPE = 1; 142 143 private static final int POS_VARIABLE = 2; 144 145 private static final int POS_CONSTRAINTS = 3; 146 147 private static final int POS_FIELD = 4; 148 149 private static final int POS_PACKS = 5; 150 151 private static final int POS_OS = 6; 152 153 private static final int POS_TRUE = 7; 154 155 private static final int POS_FALSE = 8; 156 157 private static final int POS_MESSAGE = 9; 158 159 private static final int POS_GROUP = 10; 160 161 /** The name of the XML file that specifies the panel layout */ 162 private static final String SPEC_FILE_NAME = "userInputSpec.xml"; 163 164 private static final String LANG_FILE_NAME = "userInputLang.xml"; 165 166 /** how the spec node for a specific panel is identified */ 167 private static final String NODE_ID = "panel"; 168 169 private static final String FIELD_NODE_ID = "field"; 170 171 private static final String INSTANCE_IDENTIFIER = "order"; 172 173 private static final String TYPE = "type"; 174 175 private static final String DESCRIPTION = "description"; 176 177 private static final String VARIABLE = "variable"; 178 179 private static final String TEXT = "txt"; 180 181 private static final String KEY = "id"; 182 183 private static final String SPEC = "spec"; 184 185 private static final String SET = "set"; 186 187 private static final String TRUE = "true"; 188 189 private static final String FALSE = "false"; 190 191 private static final String ALIGNMENT = "align"; 192 193 private static final String LEFT = "left"; 194 195 private static final String CENTER = "center"; 196 197 private static final String RIGHT = "right"; 198 199 private static final String TOP = "top"; 200 201 private static final String ITALICS = "italic"; 202 203 private static final String BOLD = "bold"; 204 205 private static final String SIZE = "size"; 206 207 private static final String VALIDATOR = "validator"; 208 209 private static final String PROCESSOR = "processor"; 210 211 private static final String CLASS = "class"; 212 213 private static final String FIELD_LABEL = "label"; 214 215 private static final String TITLE_FIELD = "title"; 216 217 private static final String TEXT_FIELD = "text"; 218 219 private static final String TEXT_SIZE = "size"; 220 221 private static final String STATIC_TEXT = "staticText"; 222 223 private static final String COMBO_FIELD = "combo"; 224 225 private static final String COMBO_CHOICE = "choice"; 226 227 private static final String COMBO_VALUE = "value"; 228 229 private static final String RADIO_FIELD = "radio"; 230 231 private static final String RADIO_CHOICE = "choice"; 232 233 private static final String RADIO_VALUE = "value"; 234 235 private static final String SPACE_FIELD = "space"; 236 237 private static final String DIVIDER_FIELD = "divider"; 238 239 private static final String CHECK_FIELD = "check"; 240 241 private static final String RULE_FIELD = "rule"; 242 243 private static final String RULE_LAYOUT = "layout"; 244 245 private static final String RULE_SEPARATOR = "separator"; 246 247 private static final String RULE_RESULT_FORMAT = "resultFormat"; 248 249 private static final String RULE_PLAIN_STRING = "plainString"; 250 251 private static final String RULE_DISPLAY_FORMAT = "displayFormat"; 252 253 private static final String RULE_SPECIAL_SEPARATOR = "specialSeparator"; 254 255 private static final String RULE_ENCRYPTED = "processed"; 256 257 private static final String RULE_PARAM_NAME = "name"; 258 259 private static final String RULE_PARAM_VALUE = "value"; 260 261 private static final String RULE_PARAM = "param"; 262 263 private static final String PWD_FIELD = "password"; 264 265 private static final String PWD_INPUT = "pwd"; 266 267 private static final String PWD_SIZE = "size"; 268 269 private static final String SEARCH_FIELD = "search"; 270 271 // internal value for the button used to trigger autodetection 272 private static final String SEARCH_BUTTON_FIELD = "autodetect"; 273 274 private static final String SEARCH_CHOICE = "choice"; 275 276 private static final String SEARCH_FILENAME = "filename"; 277 278 private static final String SEARCH_RESULT = "result"; 279 280 private static final String SEARCH_VALUE = "value"; 281 282 private static final String SEARCH_TYPE = "type"; 283 284 private static final String SEARCH_FILE = "file"; 285 286 private static final String SEARCH_DIRECTORY = "directory"; 287 288 private static final String SEARCH_PARENTDIR = "parentdir"; 289 290 private static final String SEARCH_CHECKFILENAME = "checkfilename"; 291 292 private static final String SELECTEDPACKS = "createForPack"; // renamed 293 294 private static final String UNSELECTEDPACKS = "createForUnselectedPack"; // new 295 296 // node 297 298 private static final String NAME = "name"; 299 300 private static final String OS = "os"; 301 302 private static final String FAMILY = "family"; 303 304 // ------------------------------------------------------------------------ 305 // Variable Declarations 306 // ------------------------------------------------------------------------ 307 private static int instanceCount = 0; 308 309 protected int instanceNumber = 0; 310 311 /** 312 * If there is a possibility that some UI elements will not get added we can not allow to go 313 * back to the PacksPanel, because the process of building the UI is not reversable. This 314 * variable keeps track if any packs have been defined and will be used to make a decision for 315 * locking the 'previous' button. 316 */ 317 private boolean packsDefined = false; 318 319 private InstallerFrame parentFrame; 320 321 /** The parsed result from reading the XML specification from the file */ 322 private XMLElement spec; 323 324 private boolean haveSpec = false; 325 326 /** Holds the references to all of the UI elements */ 327 private Vector uiElements = new Vector(); 328 329 /** Holds the references to all radio button groups */ 330 private Vector buttonGroups = new Vector(); 331 332 /** Holds the references to all password field groups */ 333 private Vector passwordGroups = new Vector(); 334 335 /** 336 * used for temporary storage of references to password groups that have already been read in a 337 * given read cycle. 338 */ 339 private Vector passwordGroupsRead = new Vector(); 340 341 /** Used to track search fields. Contains SearchField references. */ 342 private Vector searchFields = new Vector(); 343 344 /** Holds all user inputs for use in automated installation */ 345 private Vector entries = new Vector(); 346 347 private TwoColumnLayout layout; 348 349 private LocaleDatabase langpack = null; 350 351 /*--------------------------------------------------------------------------*/ 352 // This method can be used to search for layout problems. If this class is 353 // compiled with this method uncommented, the layout guides will be shown 354 // on the panel, making it possible to see if all components are placed 355 // correctly. 356 /*--------------------------------------------------------------------------*/ 357 // public void paint (Graphics graphics) 358 // { 359 // super.paint (graphics); 360 // layout.showRules ((Graphics2D)graphics, Color.red); 361 // } 362 /*--------------------------------------------------------------------------*/ 363 /** 364 * Constructs a <code>UserInputPanel</code>. 365 * 366 * @param parent reference to the application frame 367 * @param installData shared information about the installation 368 */ 369 /*--------------------------------------------------------------------------*/ 370 public UserInputPanel(InstallerFrame parent, InstallData installData) 371 372 { 373 super(parent, installData); 374 375 instanceNumber = instanceCount++; 376 this.parentFrame = parent; 377 378 // ---------------------------------------------------- 379 // ---------------------------------------------------- 380 layout = new TwoColumnLayout(10, 5, 30, 25, TwoColumnLayout.LEFT); 381 setLayout(layout); 382 383 // ---------------------------------------------------- 384 // get a locale database 385 // ---------------------------------------------------- 386 try 387 { 388 // this.langpack = parent.langpack; 389 390 String resource = LANG_FILE_NAME + "_" + idata.localeISO3; 391 this.langpack = new LocaleDatabase(ResourceManager.getInstance().getInputStream( 392 resource)); 393 } 394 catch (Throwable exception) 395 {} 396 397 // ---------------------------------------------------- 398 // read the specifications 399 // ---------------------------------------------------- 400 try 401 { 402 readSpec(); 403 } 404 catch (Throwable exception) 405 { 406 // log the problem 407 exception.printStackTrace(); 408 } 409 410 if (!haveSpec) 411 { 412 // return if we could not read the spec. further 413 // processing will only lead to problems. In this 414 // case we must skip the panel when it gets activated. 415 return; 416 } 417 418 // ---------------------------------------------------- 419 // process all field nodes. Each field node is analyzed 420 // for its type, then an appropriate memeber function 421 // is called that will create the correct UI elements. 422 // ---------------------------------------------------- 423 Vector fields = spec.getChildrenNamed(FIELD_NODE_ID); 424 425 for (int i = 0; i < fields.size(); i++) 426 { 427 XMLElement field = (XMLElement) fields.elementAt(i); 428 String attribute = field.getAttribute(TYPE); 429 430 if (attribute != null) 431 { 432 if (attribute.equals(RULE_FIELD)) 433 { 434 addRuleField(field); 435 } 436 else if (attribute.equals(TEXT_FIELD)) 437 { 438 addTextField(field); 439 } 440 else if (attribute.equals(COMBO_FIELD)) 441 { 442 addComboBox(field); 443 } 444 else if (attribute.equals(RADIO_FIELD)) 445 { 446 addRadioButton(field); 447 } 448 else if (attribute.equals(PWD_FIELD)) 449 { 450 addPasswordField(field); 451 } 452 else if (attribute.equals(SPACE_FIELD)) 453 { 454 addSpace(field); 455 } 456 else if (attribute.equals(DIVIDER_FIELD)) 457 { 458 addDivider(field); 459 } 460 else if (attribute.equals(CHECK_FIELD)) 461 { 462 addCheckBox(field); 463 } 464 else if (attribute.equals(STATIC_TEXT)) 465 { 466 addText(field); 467 } 468 else if (attribute.equals(TITLE_FIELD)) 469 { 470 addTitle(field); 471 } 472 else if (attribute.equals(SEARCH_FIELD)) 473 { 474 addSearch(field); 475 } 476 } 477 } 478 } 479 480 /*--------------------------------------------------------------------------*/ 481 /** 482 * Indicates wether the panel has been validated or not. The installer won't let the user go 483 * further through the installation process until the panel is validated. Default behavior is to 484 * return true. 485 * 486 * @return A boolean stating wether the panel has been validated or not. 487 */ 488 /*--------------------------------------------------------------------------*/ 489 public boolean isValidated() 490 { 491 return (readInput()); 492 } 493 494 /*--------------------------------------------------------------------------*/ 495 /** 496 * This method is called when the panel becomes active. 497 */ 498 /*--------------------------------------------------------------------------*/ 499 public void panelActivate() 500 { 501 if (spec == null) 502 { 503 // TODO: translate 504 emitError("User input specification could not be found.", 505 "The specification for the user input panel could not be found. Please contact the packager."); 506 parentFrame.skipPanel(); 507 } 508 509 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 510 Vector forUnselectedPacks = spec.getChildrenNamed(UNSELECTEDPACKS); 511 Vector forOs = spec.getChildrenNamed(OS); 512 513 if (!itemRequiredFor(forPacks) || !itemRequiredForUnselected(forUnselectedPacks) 514 || !itemRequiredForOs(forOs)) 515 { 516 parentFrame.skipPanel(); 517 return; 518 } 519 if (!haveSpec) 520 { 521 parentFrame.skipPanel(); 522 return; 523 } 524 // if (uiBuilt) 525 // { 526 // return; 527 // } 528 529 buildUI(); 530 if (packsDefined) 531 { 532 parentFrame.lockPrevButton(); 533 } 534 } 535 536 /*--------------------------------------------------------------------------*/ 537 /** 538 * Asks the panel to set its own XML data that can be brought back for an automated installation 539 * process. Use it as a blackbox if your panel needs to do something even in automated mode. 540 * 541 * @param panelRoot The XML root element of the panels blackbox tree. 542 */ 543 /*--------------------------------------------------------------------------*/ 544 public void makeXMLData(XMLElement panelRoot) 545 { 546 Map entryMap = new HashMap(); 547 548 for (int i = 0; i < entries.size(); i++) 549 { 550 TextValuePair pair = (TextValuePair) entries.elementAt(i); 551 entryMap.put(pair.toString(), pair.getValue()); 552 } 553 554 new UserInputPanelAutomationHelper(entryMap).makeXMLData(idata, panelRoot); 555 } 556 557 /*--------------------------------------------------------------------------*/ 558 /** 559 * Builds the UI and makes it ready for display 560 */ 561 /*--------------------------------------------------------------------------*/ 562 private void buildUI() 563 { 564 Object[] uiElement; 565 566 for (int i = 0; i < uiElements.size(); i++) 567 { 568 uiElement = (Object[]) uiElements.elementAt(i); 569 570 if (itemRequiredFor((Vector) uiElement[POS_PACKS]) 571 && itemRequiredForOs((Vector) uiElement[POS_OS])) 572 { 573 try 574 { 575 if (uiElement[POS_DISPLAYED] == null 576 || uiElement[POS_DISPLAYED].toString().equals("false")) 577 { 578 add((JComponent) uiElement[POS_FIELD], uiElement[POS_CONSTRAINTS]); 579 } 580 581 uiElement[POS_DISPLAYED] = Boolean.valueOf(true); 582 uiElements.remove(i); 583 uiElements.add(i, uiElement); 584 } 585 catch (Throwable exception) 586 { 587 System.out.println("Internal format error in field: " 588 + uiElement[POS_TYPE].toString()); // !!! logging 589 } 590 } 591 else 592 { 593 try 594 { 595 if (uiElement[POS_DISPLAYED] != null 596 && uiElement[POS_DISPLAYED].toString().equals("true")) 597 { 598 remove((JComponent) uiElement[POS_FIELD]); 599 } 600 } 601 catch (Throwable exception) 602 { 603 System.out.println("Internal format error in field: " 604 + uiElement[POS_TYPE].toString()); // !!! logging 605 } 606 uiElement[POS_DISPLAYED] = Boolean.valueOf(false); 607 uiElements.remove(i); 608 uiElements.add(i, uiElement); 609 } 610 } 611 } 612 613 /*--------------------------------------------------------------------------*/ 614 /** 615 * Reads the input data from all UI elements and sets the associated variables. 616 * 617 * @return <code>true</code> if the operation is successdul, otherwise <code>false</code>. 618 */ 619 /*--------------------------------------------------------------------------*/ 620 private boolean readInput() 621 { 622 boolean success; 623 String fieldType = null; 624 Object[] field = null; 625 626 passwordGroupsRead.clear(); 627 // ---------------------------------------------------- 628 // cycle through all but the password fields and read 629 // their contents 630 // ---------------------------------------------------- 631 for (int i = 0; i < uiElements.size(); i++) 632 { 633 field = (Object[]) uiElements.elementAt(i); 634 635 if ((field != null) && (((Boolean) field[POS_DISPLAYED]).booleanValue())) 636 { 637 fieldType = (String) (field[POS_TYPE]); 638 639 // ------------------------------------------------ 640 if (fieldType.equals(RULE_FIELD)) 641 { 642 success = readRuleField(field); 643 if (!success) { return (false); } 644 } 645 646 // ------------------------------------------------ 647 if (fieldType.equals(PWD_FIELD)) 648 { 649 success = readPasswordField(field); 650 if (!success) { return (false); } 651 } 652 653 // ------------------------------------------------ 654 else if (fieldType.equals(TEXT_FIELD)) 655 { 656 success = readTextField(field); 657 if (!success) { return (false); } 658 } 659 660 // ------------------------------------------------ 661 else if (fieldType.equals(COMBO_FIELD)) 662 { 663 success = readComboBox(field); 664 if (!success) { return (false); } 665 } 666 667 // ------------------------------------------------ 668 else if (fieldType.equals(RADIO_FIELD)) 669 { 670 success = readRadioButton(field); 671 if (!success) { return (false); } 672 } 673 674 // ------------------------------------------------ 675 else if (fieldType.equals(CHECK_FIELD)) 676 { 677 success = readCheckBox(field); 678 if (!success) { return (false); } 679 } 680 else if (fieldType.equals(SEARCH_FIELD)) 681 { 682 success = readSearch(field); 683 if (!success) { return (false); } 684 } 685 } 686 } 687 688 return (true); 689 } 690 691 /*--------------------------------------------------------------------------*/ 692 /** 693 * Reads the XML specification for the panel layout. The result is stored in spec. 694 * 695 * @exception Exception for any problems in reading the specification 696 */ 697 /*--------------------------------------------------------------------------*/ 698 private void readSpec() throws Exception 699 { 700 InputStream input = null; 701 XMLElement data; 702 Vector specElements; 703 String attribute; 704 String instance = Integer.toString(instanceNumber); 705 706 try 707 { 708 input = parentFrame.getResource(SPEC_FILE_NAME); 709 } 710 catch (Exception exception) 711 { 712 haveSpec = false; 713 return; 714 } 715 if (input == null) 716 { 717 haveSpec = false; 718 return; 719 } 720 721 // initialize the parser 722 StdXMLParser parser = new StdXMLParser(); 723 parser.setBuilder(new StdXMLBuilder()); 724 parser.setValidator(new NonValidator()); 725 parser.setReader(new StdXMLReader(input)); 726 727 // get the data 728 data = (XMLElement) parser.parse(); 729 730 // extract the spec to this specific panel instance 731 if (data.hasChildren()) 732 { 733 specElements = data.getChildrenNamed(NODE_ID); 734 for (int i = 0; i < specElements.size(); i++) 735 { 736 data = (XMLElement) specElements.elementAt(i); 737 attribute = data.getAttribute(INSTANCE_IDENTIFIER); 738 739 if (instance.equals(attribute)) 740 { 741 // use the current element as spec 742 spec = data; 743 // close the stream 744 input.close(); 745 haveSpec = true; 746 return; 747 } 748 } 749 750 haveSpec = false; 751 return; 752 } 753 754 haveSpec = false; 755 } 756 757 /*--------------------------------------------------------------------------*/ 758 /** 759 * Adds the title to the panel. There can only be one title, if mutiple titles are defined, they 760 * keep overwriting what has already be defined, so that the last definition is the one that 761 * prevails. 762 * 763 * @param spec a <code>XMLElement</code> containing the specification for the title. 764 */ 765 /*--------------------------------------------------------------------------*/ 766 private void addTitle(XMLElement spec) 767 { 768 String title = getText(spec); 769 boolean italic = getBoolean(spec, ITALICS, false); 770 boolean bold = getBoolean(spec, BOLD, false); 771 float multiplier = getFloat(spec, SIZE, 2.0f); 772 int justify = getAlignment(spec); 773 774 if (title != null) 775 { 776 JLabel label = new JLabel(title); 777 Font font = label.getFont(); 778 float size = font.getSize(); 779 int style = 0; 780 781 if (bold) 782 { 783 style = style + Font.BOLD; 784 } 785 if (italic) 786 { 787 style = style + Font.ITALIC; 788 } 789 790 font = font.deriveFont(style, (size * multiplier)); 791 label.setFont(font); 792 label.setAlignmentX(0); 793 794 TwoColumnConstraints constraints = new TwoColumnConstraints(); 795 constraints.align = justify; 796 constraints.position = TwoColumnConstraints.NORTH; 797 798 add(label, constraints); 799 } 800 } 801 802 /*--------------------------------------------------------------------------*/ 803 /** 804 * Adds a rule field to the list of UI elements. 805 * 806 * @param spec a <code>XMLElement</code> containing the specification for the rule field. 807 */ 808 /*--------------------------------------------------------------------------*/ 809 private void addRuleField(XMLElement spec) 810 { 811 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 812 Vector forOs = spec.getChildrenNamed(OS); 813 XMLElement element = spec.getFirstChildNamed(SPEC); 814 String variable = spec.getAttribute(VARIABLE); 815 RuleInputField field = null; 816 JLabel label; 817 String layout; 818 String set; 819 String separator; 820 String format; 821 String validator = null; 822 String message = null; 823 boolean hasParams = false; 824 String paramName = null; 825 String paramValue = null; 826 HashMap validateParamMap = null; 827 Vector validateParams = null; 828 String processor = null; 829 int resultFormat = RuleInputField.DISPLAY_FORMAT; 830 831 // ---------------------------------------------------- 832 // extract the specification details 833 // ---------------------------------------------------- 834 if (element != null) 835 { 836 label = new JLabel(getText(element)); 837 layout = element.getAttribute(RULE_LAYOUT); 838 set = element.getAttribute(SET); 839 840 // retrieve value of variable if not specified 841 // (does not work here because of special format for set attribute) 842 // if (set == null) 843 // { 844 // set = idata.getVariable (variable); 845 // } 846 847 separator = element.getAttribute(RULE_SEPARATOR); 848 format = element.getAttribute(RULE_RESULT_FORMAT); 849 850 if (format != null) 851 { 852 if (format.equals(RULE_PLAIN_STRING)) 853 { 854 resultFormat = RuleInputField.PLAIN_STRING; 855 } 856 else if (format.equals(RULE_DISPLAY_FORMAT)) 857 { 858 resultFormat = RuleInputField.DISPLAY_FORMAT; 859 } 860 else if (format.equals(RULE_SPECIAL_SEPARATOR)) 861 { 862 resultFormat = RuleInputField.SPECIAL_SEPARATOR; 863 } 864 else if (format.equals(RULE_ENCRYPTED)) 865 { 866 resultFormat = RuleInputField.ENCRYPTED; 867 } 868 } 869 } 870 // ---------------------------------------------------- 871 // if there is no specification element, return without 872 // doing anything. 873 // ---------------------------------------------------- 874 else 875 { 876 return; 877 } 878 879 // ---------------------------------------------------- 880 // get the description and add it to the list of UI 881 // elements if it exists. 882 // ---------------------------------------------------- 883 element = spec.getFirstChildNamed(DESCRIPTION); 884 addDescription(element, forPacks, forOs); 885 886 // ---------------------------------------------------- 887 // get the validator and processor if they are defined 888 // ---------------------------------------------------- 889 element = spec.getFirstChildNamed(VALIDATOR); 890 if (element != null) 891 { 892 validator = element.getAttribute(CLASS); 893 message = getText(element); 894 // ---------------------------------------------------------- 895 // check and see if we have any parameters for this validator. 896 // If so, then add them to validateParamMap. 897 // ---------------------------------------------------------- 898 validateParams = element.getChildrenNamed(RULE_PARAM); 899 if (validateParams != null && validateParams.size() > 0 && validateParamMap == null) 900 { 901 902 validateParamMap = new HashMap(); 903 hasParams = true; 904 905 } 906 907 for (Iterator it = validateParams.iterator(); it.hasNext();) 908 { 909 element = (XMLElement) it.next(); 910 paramName = element.getAttribute(RULE_PARAM_NAME); 911 paramValue = element.getAttribute(RULE_PARAM_VALUE); 912 validateParamMap.put(paramName, paramValue); 913 } 914 } 915 916 element = spec.getFirstChildNamed(PROCESSOR); 917 if (element != null) 918 { 919 processor = element.getAttribute(CLASS); 920 } 921 922 // ---------------------------------------------------- 923 // create an instance of RuleInputField based on the 924 // extracted specifications, then add it to the list 925 // of UI elements. 926 // ---------------------------------------------------- 927 if (hasParams) 928 { 929 field = new RuleInputField(layout, set, separator, validator, validateParamMap, 930 processor, resultFormat, getToolkit(), idata); 931 } 932 else 933 { 934 field = new RuleInputField(layout, set, separator, validator, processor, resultFormat, 935 getToolkit(), idata); 936 937 } 938 TwoColumnConstraints constraints = new TwoColumnConstraints(); 939 constraints.position = TwoColumnConstraints.WEST; 940 941 uiElements 942 .add(new Object[] { null, FIELD_LABEL, null, constraints, label, forPacks, forOs}); 943 944 TwoColumnConstraints constraints2 = new TwoColumnConstraints(); 945 constraints2.position = TwoColumnConstraints.EAST; 946 947 uiElements.add(new Object[] { null, RULE_FIELD, variable, constraints2, field, forPacks, 948 forOs, null, null, message}); 949 } 950 951 /*--------------------------------------------------------------------------*/ 952 /** 953 * Reads the data from the rule input field and sets the associated variable. 954 * 955 * @param field the object array that holds the details of the field. 956 * 957 * @return <code>true</code> if there was no problem reading the data or if there was an 958 * irrecovarable problem. If there was a problem that can be corrected by the operator, an error 959 * dialog is popped up and <code>false</code> is returned. 960 */ 961 /*--------------------------------------------------------------------------*/ 962 private boolean readRuleField(Object[] field) 963 { 964 RuleInputField ruleField = null; 965 String variable = null; 966 967 try 968 { 969 ruleField = (RuleInputField) field[POS_FIELD]; 970 variable = (String) field[POS_VARIABLE]; 971 } 972 catch (Throwable exception) 973 { 974 return (true); 975 } 976 if ((variable == null) || (ruleField == null)) { return (true); } 977 978 boolean success = ruleField.validateContents(); 979 if (!success) 980 { 981 String message = ""; 982 try 983 { 984 message = langpack.getString((String) field[POS_MESSAGE]); 985 if (message.equals("")) 986 { 987 message = (String) field[POS_MESSAGE]; 988 } 989 } 990 catch (Throwable t) 991 { 992 message = (String) field[POS_MESSAGE]; 993 } 994 JOptionPane.showMessageDialog(parentFrame, message, parentFrame.langpack 995 .getString("UserInputPanel.error.caption"), JOptionPane.WARNING_MESSAGE); 996 return (false); 997 } 998 999 idata.setVariable(variable, ruleField.getText()); 1000 entries.add(new TextValuePair(variable, ruleField.getText())); 1001 return (true); 1002 } 1003 1004 /*--------------------------------------------------------------------------*/ 1005 /** 1006 * Adds a text field to the list of UI elements 1007 * 1008 * @param spec a <code>XMLElement</code> containing the specification for the text field. 1009 */ 1010 /*--------------------------------------------------------------------------*/ 1011 private void addTextField(XMLElement spec) 1012 { 1013 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 1014 Vector forOs = spec.getChildrenNamed(OS); 1015 XMLElement element = spec.getFirstChildNamed(SPEC); 1016 JLabel label; 1017 String set; 1018 int size; 1019 1020 String variable = spec.getAttribute(VARIABLE); 1021 if ((variable == null) || (variable.length() == 0)) { return; } 1022 1023 // ---------------------------------------------------- 1024 // extract the specification details 1025 // ---------------------------------------------------- 1026 if (element != null) 1027 { 1028 label = new JLabel(getText(element)); 1029 set = element.getAttribute(SET); 1030 if (set == null) 1031 { 1032 set = idata.getVariable(variable); 1033 if (set == null) 1034 { 1035 set = ""; 1036 } 1037 }else{ 1038 if (set != null && !"".equals(set)){ 1039 VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); 1040 set = vs.substitute(set, null); 1041 } 1042 } 1043 1044 try 1045 { 1046 size = Integer.parseInt(element.getAttribute(TEXT_SIZE)); 1047 } 1048 catch (Throwable exception) 1049 { 1050 size = 1; 1051 } 1052 } 1053 // ---------------------------------------------------- 1054 // if there is no specification element, return without 1055 // doing anything. 1056 // ---------------------------------------------------- 1057 else 1058 { 1059 return; 1060 } 1061 1062 // ---------------------------------------------------- 1063 // get the description and add it to the list UI 1064 // elements if it exists. 1065 // ---------------------------------------------------- 1066 element = spec.getFirstChildNamed(DESCRIPTION); 1067 addDescription(element, forPacks, forOs); 1068 1069 // ---------------------------------------------------- 1070 // construct the UI element and add it to the list 1071 // ---------------------------------------------------- 1072 JTextField field = new JTextField(set, size); 1073 field.setCaretPosition(0); 1074 1075 TwoColumnConstraints constraints = new TwoColumnConstraints(); 1076 constraints.position = TwoColumnConstraints.WEST; 1077 1078 uiElements 1079 .add(new Object[] { null, FIELD_LABEL, null, constraints, label, forPacks, forOs}); 1080 1081 TwoColumnConstraints constraints2 = new TwoColumnConstraints(); 1082 constraints2.position = TwoColumnConstraints.EAST; 1083 1084 uiElements.add(new Object[] { null, TEXT_FIELD, variable, constraints2, field, forPacks, 1085 forOs}); 1086 } 1087 1088 /*--------------------------------------------------------------------------*/ 1089 /** 1090 * Reads data from the text field and sets the associated variable. 1091 * 1092 * @param field the object array that holds the details of the field. 1093 * 1094 * @return <code>true</code> if there was no problem reading the data or if there was an 1095 * irrecovarable problem. If there was a problem that can be corrected by the operator, an error 1096 * dialog is popped up and <code>false</code> is returned. 1097 */ 1098 /*--------------------------------------------------------------------------*/ 1099 private boolean readTextField(Object[] field) 1100 { 1101 JTextField textField = null; 1102 String variable = null; 1103 String value = null; 1104 1105 try 1106 { 1107 textField = (JTextField) field[POS_FIELD]; 1108 variable = (String) field[POS_VARIABLE]; 1109 value = textField.getText(); 1110 } 1111 catch (Throwable exception) 1112 { 1113 return (true); 1114 } 1115 if ((variable == null) || (value == null)) { return (true); } 1116 1117 idata.setVariable(variable, value); 1118 entries.add(new TextValuePair(variable, value)); 1119 return (true); 1120 } 1121 1122 /*--------------------------------------------------------------------------*/ 1123 /** 1124 * Adds a combo box to the list of UI elements. <br> 1125 * This is a complete example of a valid XML specification 1126 * 1127 * <pre> 1128 * 1129 * 1130 * 1131 * <field type="combo" variable="testVariable"> 1132 * <description text="Description for the combo box" id="a key for translated text"/> 1133 * <spec text="label" id="key for the label"/> 1134 * <choice text="choice 1" id="" value="combo box 1"/> 1135 * <choice text="choice 2" id="" value="combo box 2" set="true"/> 1136 * <choice text="choice 3" id="" value="combo box 3"/> 1137 * <choice text="choice 4" id="" value="combo box 4"/> 1138 * </spec> 1139 * </field> 1140 * 1141 * 1142 * 1143 * </pre> 1144 * 1145 * @param spec a <code>XMLElement</code> containing the specification for the combo box. 1146 */ 1147 /*--------------------------------------------------------------------------*/ 1148 private void addComboBox(XMLElement spec) 1149 { 1150 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 1151 Vector forOs = spec.getChildrenNamed(OS); 1152 XMLElement element = spec.getFirstChildNamed(SPEC); 1153 String variable = spec.getAttribute(VARIABLE); 1154 TextValuePair listItem = null; 1155 JComboBox field = new JComboBox(); 1156 JLabel label; 1157 1158 // ---------------------------------------------------- 1159 // extract the specification details 1160 // ---------------------------------------------------- 1161 if (element != null) 1162 { 1163 label = new JLabel(getText(element)); 1164 1165 Vector choices = element.getChildrenNamed(COMBO_CHOICE); 1166 1167 if (choices == null) { return; } 1168 1169 for (int i = 0; i < choices.size(); i++) 1170 { 1171 String processorClass = ((XMLElement) choices.elementAt(i)) 1172 .getAttribute("processor"); 1173 1174 if (processorClass != null && !"".equals(processorClass)) 1175 { 1176 String choiceValues = ""; 1177 try 1178 { 1179 choiceValues = ((Processor) Class.forName(processorClass).newInstance()) 1180 .process(null); 1181 } 1182 catch (Throwable t) 1183 { 1184 t.printStackTrace(); 1185 } 1186 String set = ((XMLElement) choices.elementAt(i)).getAttribute(SET); 1187 if (set == null) 1188 { 1189 set = ""; 1190 } 1191 if (set != null && !"".equals(set)){ 1192 VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); 1193 set = vs.substitute(set, null); 1194 } 1195 1196 StringTokenizer tokenizer = new StringTokenizer(choiceValues, ":"); 1197 int counter = 0; 1198 while (tokenizer.hasMoreTokens()) 1199 { 1200 String token = tokenizer.nextToken(); 1201 listItem = new TextValuePair(token, token); 1202 field.addItem(listItem); 1203 if (set.equals(token)) 1204 { 1205 field.setSelectedIndex(field.getItemCount() - 1); 1206 } 1207 counter++; 1208 } 1209 } 1210 else 1211 { 1212 listItem = new TextValuePair(getText((XMLElement) choices.elementAt(i)), 1213 ((XMLElement) choices.elementAt(i)).getAttribute(COMBO_VALUE)); 1214 field.addItem(listItem); 1215 String set = ((XMLElement) choices.elementAt(i)).getAttribute(SET); 1216 if (set != null) 1217 { 1218 if (set != null && !"".equals(set)){ 1219 VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); 1220 set = vs.substitute(set, null); 1221 } 1222 if (set.equals(TRUE)) 1223 { 1224 field.setSelectedIndex(i); 1225 } 1226 } 1227 } 1228 1229 } 1230 } 1231 // ---------------------------------------------------- 1232 // if there is no specification element, return without 1233 // doing anything. 1234 // ---------------------------------------------------- 1235 else 1236 { 1237 return; 1238 } 1239 1240 // ---------------------------------------------------- 1241 // get the description and add it to the list of UI 1242 // elements if it exists. 1243 // ---------------------------------------------------- 1244 element = spec.getFirstChildNamed(DESCRIPTION); 1245 addDescription(element, forPacks, forOs); 1246 1247 TwoColumnConstraints constraints = new TwoColumnConstraints(); 1248 constraints.position = TwoColumnConstraints.WEST; 1249 1250 uiElements 1251 .add(new Object[] { null, FIELD_LABEL, null, constraints, label, forPacks, forOs}); 1252 1253 TwoColumnConstraints constraints2 = new TwoColumnConstraints(); 1254 constraints2.position = TwoColumnConstraints.EAST; 1255 1256 uiElements.add(new Object[] { null, COMBO_FIELD, variable, constraints2, field, forPacks, 1257 forOs}); 1258 } 1259 1260 /*--------------------------------------------------------------------------*/ 1261 /** 1262 * Reads the content of the combobox field and substitutes the associated variable. 1263 * 1264 * @param field the object array that holds the details of the field. 1265 * 1266 * @return <code>true</code> if there was no problem reading the data or if there was an 1267 * irrecovarable problem. If there was a problem that can be corrected by the operator, an error 1268 * dialog is popped up and <code>false</code> is returned. 1269 */ 1270 /*--------------------------------------------------------------------------*/ 1271 private boolean readComboBox(Object[] field) 1272 { 1273 String variable; 1274 String value; 1275 JComboBox comboBox; 1276 1277 try 1278 { 1279 variable = (String) field[POS_VARIABLE]; 1280 comboBox = (JComboBox) field[POS_FIELD]; 1281 value = ((TextValuePair) comboBox.getSelectedItem()).getValue(); 1282 } 1283 catch (Throwable exception) 1284 { 1285 return true; 1286 } 1287 if ((variable == null) || (value == null)) { return true; } 1288 1289 idata.setVariable(variable, value); 1290 entries.add(new TextValuePair(variable, value)); 1291 return true; 1292 } 1293 1294 /*--------------------------------------------------------------------------*/ 1295 /** 1296 * Adds a radio button set to the list of UI elements. <br> 1297 * This is a complete example of a valid XML specification 1298 * 1299 * <pre> 1300 * 1301 * 1302 * 1303 * <field type="radio" variable="testVariable"> 1304 * <description text="Description for the radio buttons" id="a key for translated text"/> 1305 * <spec text="label" id="key for the label"/> 1306 * <choice text="radio 1" id="" value=""/> 1307 * <choice text="radio 2" id="" value="" set="true"/> 1308 * <choice text="radio 3" id="" value=""/> 1309 * <choice text="radio 4" id="" value=""/> 1310 * <choice text="radio 5" id="" value=""/> 1311 * </spec> 1312 * </field> 1313 * 1314 * 1315 * 1316 * </pre> 1317 * 1318 * @param spec a <code>XMLElement</code> containing the specification for the radio button 1319 * set. 1320 */ 1321 /*--------------------------------------------------------------------------*/ 1322 private void addRadioButton(XMLElement spec) 1323 { 1324 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 1325 Vector forOs = spec.getChildrenNamed(OS); 1326 String variable = spec.getAttribute(VARIABLE); 1327 String value = null; 1328 1329 XMLElement element = null; 1330 ButtonGroup group = new ButtonGroup(); 1331 1332 TwoColumnConstraints constraints = new TwoColumnConstraints(); 1333 constraints.position = TwoColumnConstraints.BOTH; 1334 constraints.indent = true; 1335 constraints.stretch = true; 1336 1337 // ---------------------------------------------------- 1338 // get the description and add it to the list of UI 1339 // elements if it exists. 1340 // ---------------------------------------------------- 1341 element = spec.getFirstChildNamed(DESCRIPTION); 1342 addDescription(element, forPacks, forOs); 1343 1344 // ---------------------------------------------------- 1345 // extract the specification details 1346 // ---------------------------------------------------- 1347 element = spec.getFirstChildNamed(SPEC); 1348 1349 if (element != null) 1350 { 1351 Vector choices = element.getChildrenNamed(RADIO_CHOICE); 1352 1353 if (choices == null) { return; } 1354 1355 // -------------------------------------------------- 1356 // process each choice element 1357 // -------------------------------------------------- 1358 for (int i = 0; i < choices.size(); i++) 1359 { 1360 JRadioButton choice = new JRadioButton(); 1361 choice.setText(getText((XMLElement) choices.elementAt(i))); 1362 value = (((XMLElement) choices.elementAt(i)).getAttribute(RADIO_VALUE)); 1363 1364 group.add(choice); 1365 1366 String set = ((XMLElement) choices.elementAt(i)).getAttribute(SET); 1367 if (set != null) 1368 { 1369 if (set != null && !"".equals(set)){ 1370 VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); 1371 set = vs.substitute(set, null); 1372 } 1373 if (set.equals(TRUE)) 1374 { 1375 choice.setSelected(true); 1376 } 1377 } 1378 1379 buttonGroups.add(group); 1380 uiElements.add(new Object[] { null, RADIO_FIELD, variable, constraints, choice, 1381 forPacks, forOs, value, null, null, group}); 1382 } 1383 } 1384 } 1385 1386 /*--------------------------------------------------------------------------*/ 1387 /** 1388 * Reads the content of the radio button field and substitutes the associated variable. 1389 * 1390 * @param field the object array that holds the details of the field. 1391 * 1392 * @return <code>true</code> if there was no problem reading the data or if there was an 1393 * irrecovarable problem. If there was a problem that can be corrected by the operator, an error 1394 * dialog is popped up and <code>false</code> is returned. 1395 */ 1396 /*--------------------------------------------------------------------------*/ 1397 private boolean readRadioButton(Object[] field) 1398 { 1399 String variable = null; 1400 String value = null; 1401 JRadioButton button = null; 1402 1403 try 1404 { 1405 button = (JRadioButton) field[POS_FIELD]; 1406 1407 if (!button.isSelected()) { return (true); } 1408 1409 variable = (String) field[POS_VARIABLE]; 1410 value = (String) field[POS_TRUE]; 1411 } 1412 catch (Throwable exception) 1413 { 1414 return (true); 1415 } 1416 1417 idata.setVariable(variable, value); 1418 entries.add(new TextValuePair(variable, value)); 1419 return (true); 1420 } 1421 1422 /*--------------------------------------------------------------------------*/ 1423 /** 1424 * Adds one or more password fields to the list of UI elements. <br> 1425 * This is a complete example of a valid XML specification 1426 * 1427 * <pre> 1428 * 1429 * 1430 * 1431 * <field type="password" variable="testVariable"> 1432 * <description align="left" txt="Please enter your password" id="a key for translated text"/> 1433 * <spec> 1434 * <pwd txt="Password" id="key for the label" size="10" set=""/> 1435 * <pwd txt="Retype password" id="another key for the label" size="10" set=""/> 1436 * </spec> 1437 * <validator class="com.izforge.sample.PWDValidator" txt="Both versions of the password must match" id="key for the error text"/> 1438 * <processor class="com.izforge.sample.PWDEncryptor"/> 1439 * </field> 1440 * 1441 * 1442 * 1443 * </pre> 1444 * 1445 * @param spec a <code>XMLElement</code> containing the specification for the set of password 1446 * fields. 1447 */ 1448 /*--------------------------------------------------------------------------*/ 1449 private void addPasswordField(XMLElement spec) 1450 { 1451 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 1452 Vector forOs = spec.getChildrenNamed(OS); 1453 String variable = spec.getAttribute(VARIABLE); 1454 String validator = null; 1455 String message = null; 1456 String processor = null; 1457 XMLElement element = null; 1458 PasswordGroup group = null; 1459 int size = 0; 1460 1461 // ---------------------------------------------------- 1462 // get the description and add it to the list of UI 1463 // elements if it exists. 1464 // ---------------------------------------------------- 1465 element = spec.getFirstChildNamed(DESCRIPTION); 1466 addDescription(element, forPacks, forOs); 1467 1468 // ---------------------------------------------------- 1469 // get the validator and processor if they are defined 1470 // ---------------------------------------------------- 1471 element = spec.getFirstChildNamed(VALIDATOR); 1472 if (element != null) 1473 { 1474 validator = element.getAttribute(CLASS); 1475 message = getText(element); 1476 } 1477 1478 element = spec.getFirstChildNamed(PROCESSOR); 1479 if (element != null) 1480 { 1481 processor = element.getAttribute(CLASS); 1482 } 1483 1484 group = new PasswordGroup(validator, processor); 1485 1486 // ---------------------------------------------------- 1487 // extract the specification details 1488 // ---------------------------------------------------- 1489 element = spec.getFirstChildNamed(SPEC); 1490 1491 if (element != null) 1492 { 1493 Vector inputs = element.getChildrenNamed(PWD_INPUT); 1494 1495 if (inputs == null) { return; } 1496 1497 // -------------------------------------------------- 1498 // process each input field 1499 // -------------------------------------------------- 1500 XMLElement fieldSpec; 1501 for (int i = 0; i < inputs.size(); i++) 1502 { 1503 fieldSpec = (XMLElement) inputs.elementAt(i); 1504 String set = fieldSpec.getAttribute(SET); 1505 if (set != null && !"".equals(set)){ 1506 VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); 1507 set = vs.substitute(set, null); 1508 } 1509 JLabel label = new JLabel(getText(fieldSpec)); 1510 try 1511 { 1512 size = Integer.parseInt(fieldSpec.getAttribute(PWD_SIZE)); 1513 } 1514 catch (Throwable exception) 1515 { 1516 size = 1; 1517 } 1518 1519 // ---------------------------------------------------- 1520 // construct the UI element and add it to the list 1521 // ---------------------------------------------------- 1522 JPasswordField field = new JPasswordField(set, size); 1523 field.setCaretPosition(0); 1524 1525 TwoColumnConstraints constraints = new TwoColumnConstraints(); 1526 constraints.position = TwoColumnConstraints.WEST; 1527 1528 uiElements.add(new Object[] { null, FIELD_LABEL, null, constraints, label, 1529 forPacks, forOs}); 1530 1531 TwoColumnConstraints constraints2 = new TwoColumnConstraints(); 1532 constraints2.position = TwoColumnConstraints.EAST; 1533 1534 uiElements.add(new Object[] { null, PWD_FIELD, variable, constraints2, field, 1535 forPacks, forOs, null, null, message, group}); 1536 group.addField(field); 1537 } 1538 } 1539 1540 passwordGroups.add(group); 1541 } 1542 1543 /*--------------------------------------------------------------------------*/ 1544 /** 1545 * Reads the content of the password field and substitutes the associated variable. 1546 * 1547 * @param field a password group that manages one or more passord fields. 1548 * 1549 * @return <code>true</code> if there was no problem reading the data or if there was an 1550 * irrecovarable problem. If there was a problem that can be corrected by the operator, an error 1551 * dialog is popped up and <code>false</code> is returned. 1552 */ 1553 /*--------------------------------------------------------------------------*/ 1554 private boolean readPasswordField(Object[] field) 1555 { 1556 PasswordGroup group = null; 1557 String variable = null; 1558 String message = null; 1559 1560 try 1561 { 1562 group = (PasswordGroup) field[POS_GROUP]; 1563 variable = (String) field[POS_VARIABLE]; 1564 message = (String) field[POS_MESSAGE]; 1565 } 1566 catch (Throwable exception) 1567 { 1568 return (true); 1569 } 1570 if ((variable == null) || (passwordGroupsRead.contains(group))) { return (true); } 1571 passwordGroups.add(group); 1572 1573 boolean success = group.validateContents(); 1574 1575 if (!success) 1576 { 1577 JOptionPane.showMessageDialog(parentFrame, message, parentFrame.langpack 1578 .getString("UserInputPanel.error.caption"), JOptionPane.WARNING_MESSAGE); 1579 return (false); 1580 } 1581 1582 idata.setVariable(variable, group.getPassword()); 1583 entries.add(new TextValuePair(variable, group.getPassword())); 1584 return (true); 1585 } 1586 1587 /*--------------------------------------------------------------------------*/ 1588 /** 1589 * Adds a chackbox to the list of UI elements. 1590 * 1591 * @param spec a <code>XMLElement</code> containing the specification for the checkbox. 1592 */ 1593 /*--------------------------------------------------------------------------*/ 1594 private void addCheckBox(XMLElement spec) 1595 { 1596 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 1597 Vector forOs = spec.getChildrenNamed(OS); 1598 String label = ""; 1599 String set = null; 1600 String trueValue = null; 1601 String falseValue = null; 1602 String variable = spec.getAttribute(VARIABLE); 1603 XMLElement detail = spec.getFirstChildNamed(SPEC); 1604 1605 if (variable == null) { return; } 1606 1607 if (detail != null) 1608 { 1609 label = getText(detail); 1610 set = detail.getAttribute(SET); 1611 trueValue = detail.getAttribute(TRUE); 1612 falseValue = detail.getAttribute(FALSE); 1613 } 1614 1615 JCheckBox checkbox = new JCheckBox(label); 1616 1617 if (set != null) 1618 { 1619 if (set != null && !"".equals(set)){ 1620 VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); 1621 set = vs.substitute(set, null); 1622 } 1623 if (set.equals(FALSE)) 1624 { 1625 checkbox.setSelected(false); 1626 } 1627 if (set.equals(TRUE)) 1628 { 1629 checkbox.setSelected(true); 1630 } 1631 } 1632 1633 // ---------------------------------------------------- 1634 // get the description and add it to the list of UI 1635 // elements if it exists. 1636 // ---------------------------------------------------- 1637 XMLElement element = spec.getFirstChildNamed(DESCRIPTION); 1638 addDescription(element, forPacks, forOs); 1639 1640 TwoColumnConstraints constraints = new TwoColumnConstraints(); 1641 constraints.position = TwoColumnConstraints.BOTH; 1642 constraints.stretch = true; 1643 constraints.indent = true; 1644 1645 uiElements.add(new Object[] { null, CHECK_FIELD, variable, constraints, checkbox, forPacks, 1646 forOs, trueValue, falseValue}); 1647 } 1648 1649 /*--------------------------------------------------------------------------*/ 1650 /** 1651 * Reads the content of the checkbox field and substitutes the associated variable. 1652 * 1653 * @param field the object array that holds the details of the field. 1654 * 1655 * @return <code>true</code> if there was no problem reading the data or if there was an 1656 * irrecovarable problem. If there was a problem that can be corrected by the operator, an error 1657 * dialog is popped up and <code>false</code> is returned. 1658 */ 1659 /*--------------------------------------------------------------------------*/ 1660 private boolean readCheckBox(Object[] field) 1661 { 1662 String variable = null; 1663 String trueValue = null; 1664 String falseValue = null; 1665 JCheckBox box = null; 1666 1667 try 1668 { 1669 box = (JCheckBox) field[POS_FIELD]; 1670 variable = (String) field[POS_VARIABLE]; 1671 trueValue = (String) field[POS_TRUE]; 1672 if (trueValue == null) 1673 { 1674 trueValue = ""; 1675 } 1676 1677 falseValue = (String) field[POS_FALSE]; 1678 if (falseValue == null) 1679 { 1680 falseValue = ""; 1681 } 1682 } 1683 catch (Throwable exception) 1684 { 1685 return (true); 1686 } 1687 1688 if (box.isSelected()) 1689 { 1690 idata.setVariable(variable, trueValue); 1691 entries.add(new TextValuePair(variable, trueValue)); 1692 } 1693 else 1694 { 1695 idata.setVariable(variable, falseValue); 1696 entries.add(new TextValuePair(variable, falseValue)); 1697 } 1698 1699 return (true); 1700 } 1701 1702 /*--------------------------------------------------------------------------*/ 1703 /** 1704 * Adds a search field to the list of UI elements. 1705 * <p> 1706 * This is a complete example of a valid XML specification 1707 * 1708 * <pre> 1709 * 1710 * 1711 * 1712 * <field type="search" variable="testVariable"> 1713 * <description text="Description for the search field" id="a key for translated text"/> 1714 * <spec text="label" id="key for the label" filename="the_file_to_search" result="directory" /> <!-- values for result: directory, file --> 1715 * <choice dir="directory1" set="true" /> <!-- default value --> 1716 * <choice dir="dir2" /> 1717 * </spec> 1718 * </field> 1719 * 1720 * 1721 * 1722 * </pre> 1723 * 1724 * @param spec a <code>XMLElement</code> containing the specification for the search field 1725 */ 1726 /*--------------------------------------------------------------------------*/ 1727 private void addSearch(XMLElement spec) 1728 { 1729 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 1730 Vector forOs = spec.getChildrenNamed(OS); 1731 XMLElement element = spec.getFirstChildNamed(SPEC); 1732 String variable = spec.getAttribute(VARIABLE); 1733 String filename = null; 1734 String check_filename = null; 1735 int search_type = 0; 1736 int result_type = 0; 1737 JComboBox combobox = new JComboBox(); 1738 JLabel label = null; 1739 1740 // System.out.println ("adding search combobox, variable "+variable); 1741 1742 // allow the user to enter something 1743 combobox.setEditable(true); 1744 1745 // ---------------------------------------------------- 1746 // extract the specification details 1747 // ---------------------------------------------------- 1748 if (element != null) 1749 { 1750 label = new JLabel(getText(element)); 1751 1752 // search type is optional (default: file) 1753 search_type = SearchField.TYPE_FILE; 1754 1755 String search_type_str = element.getAttribute(SEARCH_TYPE); 1756 1757 if (search_type_str != null) 1758 { 1759 if (search_type_str.equals(SEARCH_FILE)) 1760 { 1761 search_type = SearchField.TYPE_FILE; 1762 } 1763 else if (search_type_str.equals(SEARCH_DIRECTORY)) 1764 { 1765 search_type = SearchField.TYPE_DIRECTORY; 1766 } 1767 } 1768 1769 // result type is mandatory too 1770 String result_type_str = element.getAttribute(SEARCH_RESULT); 1771 1772 if (result_type_str == null) 1773 { 1774 return; 1775 } 1776 else if (result_type_str.equals(SEARCH_FILE)) 1777 { 1778 result_type = SearchField.RESULT_FILE; 1779 } 1780 else if (result_type_str.equals(SEARCH_DIRECTORY)) 1781 { 1782 result_type = SearchField.RESULT_DIRECTORY; 1783 } 1784 else if (result_type_str.equals(SEARCH_PARENTDIR)) 1785 { 1786 result_type = SearchField.RESULT_PARENTDIR; 1787 } 1788 else 1789 { 1790 return; 1791 } 1792 1793 // might be missing - null is okay 1794 filename = element.getAttribute(SEARCH_FILENAME); 1795 1796 check_filename = element.getAttribute(SEARCH_CHECKFILENAME); 1797 1798 Vector choices = element.getChildrenNamed(SEARCH_CHOICE); 1799 1800 if (choices == null) { return; } 1801 1802 for (int i = 0; i < choices.size(); i++) 1803 { 1804 XMLElement choice_el = (XMLElement) choices.elementAt(i); 1805 1806 if (!OsConstraint.oneMatchesCurrentSystem(choice_el)) continue; 1807 1808 String value = choice_el.getAttribute(SEARCH_VALUE); 1809 1810 combobox.addItem(value); 1811 1812 String set = ((XMLElement) choices.elementAt(i)).getAttribute(SET); 1813 if (set != null) 1814 { 1815 if (set != null && !"".equals(set)){ 1816 VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); 1817 set = vs.substitute(set, null); 1818 } 1819 if (set.equals(TRUE)) 1820 { 1821 combobox.setSelectedIndex(i); 1822 } 1823 } 1824 } 1825 } 1826 // ---------------------------------------------------- 1827 // if there is no specification element, return without 1828 // doing anything. 1829 // ---------------------------------------------------- 1830 else 1831 { 1832 return; 1833 } 1834 1835 // ---------------------------------------------------- 1836 // get the description and add it to the list of UI 1837 // elements if it exists. 1838 // ---------------------------------------------------- 1839 element = spec.getFirstChildNamed(DESCRIPTION); 1840 addDescription(element, forPacks, forOs); 1841 1842 TwoColumnConstraints westconstraint1 = new TwoColumnConstraints(); 1843 westconstraint1.position = TwoColumnConstraints.WEST; 1844 1845 uiElements.add(new Object[] { null, FIELD_LABEL, null, westconstraint1, label, forPacks, 1846 forOs}); 1847 1848 TwoColumnConstraints eastconstraint1 = new TwoColumnConstraints(); 1849 eastconstraint1.position = TwoColumnConstraints.EAST; 1850 1851 StringBuffer tooltiptext = new StringBuffer(); 1852 1853 if ((filename != null) && (filename.length() > 0)) 1854 { 1855 tooltiptext.append(MessageFormat.format(parentFrame.langpack 1856 .getString("UserInputPanel.search.location"), new String[] { filename})); 1857 } 1858 1859 boolean showAutodetect = (check_filename != null) && (check_filename.length() > 0); 1860 if (showAutodetect) 1861 { 1862 tooltiptext.append(MessageFormat.format(parentFrame.langpack 1863 .getString("UserInputPanel.search.location.checkedfile"), 1864 new String[] { check_filename})); 1865 } 1866 1867 if (tooltiptext.length() > 0) combobox.setToolTipText(tooltiptext.toString()); 1868 1869 uiElements.add(new Object[] { null, SEARCH_FIELD, variable, eastconstraint1, combobox, 1870 forPacks, forOs}); 1871 1872 JPanel buttonPanel = new JPanel(); 1873 buttonPanel.setLayout(new com.izforge.izpack.gui.FlowLayout( 1874 com.izforge.izpack.gui.FlowLayout.LEADING)); 1875 1876 JButton autodetectButton = ButtonFactory.createButton(parentFrame.langpack 1877 .getString("UserInputPanel.search.autodetect"), idata.buttonsHColor); 1878 autodetectButton.setVisible(showAutodetect); 1879 1880 autodetectButton.setToolTipText(parentFrame.langpack 1881 .getString("UserInputPanel.search.autodetect.tooltip")); 1882 1883 buttonPanel.add(autodetectButton); 1884 1885 JButton browseButton = ButtonFactory.createButton(parentFrame.langpack 1886 .getString("UserInputPanel.search.browse"), idata.buttonsHColor); 1887 1888 buttonPanel.add(browseButton); 1889 1890 TwoColumnConstraints eastonlyconstraint = new TwoColumnConstraints(); 1891 eastonlyconstraint.position = TwoColumnConstraints.EASTONLY; 1892 1893 uiElements.add(new Object[] { null, SEARCH_BUTTON_FIELD, null, eastonlyconstraint, 1894 buttonPanel, forPacks, forOs}); 1895 1896 searchFields.add(new SearchField(filename, check_filename, parentFrame, combobox, 1897 autodetectButton, browseButton, search_type, result_type)); 1898 } 1899 1900 /*--------------------------------------------------------------------------*/ 1901 /** 1902 * Reads the content of the search field and substitutes the associated variable. 1903 * 1904 * @param field the object array that holds the details of the field. 1905 * 1906 * @return <code>true</code> if there was no problem reading the data or if there was an 1907 * irrecovarable problem. If there was a problem that can be corrected by the operator, an error 1908 * dialog is popped up and <code>false</code> is returned. 1909 */ 1910 /*--------------------------------------------------------------------------*/ 1911 private boolean readSearch(Object[] field) 1912 { 1913 String variable = null; 1914 String value = null; 1915 JComboBox comboBox = null; 1916 1917 try 1918 { 1919 variable = (String) field[POS_VARIABLE]; 1920 comboBox = (JComboBox) field[POS_FIELD]; 1921 for (int i = 0; i < this.searchFields.size(); ++i) 1922 { 1923 SearchField sf = (SearchField) this.searchFields.elementAt(i); 1924 if (sf.belongsTo(comboBox)) 1925 { 1926 value = sf.getResult(); 1927 break; 1928 } 1929 } 1930 } 1931 catch (Throwable exception) 1932 { 1933 return (true); 1934 } 1935 if ((variable == null) || (value == null)) { return (true); } 1936 1937 idata.setVariable(variable, value); 1938 entries.add(new TextValuePair(variable, value)); 1939 return (true); 1940 } 1941 1942 /*--------------------------------------------------------------------------*/ 1943 /** 1944 * Adds text to the list of UI elements 1945 * 1946 * @param spec a <code>XMLElement</code> containing the specification for the text. 1947 */ 1948 /*--------------------------------------------------------------------------*/ 1949 private void addText(XMLElement spec) 1950 { 1951 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 1952 Vector forOs = spec.getChildrenNamed(OS); 1953 1954 addDescription(spec, forPacks, forOs); 1955 } 1956 1957 /*--------------------------------------------------------------------------*/ 1958 /** 1959 * Adds a dummy field to the list of UI elements to act as spacer. 1960 * 1961 * @param spec a <code>XMLElement</code> containing other specifications. At present this 1962 * information is not used but might be in future versions. 1963 */ 1964 /*--------------------------------------------------------------------------*/ 1965 private void addSpace(XMLElement spec) 1966 { 1967 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 1968 Vector forOs = spec.getChildrenNamed(OS); 1969 JPanel panel = new JPanel(); 1970 1971 TwoColumnConstraints constraints = new TwoColumnConstraints(); 1972 constraints.position = TwoColumnConstraints.BOTH; 1973 constraints.stretch = true; 1974 1975 uiElements 1976 .add(new Object[] { null, SPACE_FIELD, null, constraints, panel, forPacks, forOs}); 1977 } 1978 1979 /*--------------------------------------------------------------------------*/ 1980 /** 1981 * Adds a dividing line to the list of UI elements act as separator. 1982 * 1983 * @param spec a <code>XMLElement</code> containing additional specifications. 1984 */ 1985 /*--------------------------------------------------------------------------*/ 1986 private void addDivider(XMLElement spec) 1987 { 1988 Vector forPacks = spec.getChildrenNamed(SELECTEDPACKS); 1989 Vector forOs = spec.getChildrenNamed(OS); 1990 JPanel panel = new JPanel(); 1991 String alignment = spec.getAttribute(ALIGNMENT); 1992 1993 if (alignment != null) 1994 { 1995 if (alignment.equals(TOP)) 1996 { 1997 panel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.gray)); 1998 } 1999 else 2000 { 2001 panel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.gray)); 2002 } 2003 } 2004 else 2005 { 2006 panel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.gray)); 2007 } 2008 2009 TwoColumnConstraints constraints = new TwoColumnConstraints(); 2010 constraints.position = TwoColumnConstraints.BOTH; 2011 constraints.stretch = true; 2012 2013 uiElements.add(new Object[] { null, DIVIDER_FIELD, null, constraints, panel, forPacks, 2014 forOs}); 2015 } 2016 2017 /*--------------------------------------------------------------------------*/ 2018 /** 2019 * Adds a description to the list of UI elements. 2020 * 2021 * @param spec a <code>XMLElement</code> containing the specification for the description. 2022 */ 2023 /*--------------------------------------------------------------------------*/ 2024 private void addDescription(XMLElement spec, Vector forPacks, Vector forOs) 2025 { 2026 String description; 2027 TwoColumnConstraints constraints = new TwoColumnConstraints(); 2028 constraints.position = TwoColumnConstraints.BOTH; 2029 constraints.stretch = true; 2030 2031 if (spec != null) 2032 { 2033 description = getText(spec); 2034 2035 // if we have a description, add it to the UI elements 2036 if (description != null) 2037 { 2038 String alignment = spec.getAttribute(ALIGNMENT); 2039 int justify = MultiLineLabel.LEFT; 2040 2041 if (alignment != null) 2042 { 2043 if (alignment.equals(LEFT)) 2044 { 2045 justify = MultiLineLabel.LEFT; 2046 } 2047 else if (alignment.equals(CENTER)) 2048 { 2049 justify = MultiLineLabel.CENTER; 2050 } 2051 else if (alignment.equals(RIGHT)) 2052 { 2053 justify = MultiLineLabel.RIGHT; 2054 } 2055 } 2056 2057 MultiLineLabel label = new MultiLineLabel(description, justify); 2058 2059 uiElements.add(new Object[] { null, DESCRIPTION, null, constraints, label, 2060 forPacks, forOs}); 2061 } 2062 } 2063 } 2064 2065 /*--------------------------------------------------------------------------*/ 2066 /** 2067 * Retrieves the value of a boolean attribute. If the attribute is found and the values equals 2068 * the value of the constant <code>TRUE</code> then true is returned. If it equals 2069 * <code>FALSE</code> the false is returned. In all other cases, including when the attribute 2070 * is not found, the default value is returned. 2071 * 2072 * @param element the <code>XMLElement</code> to search for the attribute. 2073 * @param attribute the attribute to search for 2074 * @param defaultValue the default value to use if the attribute does not exist or a illegal 2075 * value was discovered. 2076 * 2077 * @return <code>true</code> if the attribute is found and the value equals the the constant 2078 * <code>TRUE</code>. <<code> if the 2079 * attribute is <code>FALSE</code>. In all other cases the 2080 * default value is returned. 2081 */ 2082 /*--------------------------------------------------------------------------*/ 2083 private boolean getBoolean(XMLElement element, String attribute, boolean defaultValue) 2084 { 2085 boolean result = defaultValue; 2086 2087 if ((attribute != null) && (attribute.length() > 0)) 2088 { 2089 String value = element.getAttribute(attribute); 2090 2091 if (value != null) 2092 { 2093 if (value.equals(TRUE)) 2094 { 2095 result = true; 2096 } 2097 else if (value.equals(FALSE)) 2098 { 2099 result = false; 2100 } 2101 } 2102 } 2103 2104 return (result); 2105 } 2106 2107 /*--------------------------------------------------------------------------*/ 2108 /** 2109 * Retrieves the value of an integer attribute. If the attribute is not found or the value is 2110 * non-numeric then the default value is returned. 2111 * 2112 * @param element the <code>XMLElement</code> to search for the attribute. 2113 * @param attribute the attribute to search for 2114 * @param defaultValue the default value to use in case the attribute does not exist. 2115 * 2116 * @return the value of the attribute. If the attribute is not found or the content is not a 2117 * legal integer, then the default value is returned. 2118 */ 2119 /*--------------------------------------------------------------------------*/ 2120// private int getInt(XMLElement element, String attribute, int defaultValue) 2121// { 2122// int result = defaultValue; 2123// 2124// if ((attribute != null) && (attribute.length() > 0)) 2125// { 2126// try 2127// { 2128// result = Integer.parseInt(element.getAttribute(attribute)); 2129// } 2130// catch (Throwable exception) 2131// {} 2132// } 2133// 2134// return (result); 2135// } 2136 2137 /*--------------------------------------------------------------------------*/ 2138 /** 2139 * Retrieves the value of a floating point attribute. If the attribute is not found or the value 2140 * is non-numeric then the default value is returned. 2141 * 2142 * @param element the <code>XMLElement</code> to search for the attribute. 2143 * @param attribute the attribute to search for 2144 * @param defaultValue the default value to use in case the attribute does not exist. 2145 * 2146 * @return the value of the attribute. If the attribute is not found or the content is not a 2147 * legal integer, then the default value is returned. 2148 */ 2149 /*--------------------------------------------------------------------------*/ 2150 private float getFloat(XMLElement element, String attribute, float defaultValue) 2151 { 2152 float result = defaultValue; 2153 2154 if ((attribute != null) && (attribute.length() > 0)) 2155 { 2156 try 2157 { 2158 result = Float.parseFloat(element.getAttribute(attribute)); 2159 } 2160 catch (Throwable exception) 2161 {} 2162 } 2163 2164 return (result); 2165 } 2166 2167 /*--------------------------------------------------------------------------*/ 2168 /** 2169 * Extracts the text from an <code>XMLElement</code>. The text must be defined in the 2170 * resource file under the key defined in the <code>id</code> attribute or as value of the 2171 * attribute <code>text</code>. 2172 * 2173 * @param element the <code>XMLElement</code> from which to extract the text. 2174 * 2175 * @return The text defined in the <code>XMLElement</code>. If no text can be located, 2176 * <code>null</code> is returned. 2177 */ 2178 /*--------------------------------------------------------------------------*/ 2179 private String getText(XMLElement element) 2180 { 2181 if (element == null) { return (null); } 2182 2183 String key = element.getAttribute(KEY); 2184 String text = null; 2185 2186 if ((key != null) && (langpack != null)) 2187 { 2188 try 2189 { 2190 text = langpack.getString(key); 2191 } 2192 catch (Throwable exception) 2193 { 2194 text = null; 2195 } 2196 } 2197 2198 // if there is no text in the description, then 2199 // we were unable to retrieve it form the resource. 2200 // In this case try to get the text directly from 2201 // the XMLElement 2202 if (text == null) 2203 { 2204 text = element.getAttribute(TEXT); 2205 } 2206 2207 return (text); 2208 } 2209 2210 /*--------------------------------------------------------------------------*/ 2211 /** 2212 * Retreives the alignment setting for the <code>XMLElement</code>. The default value in case 2213 * the <code>ALIGNMENT</code> attribute is not found or the value is illegal is 2214 * <code>TwoColumnConstraints.LEFT</code>. 2215 * 2216 * @param element the <code>XMLElement</code> from which to extract the alignment setting. 2217 * 2218 * @return the alignement setting for the <code>XMLElement</code>. The value is either 2219 * <code>TwoColumnConstraints.LEFT</code>, <code>TwoColumnConstraints.CENTER</code> or 2220 * <code>TwoColumnConstraints.RIGHT</code>. 2221 * 2222 * @see com.izforge.izpack.gui.TwoColumnConstraints 2223 */ 2224 /*--------------------------------------------------------------------------*/ 2225 private int getAlignment(XMLElement element) 2226 { 2227 int result = TwoColumnConstraints.LEFT; 2228 2229 String value = element.getAttribute(ALIGNMENT); 2230 2231 if (value != null) 2232 { 2233 if (value.equals(LEFT)) 2234 { 2235 result = TwoColumnConstraints.LEFT; 2236 } 2237 else if (value.equals(CENTER)) 2238 { 2239 result = TwoColumnConstraints.CENTER; 2240 } 2241 else if (value.equals(RIGHT)) 2242 { 2243 result = TwoColumnConstraints.RIGHT; 2244 } 2245 } 2246 2247 return (result); 2248 } 2249 2250 /** 2251 * Verifies if an item is required for the operating system the installer executed. The 2252 * configuration for this feature is: <br/> <os family="unix"/> <br> 2253 * <br> 2254 * <b>Note:</b><br> 2255 * If the list of the os is empty then <code>true</code> is always returnd. 2256 * 2257 * @param os The <code>Vector</code> of <code>String</code>s. containing the os names 2258 * 2259 * @return <code>true</code> if the item is required for the os, otherwise returns 2260 * <code>false</code>. 2261 */ 2262 public boolean itemRequiredForOs(Vector os) 2263 { 2264 if (os.size() == 0) { return true; } 2265 2266 for (int i = 0; i < os.size(); i++) 2267 { 2268 String family = ((XMLElement) os.elementAt(i)).getAttribute(FAMILY); 2269 boolean match = false; 2270 2271 if (family.equals("windows")) 2272 { 2273 match = OsVersion.IS_WINDOWS; 2274 } 2275 else if (family.equals("mac")) 2276 { 2277 match = OsVersion.IS_OSX; 2278 } 2279 else if (family.equals("unix")) 2280 { 2281 match = OsVersion.IS_UNIX; 2282 } 2283 return match; 2284 } 2285 return false; 2286 } 2287 2288 /*--------------------------------------------------------------------------*/ 2289 /** 2290 * Verifies if an item is required for any of the packs listed. An item is required for a pack 2291 * in the list if that pack is actually selected for installation. <br> 2292 * <br> 2293 * <b>Note:</b><br> 2294 * If the list of selected packs is empty then <code>true</code> is always returnd. The same 2295 * is true if the <code>packs</code> list is empty. 2296 * 2297 * @param packs a <code>Vector</code> of <code>String</code>s. Each of the strings denotes 2298 * a pack for which an item should be created if the pack is actually installed. 2299 * 2300 * @return <code>true</code> if the item is required for at least one pack in the list, 2301 * otherwise returns <code>false</code>. 2302 */ 2303 /*--------------------------------------------------------------------------*/ 2304 /* 2305 * $ @design 2306 * 2307 * The information about the installed packs comes from InstallData.selectedPacks. This assumes 2308 * that this panel is presented to the user AFTER the PacksPanel. 2309 * -------------------------------------------------------------------------- 2310 */ 2311 private boolean itemRequiredFor(Vector packs) 2312 { 2313 2314 String selected; 2315 String required; 2316 2317 if (packs.size() == 0) { return (true); } 2318 2319 // ---------------------------------------------------- 2320 // We are getting to this point if any packs have been 2321 // specified. This means that there is a possibility 2322 // that some UI elements will not get added. This 2323 // means that we can not allow to go back to the 2324 // PacksPanel, because the process of building the 2325 // UI is not reversable. 2326 // ---------------------------------------------------- 2327 // packsDefined = true; 2328 2329 // ---------------------------------------------------- 2330 // analyze if the any of the packs for which the item 2331 // is required have been selected for installation. 2332 // ---------------------------------------------------- 2333 for (int i = 0; i < idata.selectedPacks.size(); i++) 2334 { 2335 selected = ((Pack) idata.selectedPacks.get(i)).name; 2336 2337 for (int k = 0; k < packs.size(); k++) 2338 { 2339 required = (String) ((XMLElement) packs.elementAt(k)).getAttribute(NAME, ""); 2340 if (selected.equals(required)) { return (true); } 2341 } 2342 } 2343 2344 return (false); 2345 } 2346 2347 /*--------------------------------------------------------------------------*/ 2348 /** 2349 * Verifies if an item is required for any of the packs listed. An item is required for a pack 2350 * in the list if that pack is actually NOT selected for installation. <br> 2351 * <br> 2352 * <b>Note:</b><br> 2353 * If the list of selected packs is empty then <code>true</code> is always returnd. The same 2354 * is true if the <code>packs</code> list is empty. 2355 * 2356 * @param packs a <code>Vector</code> of <code>String</code>s. Each of the strings denotes 2357 * a pack for which an item should be created if the pack is actually installed. 2358 * 2359 * @return <code>true</code> if the item is required for at least one pack in the list, 2360 * otherwise returns <code>false</code>. 2361 */ 2362 /*--------------------------------------------------------------------------*/ 2363 /* 2364 * $ @design 2365 * 2366 * The information about the installed packs comes from InstallData.selectedPacks. This assumes 2367 * that this panel is presented to the user AFTER the PacksPanel. 2368 * -------------------------------------------------------------------------- 2369 */ 2370 private boolean itemRequiredForUnselected(Vector packs) 2371 { 2372 2373 String selected; 2374 String required; 2375 2376 if (packs.size() == 0) { return (true); } 2377 2378 // ---------------------------------------------------- 2379 // analyze if the any of the packs for which the item 2380 // is required have been selected for installation. 2381 // ---------------------------------------------------- 2382 for (int i = 0; i < idata.selectedPacks.size(); i++) 2383 { 2384 selected = ((Pack) idata.selectedPacks.get(i)).name; 2385 2386 for (int k = 0; k < packs.size(); k++) 2387 { 2388 required = (String) ((XMLElement) packs.elementAt(k)).getAttribute(NAME, ""); 2389 if (selected.equals(required)) { return (false); } 2390 } 2391 } 2392 2393 return (true); 2394 } 2395 2396 // ----------- Inheritance stuff ----------------------------------------- 2397 /** 2398 * Returns the uiElements. 2399 * 2400 * @return Returns the uiElements. 2401 */ 2402 protected Vector getUiElements() 2403 { 2404 return uiElements; 2405 } 2406 2407 // -------------------------------------------------------------------------- 2408 // Inner Classes 2409 // -------------------------------------------------------------------------- 2410 2411 /*---------------------------------------------------------------------------*/ 2412 /** 2413 * This class can be used to associate a text string and a (text) value. 2414 */ 2415 /*---------------------------------------------------------------------------*/ 2416 private static class TextValuePair 2417 { 2418 2419 private String text = ""; 2420 2421 private String value = ""; 2422 2423 /*--------------------------------------------------------------------------*/ 2424 /** 2425 * Constructs a new Text/Value pair, initialized with the text and a value. 2426 * 2427 * @param text the text that this object should represent 2428 * @param value the value that should be associated with this object 2429 */ 2430 /*--------------------------------------------------------------------------*/ 2431 public TextValuePair(String text, String value) 2432 { 2433 this.text = text; 2434 this.value = value; 2435 } 2436 2437 /*--------------------------------------------------------------------------*/ 2438 /** 2439 * Sets the text 2440 * 2441 * @param text the text for this object 2442 */ 2443 /*--------------------------------------------------------------------------*/ 2444 public void setText(String text) 2445 { 2446 this.text = text; 2447 } 2448 2449 /*--------------------------------------------------------------------------*/ 2450 /** 2451 * Sets the value of this object 2452 * 2453 * @param value the value for this object 2454 */ 2455 /*--------------------------------------------------------------------------*/ 2456 public void setValue(String value) 2457 { 2458 this.value = value; 2459 } 2460 2461 /*--------------------------------------------------------------------------*/ 2462 /** 2463 * This method returns the text that was set for the object 2464 * 2465 * @return the object's text 2466 */ 2467 /*--------------------------------------------------------------------------*/ 2468 public String toString() 2469 { 2470 return (text); 2471 } 2472 2473 /*--------------------------------------------------------------------------*/ 2474 /** 2475 * This method returns the value that was associated with this object 2476 * 2477 * @return the object's value 2478 */ 2479 /*--------------------------------------------------------------------------*/ 2480 public String getValue() 2481 { 2482 return (value); 2483 } 2484 } 2485 2486 /*---------------------------------------------------------------------------*/ 2487 /** 2488 * This class encapsulates a lot of search field functionality. 2489 * 2490 * A search field supports searching directories and files on the target system. This is a 2491 * helper class to manage all data belonging to a search field. 2492 */ 2493 /*---------------------------------------------------------------------------*/ 2494 2495 private class SearchField implements ActionListener 2496 { 2497 2498 /** used in constructor - we search for a directory. */ 2499 public static final int TYPE_DIRECTORY = 1; 2500 2501 /** used in constructor - we search for a file. */ 2502 public static final int TYPE_FILE = 2; 2503 2504 /** used in constructor - result of search is the directory. */ 2505 public static final int RESULT_DIRECTORY = 1; 2506 2507 /** used in constructor - result of search is the whole file name. */ 2508 public static final int RESULT_FILE = 2; 2509 2510 /** used in constructor - result of search is the parent directory. */ 2511 public static final int RESULT_PARENTDIR = 3; 2512 2513 private String filename = null; 2514 2515 private String checkFilename = null; 2516 2517 private JButton autodetectButton = null; 2518 2519 private JButton browseButton = null; 2520 2521 private JComboBox pathComboBox = null; 2522 2523 private int searchType = TYPE_DIRECTORY; 2524 2525 private int resultType = RESULT_DIRECTORY; 2526 2527 private InstallerFrame parent = null; 2528 2529 /*---------------------------------------------------------------------------*/ 2530 /** 2531 * Constructor - initializes the object, adds it as action listener to the "autodetect" 2532 * button. 2533 * 2534 * @param filename the name of the file to search for (might be null for searching 2535 * directories) 2536 * @param checkFilename the name of the file to check when searching for directories (the 2537 * checkFilename is appended to a found directory to figure out whether it is the right 2538 * directory) 2539 * @param combobox the <code>JComboBox</code> holding the list of choices; it should be 2540 * editable and contain only Strings 2541 * @param autobutton the autodetection button for triggering autodetection 2542 * @param browsebutton the browse button to look for the file 2543 * @param search_type what to search for - TYPE_FILE or TYPE_DIRECTORY 2544 * @param result_type what to return as the result - RESULT_FILE or RESULT_DIRECTORY or 2545 * RESULT_PARENTDIR 2546 */ 2547 /*---------------------------------------------------------------------------*/ 2548 public SearchField(String filename, String checkFilename, InstallerFrame parent, 2549 JComboBox combobox, JButton autobutton, JButton browsebutton, int search_type, 2550 int result_type) 2551 { 2552 this.filename = filename; 2553 this.checkFilename = checkFilename; 2554 this.parent = parent; 2555 this.autodetectButton = autobutton; 2556 this.browseButton = browsebutton; 2557 this.pathComboBox = combobox; 2558 this.searchType = search_type; 2559 this.resultType = result_type; 2560 2561 this.autodetectButton.addActionListener(this); 2562 this.browseButton.addActionListener(this); 2563 2564 autodetect(); 2565 } 2566 2567 /** 2568 * Check whether the given combobox belongs to this searchfield. This is used when reading 2569 * the results. 2570 */ 2571 public boolean belongsTo(JComboBox combobox) 2572 { 2573 return (this.pathComboBox == combobox); 2574 } 2575 2576 /** check whether the given path matches */ 2577 private boolean pathMatches(String path) 2578 { 2579 if (path != null) 2580 { // Make sure, path is not null 2581 // System.out.println ("checking path " + path); 2582 2583 File file = null; 2584 2585 if ((this.filename == null) || (this.searchType == TYPE_DIRECTORY)) 2586 { 2587 file = new File(path); 2588 } 2589 else 2590 { 2591 file = new File(path, this.filename); 2592 } 2593 2594 if (file.exists()) 2595 { 2596 2597 if (((this.searchType == TYPE_DIRECTORY) && (file.isDirectory())) 2598 || ((this.searchType == TYPE_FILE) && (file.isFile()))) 2599 { 2600 // no file to check for 2601 if (this.checkFilename == null) return true; 2602 2603 file = new File(file, this.checkFilename); 2604 2605 return file.exists(); 2606 } 2607 2608 } 2609 2610 // System.out.println (path + " did not match"); 2611 } // end if 2612 return false; 2613 } 2614 2615 /** perform autodetection */ 2616 public boolean autodetect() 2617 { 2618 Vector items = new Vector(); 2619 2620 /* 2621 * Check if the user has entered data into the ComboBox and add it to the Itemlist 2622 */ 2623 String selected = (String) this.pathComboBox.getSelectedItem(); 2624 boolean found = false; 2625 for (int x = 0; x < this.pathComboBox.getItemCount(); x++) 2626 { 2627 if (((String) this.pathComboBox.getItemAt(x)).equals(selected)) 2628 { 2629 found = true; 2630 } 2631 } 2632 if (!found) 2633 { 2634 // System.out.println("Not found in Itemlist"); 2635 this.pathComboBox.addItem(this.pathComboBox.getSelectedItem()); 2636 } 2637 2638 // Checks whether a placeholder item is in the combobox 2639 // and resolve the pathes automatically: 2640 // /usr/lib/* searches all folders in usr/lib to find 2641 // /usr/lib/*/lib/tools.jar 2642 for (int i = 0; i < this.pathComboBox.getItemCount(); ++i) 2643 { 2644 String path = (String) this.pathComboBox.getItemAt(i); 2645 2646 if (path.endsWith("*")) 2647 { 2648 path = path.substring(0, path.length() - 1); 2649 File dir = new File(path); 2650 2651 if (dir.isDirectory()) 2652 { 2653 File[] subdirs = dir.listFiles(); 2654 for (int x = 0; x < subdirs.length; x++) 2655 { 2656 String search = subdirs[x].getAbsolutePath(); 2657 if (this.pathMatches(search)) 2658 { 2659 items.add(search); 2660 } 2661 } 2662 } 2663 } 2664 else 2665 { 2666 if (this.pathMatches(path)) 2667 { 2668 items.add(path); 2669 } 2670 } 2671 } 2672 // Make the enties in the vector unique 2673 items = new Vector(new HashSet(items)); 2674 2675 // Now clear the combobox and add the items out of the newly 2676 // generated vector 2677 this.pathComboBox.removeAllItems(); 2678 VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); 2679 for (int i = 0; i < items.size(); i++) 2680 { 2681 this.pathComboBox.addItem(vs.substitute((String) items.get(i), "plain")); 2682 } 2683 2684 // loop through all items 2685 for (int i = 0; i < this.pathComboBox.getItemCount(); ++i) 2686 { 2687 String path = (String) this.pathComboBox.getItemAt(i); 2688 2689 if (this.pathMatches(path)) 2690 { 2691 this.pathComboBox.setSelectedIndex(i); 2692 return true; 2693 } 2694 2695 } 2696 2697 // if the user entered something else, it's not listed as an item 2698 if (this.pathMatches((String) this.pathComboBox.getSelectedItem())) { return true; } 2699 2700 return false; 2701 } 2702 2703 /*--------------------------------------------------------------------------*/ 2704 /** 2705 * This is called if one of the buttons has bee pressed. 2706 * 2707 * It checks, which button caused the action and acts accordingly. 2708 */ 2709 /*--------------------------------------------------------------------------*/ 2710 public void actionPerformed(ActionEvent event) 2711 { 2712 // System.out.println ("autodetection button pressed."); 2713 2714 if (event.getSource() == this.autodetectButton) 2715 { 2716 if (!autodetect()) 2717 JOptionPane.showMessageDialog(parent, parent.langpack 2718 .getString("UserInputPanel.search.autodetect.failed.message"), 2719 parent.langpack 2720 .getString("UserInputPanel.search.autodetect.failed.caption"), 2721 JOptionPane.WARNING_MESSAGE); 2722 } 2723 else if (event.getSource() == this.browseButton) 2724 { 2725 JFileChooser chooser = new JFileChooser(); 2726 2727 if (this.searchType == RESULT_DIRECTORY) 2728 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 2729 2730 int result = chooser.showOpenDialog(this.parent); 2731 2732 if (result == JFileChooser.APPROVE_OPTION) 2733 { 2734 File f = chooser.getSelectedFile(); 2735 2736 this.pathComboBox.setSelectedItem(f.getAbsolutePath()); 2737 2738 // use any given directory directly 2739 if (!this.pathMatches(f.getAbsolutePath())) 2740 { 2741 JOptionPane.showMessageDialog(parent, parent.langpack 2742 .getString("UserInputPanel.search.wrongselection.message"), 2743 parent.langpack 2744 .getString("UserInputPanel.search.wrongselection.caption"), 2745 JOptionPane.WARNING_MESSAGE); 2746 } 2747 } 2748 2749 } 2750 2751 // we don't care for anything more here - getResult() does the rest 2752 } 2753 2754 /*--------------------------------------------------------------------------*/ 2755 /** 2756 * Return the result of the search according to result type. 2757 * 2758 * Sometimes, the whole path of the file is wanted, sometimes only the directory where the 2759 * file is in, sometimes the parent directory. 2760 * 2761 * @return null on error 2762 */ 2763 /*--------------------------------------------------------------------------*/ 2764 public String getResult() 2765 { 2766 String item = (String) this.pathComboBox.getSelectedItem(); 2767 if (item != null) item = item.trim(); 2768 String path = item; 2769 2770 File f = new File(item); 2771 2772 if (!f.isDirectory()) 2773 { 2774 path = f.getParent(); 2775 } 2776 2777 // path now contains the final content of the combo box 2778 if (this.resultType == RESULT_DIRECTORY) 2779 { 2780 return path; 2781 } 2782 else if (this.resultType == RESULT_FILE) 2783 { 2784 if (this.filename != null) 2785 { 2786 return path + File.separatorChar + this.filename; 2787 } 2788 else 2789 { 2790 return item; 2791 } 2792 } 2793 else if (this.resultType == RESULT_PARENTDIR) 2794 { 2795 File dir = new File(path); 2796 return dir.getParent(); 2797 } 2798 2799 return null; 2800 } 2801 2802 } // private class SearchFile 2803 2804} // public class UserInputPanel 2805/*---------------------------------------------------------------------------*/ 2806