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"); you may not use this file except 010 * in compliance with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software distributed under the License 015 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 016 * or implied. See the License for the specific language governing permissions and limitations under 017 * the License. 018 */ 019 020package com.izforge.izpack.panels; 021 022import java.awt.Dimension; 023import java.awt.GridBagConstraints; 024import java.awt.GridBagLayout; 025import java.awt.GridLayout; 026import java.awt.Insets; 027import java.awt.event.ActionEvent; 028import java.awt.event.ActionListener; 029import java.io.File; 030import java.io.FileWriter; 031import java.io.InputStream; 032import java.util.ArrayList; 033import java.util.Iterator; 034import java.util.Vector; 035 036import javax.swing.ButtonGroup; 037import javax.swing.JButton; 038import javax.swing.JCheckBox; 039import javax.swing.JFileChooser; 040import javax.swing.JLabel; 041import javax.swing.JList; 042import javax.swing.JPanel; 043import javax.swing.JRadioButton; 044import javax.swing.JScrollPane; 045import javax.swing.JTextField; 046import javax.swing.ListSelectionModel; 047import javax.swing.border.Border; 048import javax.swing.border.EmptyBorder; 049import javax.swing.border.TitledBorder; 050import javax.swing.event.ListSelectionEvent; 051import javax.swing.event.ListSelectionListener; 052 053import net.n3.nanoxml.NonValidator; 054import net.n3.nanoxml.StdXMLBuilder; 055import net.n3.nanoxml.StdXMLParser; 056import net.n3.nanoxml.StdXMLReader; 057import net.n3.nanoxml.XMLElement; 058 059import com.izforge.izpack.ExecutableFile; 060import com.izforge.izpack.Pack; 061import com.izforge.izpack.gui.ButtonFactory; 062import com.izforge.izpack.gui.LabelFactory; 063import com.izforge.izpack.installer.InstallData; 064import com.izforge.izpack.installer.InstallerFrame; 065import com.izforge.izpack.installer.IzPanel; 066import com.izforge.izpack.installer.ResourceNotFoundException; 067import com.izforge.izpack.installer.UninstallData; 068import com.izforge.izpack.util.FileExecutor; 069import com.izforge.izpack.util.MultiLineLabel; 070import com.izforge.izpack.util.OsConstraint; 071import com.izforge.izpack.util.OsVersion; 072import com.izforge.izpack.util.StringTool; 073import com.izforge.izpack.util.TargetFactory; 074import com.izforge.izpack.util.UnixHelper; 075import com.izforge.izpack.util.VariableSubstitutor; 076import com.izforge.izpack.util.os.Shortcut; 077 078// 079//import com.izforge.izpack.panels.ShortcutData; 080 081/*---------------------------------------------------------------------------*/ 082 083/** 084 * This class implements a panel for the creation of shortcuts. The panel prompts the user to select 085 * a program group for shortcuts, accept the creation of desktop shortcuts and actually creates the 086 * shortcuts. 087 * 088 * <h4>Important</h4> 089 * It is neccesary that the installation has been completed before this panel is called. To 090 * successfully create shortcuts this panel needs to have the following in place: <br> 091 * <br> 092 * 093 * <ul> 094 * <li>the launcher files that the shortcuts point to must exist</li> 095 * <li>it must be known which packs are installed</li> 096 * <li>where the launcher for the uninstaller is located</li> 097 * </ul> 098 * 099 * It is ok to present other panels after this one, as long as these conditions are met. 100 * 101 * @author Elmar Grom 102 * @version 0.0.1 / 2/26/02 103 * 104 * @see com.izforge.izpack.util.os.ShellLink 105 * 106 * @version 0.0.1 / 2/26/02 107 * @author Elmar Grom 108 */ 109 110/*---------------------------------------------------------------------------*/ 111 112// !!! To Do ! 113// 114// - see if I can't get multiple instances of the shortcut to work 115// - need a clean way to get pack name 116public class ShortcutPanel extends IzPanel implements ActionListener, ListSelectionListener 117{ 118 /** 119 * 120 */ 121 private static final long serialVersionUID = 3256722870838112311L; 122 123 /** a VectorList of Files wich should be make executable */ 124 private Vector execFiles = new Vector(); 125 126 /** SPEC_ATTRIBUTE_KDE_SUBST_UID = "KdeSubstUID" */ 127 private final static String SPEC_ATTRIBUTE_KDE_SUBST_UID = "KdeSubstUID"; 128 129 /** SPEC_ATTRIBUTE_URL = "url" */ 130 private final static String SPEC_ATTRIBUTE_URL = "url"; 131 132 /** SPEC_ATTRIBUTE_TYPE = "type" */ 133 private final static String SPEC_ATTRIBUTE_TYPE = "type"; 134 135 /** SPEC_ATTRIBUTE_TERMINAL_OPTIONS = "terminalOptions" */ 136 private final static String SPEC_ATTRIBUTE_TERMINAL_OPTIONS = "terminalOptions"; 137 138 /** SPEC_ATTRIBUTE_TERMINAL = "terminal" */ 139 private final static String SPEC_ATTRIBUTE_TERMINAL = "terminal"; 140 141 /** SPEC_ATTRIBUTE_MIMETYPE = "mimetype" */ 142 private final static String SPEC_ATTRIBUTE_MIMETYPE = "mimetype"; 143 144 /** SPEC_ATTRIBUTE_ENCODING = "encoding" */ 145 private final static String SPEC_ATTRIBUTE_ENCODING = "encoding"; 146 147 /** LOCATION_APPLICATIONS=applications */ 148 private static final String LOCATION_APPLICATIONS = "applications"; 149 150 /** LOCATION_START_MENU = "startMenu" */ 151 private static final String LOCATION_START_MENU = "startMenu"; 152 153 /** 154 * SEPARATOR_LINE = 155 * "--------------------------------------------------------------------------------"; 156 */ 157 private static final String SEPARATOR_LINE = "--------------------------------------------------------------------------------"; 158 159 /** 160 * The default file name for the text file in which the shortcut information should be stored, 161 * in case shortcuts can not be created on a particular target system. TEXT_FILE_NAME = 162 * "Shortcuts.txt" 163 */ 164 private static final String TEXT_FILE_NAME = "Shortcuts.txt"; 165 166 /** The name of the XML file that specifies the shortcuts SPEC_FILE_NAME = "shortcutSpec.xml"; */ 167 private static final String SPEC_FILE_NAME = "shortcutSpec.xml"; 168 169 // ------------------------------------------------------ 170 // spec file section keys 171 // ------------------------------------------------------ 172 private static final String SPEC_KEY_SKIP_IFNOT_SUPPORTED = "skipIfNotSupported"; 173 174 /** SPEC_KEY_NOT_SUPPORTED = "notSupported" */ 175 private static final String SPEC_KEY_NOT_SUPPORTED = "notSupported"; 176 177 /** SPEC_KEY_PROGRAM_GROUP = "programGroup" */ 178 private static final String SPEC_KEY_PROGRAM_GROUP = "programGroup"; 179 180 /** SPEC_KEY_SHORTCUT = "shortcut" */ 181 private static final String SPEC_KEY_SHORTCUT = "shortcut"; 182 183 /** SPEC_KEY_PACKS = "createForPack" */ 184 private static final String SPEC_KEY_PACKS = "createForPack"; 185 186 // ------------------------------------------------------ 187 // spec file key attributes 188 // ------------------------------------------------------ 189 190 /** SPEC_ATTRIBUTE_DEFAULT_GROUP = "defaultName" */ 191 private static final String SPEC_ATTRIBUTE_DEFAULT_GROUP = "defaultName"; 192 193 /** SPEC_ATTRIBUTE_LOCATION = "location" */ 194 private static final String SPEC_ATTRIBUTE_LOCATION = "location"; 195 196 /** SPEC_ATTRIBUTE_NAME = "name" */ 197 private static final String SPEC_ATTRIBUTE_NAME = "name"; 198 199 /** SPEC_ATTRIBUTE_SUBGROUP = "subgroup" */ 200 private static final String SPEC_ATTRIBUTE_SUBGROUP = "subgroup"; 201 202 /** SPEC_ATTRIBUTE_DESCRIPTION = "description" */ 203 private static final String SPEC_ATTRIBUTE_DESCRIPTION = "description"; 204 205 /** SPEC_ATTRIBUTE_TARGET = "target" */ 206 private static final String SPEC_ATTRIBUTE_TARGET = "target"; 207 208 /** SPEC_ATTRIBUTE_COMMAND = "commandLine" */ 209 private static final String SPEC_ATTRIBUTE_COMMAND = "commandLine"; 210 211 /** SPEC_ATTRIBUTE_ICON "iconFile" */ 212 private static final String SPEC_ATTRIBUTE_ICON = "iconFile"; 213 214 /** SPEC_ATTRIBUTE_ICON_INDEX "iconIndex" */ 215 private static final String SPEC_ATTRIBUTE_ICON_INDEX = "iconIndex"; 216 217 /** SPEC_ATTRIBUTE_WORKING_DIR = "workingDirectory" */ 218 private static final String SPEC_ATTRIBUTE_WORKING_DIR = "workingDirectory"; 219 220 /** SPEC_ATTRIBUTE_INITIAL_STATE = "initialState" */ 221 private static final String SPEC_ATTRIBUTE_INITIAL_STATE = "initialState"; 222 223 /** SPEC_ATTRIBUTE_DESKTOP = "desktop" */ 224 private static final String SPEC_ATTRIBUTE_DESKTOP = "desktop"; 225 226 /** SPEC_ATTRIBUTE_APPLICATIONS = "applications" */ 227 private static final String SPEC_ATTRIBUTE_APPLICATIONS = "applications"; 228 229 /** SPEC_ATTRIBUTE_START_MENU = "startMenu" */ 230 private static final String SPEC_ATTRIBUTE_START_MENU = "startMenu"; 231 232 /** SPEC_ATTRIBUTE_STARTUP = "startup" */ 233 private static final String SPEC_ATTRIBUTE_STARTUP = "startup"; 234 235 /** SPEC_ATTRIBUTE_PROGRAM_GROUP = "programGroup" */ 236 private static final String SPEC_ATTRIBUTE_PROGRAM_GROUP = "programGroup"; 237 238 // ------------------------------------------------------ 239 // spec file attribute values 240 // ------------------------------------------------------ 241 242 /** SPEC_VALUE_APPLICATIONS = "applications" */ 243 private static final String SPEC_VALUE_APPLICATIONS = "applications"; 244 245 /** SPEC_VALUE_START_MENU = "startMenu" */ 246 private static final String SPEC_VALUE_START_MENU = "startMenu"; 247 248 /** SPEC_VALUE_NO_SHOW = "noShow" */ 249 private static final String SPEC_VALUE_NO_SHOW = "noShow"; 250 251 /** SPEC_VALUE_NORMAL = "normal" */ 252 private static final String SPEC_VALUE_NORMAL = "normal"; 253 254 /** SPEC_VALUE_MAXIMIZED = "maximized" */ 255 private static final String SPEC_VALUE_MAXIMIZED = "maximized"; 256 257 /** SPEC_VALUE_MINIMIZED = "minimized" */ 258 private static final String SPEC_VALUE_MINIMIZED = "minimized"; 259 260 // ------------------------------------------------------ 261 // automatic script section keys 262 // ------------------------------------------------------ 263 264 /** */ 265 266 /** AUTO_KEY_PROGRAM_GROUP = "programGroup" */ 267 private static final String AUTO_KEY_PROGRAM_GROUP = "programGroup"; 268 269 /** AUTO_KEY_SHORTCUT = "shortcut" */ 270 private static final String AUTO_KEY_SHORTCUT = "shortcut"; 271 272 // ------------------------------------------------------ 273 // automatic script keys attributes 274 // ------------------------------------------------------ 275 276 /** AUTO_ATTRIBUTE_NAME = "name" */ 277 private static final String AUTO_ATTRIBUTE_NAME = "name"; 278 279 /** AUTO_ATTRIBUTE_GROUP = "group" */ 280 private static final String AUTO_ATTRIBUTE_GROUP = "group"; 281 282 /** AUTO_ATTRIBUTE_TYPE "type" */ 283 private static final String AUTO_ATTRIBUTE_TYPE = "type"; 284 285 /** AUTO_ATTRIBUTE_COMMAND = "commandLine" */ 286 private static final String AUTO_ATTRIBUTE_COMMAND = "commandLine"; 287 288 /** AUTO_ATTRIBUTE_DESCRIPTION = "description" */ 289 private static final String AUTO_ATTRIBUTE_DESCRIPTION = "description"; 290 291 /** AUTO_ATTRIBUTE_ICON = "icon" */ 292 private static final String AUTO_ATTRIBUTE_ICON = "icon"; 293 294 /** AUTO_ATTRIBUTE_ICON_INDEX = "iconIndex" */ 295 private static final String AUTO_ATTRIBUTE_ICON_INDEX = "iconIndex"; 296 297 /** AUTO_ATTRIBUTE_INITIAL_STATE = "initialState" */ 298 private static final String AUTO_ATTRIBUTE_INITIAL_STATE = "initialState"; 299 300 /** AUTO_ATTRIBUTE_TARGET = "target" */ 301 private static final String AUTO_ATTRIBUTE_TARGET = "target"; 302 303 /** AUTO_ATTRIBUTE_WORKING_DIR = "workingDirectory" */ 304 private static final String AUTO_ATTRIBUTE_WORKING_DIR = "workingDirectory"; 305 306 // permission flags 307 private static final String CREATE_FOR_ALL = "createForAll"; 308 309 // ------------------------------------------------------------------------ 310 // Variable Declarations 311 // ------------------------------------------------------------------------ 312 313 /** UI element to label the list of existing program groups */ 314 private JLabel listLabel; 315 316 /** UI element to present the list of existing program groups for selection */ 317 private JList groupList; 318 319 /** UI element for listing the intended shortcut targets */ 320 private JList targetList; 321 322 /** 323 * UI element to present the default name for the program group and to support editing of this 324 * name. 325 */ 326 private JTextField programGroup; 327 328 /** 329 * UI element to allow the user to revert to the default name of the program group 330 */ 331 private JButton defaultButton; 332 333 /** 334 * UI element to allow the user to save a text file with the shortcut information 335 */ 336 private JButton saveButton; 337 338 /** 339 * UI element to allow the user to decide if shortcuts should be placed on the desktop or not. 340 */ 341 private JCheckBox allowDesktopShortcut; 342 343 private JCheckBox createShortcuts; 344 345 /** 346 * UI element instruct this panel to create shortcuts for the current user only 347 */ 348 private JRadioButton currentUser; 349 350 /** UI element instruct this panel to create shortcuts for all users */ 351 private JRadioButton allUsers; 352 353 /** The layout for this panel */ 354 private GridBagLayout layout; 355 356 /** The contraints object to use whan creating the layout */ 357 private GridBagConstraints constraints; 358 359 /** 360 * The default name to use for the program group. This comes from the XML specification. 361 */ 362 private String suggestedProgramGroup; 363 364 /** The name chosen by the user for the program group, */ 365 private String groupName; 366 367 /** 368 * The location for placign the program group. This is the same as the location (type) of a 369 * shortcut, only that it applies to the program group. Note that there are only two locations 370 * that make sense as location for a program group: <br> 371 * 372 * <ul> 373 * <li>applications</li> 374 * <li>start manu</li> 375 * </ul> 376 * 377 */ 378 private int groupLocation; 379 380 /** The parsed result from reading the XML specification from the file */ 381 private XMLElement spec; 382 383 /** 384 * Set to <code>true</code> by <code>analyzeShortcutSpec()</code> if there are any desktop 385 * shortcuts to create. 386 */ 387 private boolean hasDesktopShortcuts = false; 388 389 /** Tells wether to skip if the platform is not supported. */ 390 private boolean skipIfNotSupported = false; 391 392 /** the one shortcut instance for reuse in many locations */ 393 private Shortcut shortcut; 394 395 /** 396 * A list of <code>ShortcutData</code> objects. Each object is the complete specification for 397 * one shortcut that must be created. 398 */ 399 private Vector shortcuts = new Vector(); 400 401 /** 402 * Holds a list of all the shortcut files that have been created. <b>Note: </b> this variable 403 * contains valid data only after <code>createShortcuts()</code> has been called. This list is 404 * created so that the files can be added to the uninstaller. 405 */ 406 private Vector files = new Vector(); 407 408 /** 409 * If <code>true</code> it indicates that there are shortcuts to create. The value is set by 410 * <code>analyzeShortcutSpec()</code> 411 */ 412 private boolean shortcutsToCreate = false; 413 414 /** 415 * If <code>true</code> it indicates that the spec file is existing and could be read. 416 */ 417 private boolean haveShortcutSpec = false; 418 419 /** 420 * This is set to true if the shortcut spec instructs to simulate running on an operating system 421 * that is not supported. 422 */ 423 private boolean simulteNotSupported = false; 424 425 /** 426 * Avoids bogus behaviour when the user goes back then returns to this panel. 427 */ 428 private boolean firstTime = true; 429 430 private File itsProgramFolder; 431 432 private int itsUserType; 433 434 static boolean create; 435 436 private static boolean isRootUser; 437 438 /* 439 * -------------------------------------------------------------------------- 440 */ 441 /** 442 * Constructor. 443 * 444 * @param parent reference to the application frame 445 * @param installData shared information about the installation 446 */ 447 /* 448 * -------------------------------------------------------------------------- 449 */ 450 public ShortcutPanel(InstallerFrame parent, InstallData installData) 451 { 452 super(parent, installData, "link16x16"); 453 454 try 455 { 456 readShortcutSpec(); 457 } 458 catch (Throwable exception) 459 { 460 System.out.println("could not read shortcut spec!"); 461 exception.printStackTrace(); 462 } 463 464 layout = new GridBagLayout(); 465 constraints = new GridBagConstraints(); 466 setLayout(layout); 467 468 // Create the UI elements 469 try 470 { 471 shortcut = (Shortcut) (TargetFactory.getInstance() 472 .makeObject("com.izforge.izpack.util.os.Shortcut")); 473 shortcut.initialize(Shortcut.APPLICATIONS, "-"); 474 } 475 catch (Throwable exception) 476 { 477 System.out.println("could not create shortcut instance"); 478 exception.printStackTrace(); 479 } 480 } 481 482 //~ Methods 483 // ************************************************************************************************************************************************** 484 485 /*--------------------------------------------------------------------------*/ 486 /** 487 * This method represents the <code>ActionListener</code> interface, invoked when an action 488 * occurs. 489 * 490 * @param event the action event. 491 */ 492 /*--------------------------------------------------------------------------*/ 493 public void actionPerformed(ActionEvent event) 494 { 495 Object eventSource = event.getSource(); 496 497 // ---------------------------------------------------- 498 // create shortcut for the current user was selected 499 // refresh the list of program groups accordingly and 500 // reset the program group to the default setting. 501 // ---------------------------------------------------- 502 if (eventSource.equals(currentUser)) 503 { 504 groupList.setListData(shortcut.getProgramGroups(Shortcut.CURRENT_USER)); 505 programGroup.setText(suggestedProgramGroup); 506 shortcut.setUserType(itsUserType = Shortcut.CURRENT_USER); 507 } 508 // ---------------------------------------------------- 509 // create shortcut for all users was selected 510 // refresh the list of program groups accordingly and 511 // reset the program group to the default setting. 512 // ---------------------------------------------------- 513 else if (eventSource.equals(allUsers)) 514 { 515 groupList.setListData(shortcut.getProgramGroups(Shortcut.ALL_USERS)); 516 programGroup.setText(suggestedProgramGroup); 517 shortcut.setUserType(itsUserType = Shortcut.ALL_USERS); 518 } 519 // ---------------------------------------------------- 520 // The reset button was pressed. 521 // - clear the selection in the list box, because the 522 // selection is no longer valid 523 // - refill the program group edit control with the 524 // suggested program group name 525 // ---------------------------------------------------- 526 else if (eventSource.equals(defaultButton)) 527 { 528 groupList.getSelectionModel().clearSelection(); 529 programGroup.setText(suggestedProgramGroup); 530 } 531 // ---------------------------------------------------- 532 // the save button was pressed. This is a request to 533 // save shortcut information to a text file. 534 // ---------------------------------------------------- 535 else if (eventSource.equals(saveButton)) 536 { 537 saveToFile(); 538 539 // add the file to the uninstaller 540 addToUninstaller(); 541 } 542 else if (eventSource.equals(createShortcuts)) 543 { 544 create = createShortcuts.isSelected(); 545 546 groupList.setEnabled(create); 547 programGroup.setEnabled(create); 548 currentUser.setEnabled(create); 549 defaultButton.setEnabled(create); 550 allowDesktopShortcut.setEnabled(create); 551 if( isRootUser ) 552 allUsers.setEnabled(create); 553 } 554 } 555 556 /*--------------------------------------------------------------------------*/ 557 /** 558 * Returns <code>true</code> when all selections have valid settings. This indicates that it 559 * is legal to procede to the next panel. 560 * 561 * @return <code>true</code> if it is legal to procede to the next panel, otherwise 562 * <code>false</code>. 563 */ 564 /*--------------------------------------------------------------------------*/ 565 public boolean isValidated() 566 { 567 try 568 { 569 groupName = programGroup.getText(); 570 } 571 catch (Throwable exception) 572 { 573 groupName = ""; 574 } 575 create = createShortcuts.isSelected(); 576 577 createShortcuts(); 578 579 // add files and directories to the uninstaller 580 addToUninstaller(); 581 582 return (true); 583 } 584 585 /*--------------------------------------------------------------------------*/ 586 /** 587 * Called when the panel is shown to the user. 588 */ 589 /*--------------------------------------------------------------------------*/ 590 public void panelActivate() 591 { 592 if (firstTime) 593 firstTime = false; 594 else 595 return; 596 597 analyzeShortcutSpec(); 598 599 if (shortcutsToCreate && !OsVersion.IS_OSX) 600 { 601 if (shortcut.supported() && !simulteNotSupported) 602 { 603 File allUsersProgramsFolder = getProgramsFolder(Shortcut.ALL_USERS); 604 605 isRootUser = allUsersProgramsFolder.canWrite(); 606 607 if (isRootUser) 608 itsUserType = Shortcut.ALL_USERS; 609 else 610 itsUserType = Shortcut.CURRENT_USER; 611 612 buildUI( getProgramsFolder(isRootUser ? Shortcut.ALL_USERS : Shortcut.CURRENT_USER) ); 613 } 614 else 615 { 616 if (skipIfNotSupported) 617 { 618 parent.skipPanel(); 619 } 620 else 621 { 622 buildAlternateUI(); 623 parent.unlockNextButton(); 624 parent.lockPrevButton(); 625 } 626 } 627 } 628 else 629 { 630 parent.skipPanel (); 631 } 632 } 633 634 /** 635 * Returns the ProgramsFolder for the current User 636 * 637 * @return The Basedir 638 */ 639 private File getProgramsFolder(int userType) 640 { 641 String path = shortcut.getProgramsFolder(userType); 642 return (new File(path)); 643 //} 644 //else 645 //{ 646 // TODO 647 // 0pt. Test if KDE is installed. 648 //boolean isKdeInstalled = UnixHelper.kdeIsInstalled(); 649 // 1. Test if User can write into 650 // File kdeRootShareApplinkDir = getKDERootShareApplinkDir(); 651 // if so: return getKDERootShareApplinkDir() 652 // else 653 // return getKDEUsersShareApplinkDir() + 654 //} 655 //return(result); 656 } 657 658 /** 659 * This method is called by the <code>groupList</code> when the user makes a selection. It 660 * updates the content of the <code>programGroup</code> with the result of the selection. 661 * 662 * @param event the list selection event 663 */ 664 665 /*--------------------------------------------------------------------------*/ 666 public void valueChanged(ListSelectionEvent event) 667 { 668 if (programGroup == null) { return; } 669 670 String value = ""; 671 672 try 673 { 674 value = (String) groupList.getSelectedValue(); 675 } 676 catch (ClassCastException exception) 677 {} 678 679 if (value == null) 680 { 681 value = ""; 682 } 683 684 programGroup.setText(value + File.separator + suggestedProgramGroup); 685 } 686 687 /*--------------------------------------------------------------------------*/ 688 689 /** 690 * Reads the XML specification for the shortcuts to create. The result is stored in spec. 691 * 692 * @exception Exception for any problems in reading the specification 693 */ 694 695 /*--------------------------------------------------------------------------*/ 696 private void readShortcutSpec() throws Exception 697 { 698 // open an input stream 699 InputStream input = null; 700 701 try 702 { 703 input = parent.getResource(TargetFactory.getCurrentOSPrefix() + SPEC_FILE_NAME); 704 } 705 catch (ResourceNotFoundException rnfE) 706 { 707 input = parent.getResource(SPEC_FILE_NAME); 708 709 if (input == null) 710 { 711 haveShortcutSpec = false; 712 713 return; 714 } 715 } 716 717 // if( input == null ) 718 // { 719 // haveShortcutSpec = false; 720 // return; 721 // } 722 // initialize the parser 723 StdXMLParser parser = new StdXMLParser(); 724 parser.setBuilder(new StdXMLBuilder()); 725 parser.setValidator(new NonValidator()); 726 parser.setReader(new StdXMLReader(input)); 727 728 // get the data 729 spec = (XMLElement) parser.parse(); 730 731 // close the stream 732 input.close(); 733 haveShortcutSpec = true; 734 } 735 736 /*--------------------------------------------------------------------------*/ 737 738 /** 739 * This method analyzes the specifications for creating shortcuts and builds a list of all the 740 * Shortcuts that need to be created. 741 */ 742 743 /*--------------------------------------------------------------------------*/ 744 private void analyzeShortcutSpec() 745 { 746 if (!haveShortcutSpec) 747 { 748 shortcutsToCreate = false; 749 750 return; 751 } 752 753 XMLElement skipper = spec.getFirstChildNamed(SPEC_KEY_SKIP_IFNOT_SUPPORTED); 754 skipIfNotSupported = (skipper != null); 755 756 // ---------------------------------------------------- 757 // find out if we should simulate a not supported 758 // scenario 759 // ---------------------------------------------------- 760 XMLElement support = spec.getFirstChildNamed(SPEC_KEY_NOT_SUPPORTED); 761 762 if (support != null) 763 { 764 simulteNotSupported = true; 765 } 766 767 // ---------------------------------------------------- 768 // find out in which program group the shortcuts should 769 // be placed and where this program group should be 770 // located 771 // ---------------------------------------------------- 772 XMLElement group = spec.getFirstChildNamed(SPEC_KEY_PROGRAM_GROUP); 773 String location = null; 774 hasDesktopShortcuts = false; 775 776 if (group != null) 777 { 778 suggestedProgramGroup = group.getAttribute(SPEC_ATTRIBUTE_DEFAULT_GROUP, ""); 779 location = group.getAttribute(SPEC_ATTRIBUTE_LOCATION, SPEC_VALUE_APPLICATIONS); 780 } 781 else 782 { 783 suggestedProgramGroup = ""; 784 location = SPEC_VALUE_APPLICATIONS; 785 } 786 787 if (location.equals(SPEC_VALUE_APPLICATIONS)) 788 { 789 groupLocation = Shortcut.APPLICATIONS; 790 } 791 else if (location.equals(SPEC_VALUE_START_MENU)) 792 { 793 groupLocation = Shortcut.START_MENU; 794 } 795 796 // ---------------------------------------------------- 797 // create a list of all shortcuts that need to be 798 // created, containing all details about each shortcut 799 // ---------------------------------------------------- 800 VariableSubstitutor substitutor = new VariableSubstitutor(idata.getVariables()); 801 String temp; 802 Vector shortcutSpecs = spec.getChildrenNamed(SPEC_KEY_SHORTCUT); 803 XMLElement shortcutSpec; 804 ShortcutData data; 805 806 for (int i = 0; i < shortcutSpecs.size(); i++) 807 { 808 shortcutSpec = (XMLElement) shortcutSpecs.elementAt(i); 809 810 if (!OsConstraint.oneMatchesCurrentSystem(shortcutSpec)) continue; 811 812 data = new ShortcutData(); 813 814 data.name = shortcutSpec.getAttribute(SPEC_ATTRIBUTE_NAME); 815 data.subgroup = shortcutSpec.getAttribute(SPEC_ATTRIBUTE_SUBGROUP); 816 data.description = shortcutSpec.getAttribute(SPEC_ATTRIBUTE_DESCRIPTION, ""); 817 818 //** Linux **// 819 data.deskTopEntryLinux_Encoding = shortcutSpec 820 .getAttribute(SPEC_ATTRIBUTE_ENCODING, ""); 821 data.deskTopEntryLinux_MimeType = shortcutSpec 822 .getAttribute(SPEC_ATTRIBUTE_MIMETYPE, ""); 823 data.deskTopEntryLinux_Terminal = shortcutSpec 824 .getAttribute(SPEC_ATTRIBUTE_TERMINAL, ""); 825 data.deskTopEntryLinux_TerminalOptions = shortcutSpec.getAttribute( 826 SPEC_ATTRIBUTE_TERMINAL_OPTIONS, ""); 827 data.deskTopEntryLinux_Type = shortcutSpec.getAttribute(SPEC_ATTRIBUTE_TYPE, ""); 828 829 data.deskTopEntryLinux_URL = substitutor.substitute(shortcutSpec.getAttribute( 830 SPEC_ATTRIBUTE_URL, ""), null); 831 832 data.deskTopEntryLinux_X_KDE_SubstituteUID = shortcutSpec.getAttribute( 833 SPEC_ATTRIBUTE_KDE_SUBST_UID, ""); 834 835 data.createForAll = new Boolean(shortcutSpec.getAttribute(CREATE_FOR_ALL, "false")); 836 //** EndOf LINUX **// 837 temp = fixSeparatorChar(shortcutSpec.getAttribute(SPEC_ATTRIBUTE_TARGET, "")); 838 data.target = substitutor.substitute(temp, null); 839 840 temp = shortcutSpec.getAttribute(SPEC_ATTRIBUTE_COMMAND, ""); 841 data.commandLine = substitutor.substitute(temp, null); 842 843 temp = fixSeparatorChar(shortcutSpec.getAttribute(SPEC_ATTRIBUTE_ICON, "")); 844 data.iconFile = substitutor.substitute(temp, null); 845 data.iconIndex = Integer.parseInt(shortcutSpec.getAttribute(SPEC_ATTRIBUTE_ICON_INDEX, 846 "0")); 847 848 temp = fixSeparatorChar(shortcutSpec.getAttribute(SPEC_ATTRIBUTE_WORKING_DIR, "")); 849 data.workingDirectory = substitutor.substitute(temp, null); 850 851 String initialState = shortcutSpec.getAttribute(SPEC_ATTRIBUTE_INITIAL_STATE, ""); 852 853 if (initialState.equals(SPEC_VALUE_NO_SHOW)) 854 { 855 data.initialState = Shortcut.HIDE; 856 } 857 else if (initialState.equals(SPEC_VALUE_NORMAL)) 858 { 859 data.initialState = Shortcut.NORMAL; 860 } 861 else if (initialState.equals(SPEC_VALUE_MAXIMIZED)) 862 { 863 data.initialState = Shortcut.MAXIMIZED; 864 } 865 else if (initialState.equals(SPEC_VALUE_MINIMIZED)) 866 { 867 data.initialState = Shortcut.MINIMIZED; 868 } 869 else 870 { 871 data.initialState = Shortcut.NORMAL; 872 } 873 874 // -------------------------------------------------- 875 // if the minimal data requirements are met to create 876 // the shortcut, create one entry each for each of 877 // the requested types. 878 // Eventually this will cause the creation of one 879 // shortcut in each of the associated locations. 880 // -------------------------------------------------- 881 // without a name we can not create a shortcut 882 if (data.name == null) 883 { 884 continue; 885 } 886 887 //1. Elmar: "Without a target we can not create a shortcut." 888 //2. Marc: "No, Even on Linux a Link can be an URL and has no target." 889 if (data.target == null) 890 { 891 continue; 892 } 893 894 // the shortcut is not actually required for any of the selected packs 895 Vector forPacks = shortcutSpec.getChildrenNamed(SPEC_KEY_PACKS); 896 897 if (!shortcutRequiredFor(forPacks)) 898 { 899 continue; 900 } 901 // -------------------------------------------------- 902 // This section is executed if we don't skip. 903 // -------------------------------------------------- 904 // For each of the categories set the type and if 905 // the link should be placed in the program group, 906 // then clone the data set to obtain an independent 907 // instance and add this to the list of shortcuts 908 // to be created. In this way, we will set up an 909 // identical copy for each of the locations at which 910 // a shortcut should be placed. Therefore you must 911 // not use 'else if' statements! 912 // -------------------------------------------------- 913 { 914 if (attributeIsTrue(shortcutSpec, SPEC_ATTRIBUTE_DESKTOP)) 915 { 916 hasDesktopShortcuts = true; 917 data.addToGroup = false; 918 data.type = Shortcut.DESKTOP; 919 shortcuts.add(data.clone()); 920 } 921 922 if (attributeIsTrue(shortcutSpec, SPEC_ATTRIBUTE_APPLICATIONS)) 923 { 924 data.addToGroup = false; 925 data.type = Shortcut.APPLICATIONS; 926 shortcuts.add(data.clone()); 927 } 928 929 if (attributeIsTrue(shortcutSpec, SPEC_ATTRIBUTE_START_MENU)) 930 { 931 data.addToGroup = false; 932 data.type = Shortcut.START_MENU; 933 shortcuts.add(data.clone()); 934 } 935 936 if (attributeIsTrue(shortcutSpec, SPEC_ATTRIBUTE_STARTUP)) 937 { 938 data.addToGroup = false; 939 data.type = Shortcut.START_UP; 940 shortcuts.add(data.clone()); 941 } 942 943 if (attributeIsTrue(shortcutSpec, SPEC_ATTRIBUTE_PROGRAM_GROUP)) 944 { 945 data.addToGroup = true; 946 data.type = Shortcut.APPLICATIONS; 947 shortcuts.add(data.clone()); 948 } 949 } 950 } 951 952 // ---------------------------------------------------- 953 // signal if there are any shortcuts to create 954 // ---------------------------------------------------- 955 if (shortcuts.size() > 0) 956 { 957 shortcutsToCreate = true; 958 } 959 } 960 961 /*--------------------------------------------------------------------------*/ 962 963 /** 964 * Creates all shortcuts based on the information in <code>shortcuts</code>. 965 */ 966 967 /*--------------------------------------------------------------------------*/ 968 private void createShortcuts() 969 { 970 if (!create) return; 971 ShortcutData data; 972 973 for (int i = 0; i < shortcuts.size(); i++) 974 { 975 data = (ShortcutData) shortcuts.elementAt(i); 976 977 try 978 { 979 groupName = groupName + data.subgroup; 980 shortcut.setUserType(itsUserType); 981 shortcut.setLinkName(data.name); 982 shortcut.setLinkType(data.type); 983 shortcut.setArguments(data.commandLine); 984 shortcut.setDescription(data.description); 985 shortcut.setIconLocation(data.iconFile, data.iconIndex); 986 987 shortcut.setShowCommand(data.initialState); 988 shortcut.setTargetPath(data.target); 989 shortcut.setWorkingDirectory(data.workingDirectory); 990 shortcut.setEncoding(data.deskTopEntryLinux_Encoding); 991 shortcut.setMimetype(data.deskTopEntryLinux_MimeType); 992 993 shortcut.setTerminal(data.deskTopEntryLinux_Terminal); 994 shortcut.setTerminalOptions(data.deskTopEntryLinux_TerminalOptions); 995 shortcut.setType(data.deskTopEntryLinux_Type); 996 shortcut.setKdeSubstUID(data.deskTopEntryLinux_X_KDE_SubstituteUID); 997 shortcut.setURL(data.deskTopEntryLinux_URL); 998 shortcut.setCreateForAll(data.createForAll); 999 1000 if (data.addToGroup) 1001 { 1002 shortcut.setProgramGroup(groupName); 1003 } 1004 else 1005 { 1006 shortcut.setProgramGroup(""); 1007 } 1008 1009 try 1010 { 1011 // ---------------------------------------------- 1012 // save the shortcut only if it is either not on 1013 // the desktop or if it is on the desktop and 1014 // the user has signalled that it is ok to place 1015 // shortcuts on the desktop. 1016 // ---------------------------------------------- 1017 if ((data.type != Shortcut.DESKTOP) 1018 || ((data.type == Shortcut.DESKTOP) && allowDesktopShortcut 1019 .isSelected())) 1020 { 1021 // save the shortcut 1022 shortcut.save(); 1023 1024 // add the file and directory name to the file list 1025 String fileName = shortcut.getFileName(); 1026 files.add(0, fileName); 1027 1028 File file = new File(fileName); 1029 File base = new File(shortcut.getBasePath()); 1030 Vector intermediates = new Vector(); 1031 1032 //String directoryName = shortcut.getDirectoryCreated (); 1033 execFiles.add(new ExecutableFile(fileName, 2, ExecutableFile.WARN, 1034 new ArrayList(), false)); 1035 1036 files.add(fileName); 1037 1038 while ((file = file.getParentFile()) != null) 1039 { 1040 if (file.equals(base)) break; 1041 intermediates.add(file); 1042 } 1043 if (file != null) 1044 { 1045 for (Iterator iter = intermediates.iterator(); iter.hasNext();) 1046 files.add(0, iter.next().toString()); 1047 } 1048 } 1049 } 1050 catch (Exception exception) 1051 {} 1052 } 1053 catch (Throwable exception) 1054 { 1055 continue; 1056 } 1057 } 1058 1059 1060 // 1061 try 1062 { 1063 1064 if (execFiles != null) 1065 { 1066 FileExecutor executor = new FileExecutor(execFiles); 1067 // 1068 // TODO: Hi Guys, 1069 // TODO The following commented-out line sometimes produces an uncatchable 1070 // nullpointer Exception! 1071 // TODO evaluate for what reason the files should exec. 1072 // TODO if there is a serious explanation, why to do that, 1073 // TODO the code must be more robust 1074 1075 //evaluate executor.executeFiles( ExecutableFile.NEVER, null ); 1076 } 1077 } 1078 catch (NullPointerException nep) 1079 { 1080 nep.printStackTrace(); 1081 } 1082 catch (RuntimeException cannot) 1083 { 1084 cannot.printStackTrace(); 1085 } 1086 1087 parent.unlockNextButton(); 1088 } 1089 1090 /*--------------------------------------------------------------------------*/ 1091 1092 /** 1093 * Verifies if the shortcut is required for any of the packs listed. The shortcut is required 1094 * for a pack in the list if that pack is actually selected for installation. <br> 1095 * <br> 1096 * <b>Note: </b> <br> 1097 * If the list of selected packs is empty then <code>true</code> is always returnd. The same 1098 * is true if the <code>packs</code> list is empty. 1099 * 1100 * @param packs a <code>Vector</code> of <code>String</code>s. Each of the strings denotes 1101 * a pack for which the schortcut should be created if the pack is actually installed. 1102 * 1103 * @return <code>true</code> if the shortcut is required for at least on pack in the list, 1104 * otherwise returns <code>false</code>. 1105 */ 1106 1107 /*--------------------------------------------------------------------------*/ 1108 /* 1109 * $ @design 1110 * 1111 * The information about the installed packs comes from InstallData.selectedPacks. This assumes 1112 * that this panel is presented to the user AFTER the PacksPanel. 1113 * -------------------------------------------------------------------------- 1114 */ 1115 private boolean shortcutRequiredFor(Vector packs) 1116 { 1117 String selected; 1118 String required; 1119 1120 if (packs.size() == 0) { return (true); } 1121 1122 for (int i = 0; i < idata.selectedPacks.size(); i++) 1123 { 1124 selected = ((Pack) idata.selectedPacks.get(i)).name; 1125 1126 for (int k = 0; k < packs.size(); k++) 1127 { 1128 required = (String) ((XMLElement) packs.elementAt(k)).getAttribute( 1129 SPEC_ATTRIBUTE_NAME, ""); 1130 1131 if (selected.equals(required)) { return (true); } 1132 } 1133 } 1134 1135 return (false); 1136 } 1137 1138 /*--------------------------------------------------------------------------*/ 1139 1140 /** 1141 * Determines if the named attribute in true. True is represented by any of the following 1142 * strings and is not case sensitive. <br> 1143 * 1144 * <ul> 1145 * <li>yes</li> 1146 * <li>1</li> 1147 * <li>true</li> 1148 * <li>on</li> 1149 * </ul> 1150 * 1151 * <br> 1152 * Every other string, including the empty string as well as the non-existence of the attribute 1153 * will cuase <code>false</code> to be returned. 1154 * 1155 * @param element the <code>XMLElement</code> to search for the attribute. 1156 * @param name the name of the attribute to test. 1157 * 1158 * @return <code>true</code> if the attribute value equals one of the pre-defined strings, 1159 * <code>false</code> otherwise. 1160 */ 1161 1162 /*--------------------------------------------------------------------------*/ 1163 private boolean attributeIsTrue(XMLElement element, String name) 1164 { 1165 String value = element.getAttribute(name, "").toUpperCase(); 1166 1167 if (value.equals("YES")) 1168 { 1169 return (true); 1170 } 1171 else if (value.equals("TRUE")) 1172 { 1173 return (true); 1174 } 1175 else if (value.equals("ON")) 1176 { 1177 return (true); 1178 } 1179 else if (value.equals("1")) { return (true); } 1180 1181 return (false); 1182 } 1183 1184 /*--------------------------------------------------------------------------*/ 1185 1186 /** 1187 * Replaces any ocurrence of '/' or '\' in a path string with the correct version for the 1188 * operating system. 1189 * 1190 * @param path a system path 1191 * 1192 * @return a path string that uniformely uses the proper version of the separator character. 1193 */ 1194 1195 /*--------------------------------------------------------------------------*/ 1196 private String fixSeparatorChar(String path) 1197 { 1198 String newPath = path.replace('/', File.separatorChar); 1199 newPath = newPath.replace('\\', File.separatorChar); 1200 1201 return (newPath); 1202 } 1203 1204 /*--------------------------------------------------------------------------*/ 1205 1206 /** 1207 * This method creates the UI for this panel. 1208 * 1209 * @param groups A <code>Vector</code> that contains <code>Strings</code> with all the names 1210 * of the existing program groups. These will be placed in the <code>groupList</code>. 1211 */ 1212 1213 /*--------------------------------------------------------------------------*/ 1214 private void buildUI(File groups) 1215 { 1216 itsProgramFolder = groups; 1217 1218 constraints.gridx = 0; 1219 constraints.gridy = 0; 1220 constraints.gridwidth = 3; 1221 constraints.gridheight = 1; 1222 constraints.weightx = 1.0; 1223 constraints.weighty = 1.0; 1224 constraints.fill = GridBagConstraints.HORIZONTAL; 1225 constraints.anchor = GridBagConstraints.WEST; 1226 /**/ 1227 1228 1229 // Add a CheckBox which enables the user to entirely supress shortcut creation. 1230 String menuKind = parent.langpack.getString("ShortcutPanel.regular.StartMenu:Start-Menu"); 1231 if( OsVersion.IS_UNIX && UnixHelper.kdeIsInstalled() ) 1232 menuKind = parent.langpack.getString("ShortcutPanel.regular.StartMenu:K-Menu"); 1233 1234 createShortcuts = new JCheckBox( StringTool.replace( parent.langpack.getString("ShortcutPanel.regular.create"), "StartMenu", menuKind ), 1235 true); 1236 createShortcuts.addActionListener(this); 1237 constraints.gridx = 0; 1238 constraints.gridy = 1; 1239 constraints.gridwidth = 2; 1240 constraints.gridheight = 1; 1241 constraints.weighty = 0.2; 1242 layout.addLayoutComponent(createShortcuts, constraints); 1243 add(createShortcuts); 1244 1245 // ---------------------------------------------------- 1246 // check box to allow the user to decide if a desktop 1247 // shortcut should be created. 1248 // this should only be created if needed and requested 1249 // in the definition file. 1250 // ---------------------------------------------------- 1251 if (hasDesktopShortcuts) 1252 { 1253 String initialAllowedValue = idata.getVariable( "DesktopShortcutCheckboxEnabled" ); 1254 boolean initialAllowedFlag = false; 1255 if( initialAllowedValue==null) 1256 initialAllowedFlag= false; 1257 else if( Boolean.TRUE.toString().equals(initialAllowedValue) ) 1258 initialAllowedFlag=true; 1259 1260 allowDesktopShortcut = new JCheckBox(parent.langpack 1261 .getString("ShortcutPanel.regular.desktop"), initialAllowedFlag); 1262 constraints.gridx = 0; 1263 constraints.gridy = 2; 1264 constraints.gridwidth = 3; 1265 constraints.gridheight = 1; 1266 constraints.weighty = 0.2; 1267 1268 layout.addLayoutComponent(allowDesktopShortcut, constraints); 1269 add(allowDesktopShortcut); 1270 } 1271 1272 listLabel = LabelFactory.create(parent.langpack.getString("ShortcutPanel.regular.list"), 1273 JLabel.LEADING); 1274 1275 constraints.gridx = 0; 1276 constraints.gridy = 3; 1277 constraints.gridwidth = 1; 1278 constraints.gridheight = 1; 1279 constraints.weightx = 0.2; 1280 constraints.weighty = 0.2; 1281 constraints.fill = GridBagConstraints.NONE; 1282 constraints.anchor = GridBagConstraints.WEST; 1283 1284 layout.addLayoutComponent(listLabel, constraints); 1285 add(listLabel); 1286 // ---------------------------------------------------- 1287 // list box to list all of already existing folders as program groups 1288 // at the intended destination 1289 // ---------------------------------------------------- 1290 addSelectionList( groups, 0, 4, 2, 1, GridBagConstraints.BOTH ); 1291 1292 // ---------------------------------------------------- 1293 // radio buttons to select current user or all users. 1294 // ---------------------------------------------------- 1295 if (shortcut.multipleUsers()) 1296 { 1297 JPanel usersPanel = new JPanel(new GridLayout(2, 1)); 1298 ButtonGroup usersGroup = new ButtonGroup(); 1299 currentUser = new JRadioButton(parent.langpack 1300 .getString("ShortcutPanel.regular.currentUser"), !isRootUser); 1301 currentUser.addActionListener(this); 1302 usersGroup.add(currentUser); 1303 usersPanel.add(currentUser); 1304 allUsers = new JRadioButton( 1305 parent.langpack.getString("ShortcutPanel.regular.allUsers"), isRootUser); 1306 if (!isRootUser) allUsers.setEnabled(false); 1307 allUsers.addActionListener(this); 1308 usersGroup.add(allUsers); 1309 usersPanel.add(allUsers); 1310 1311 TitledBorder border = new TitledBorder(new EmptyBorder(2, 2, 2, 2), parent.langpack 1312 .getString("ShortcutPanel.regular.userIntro")); 1313 usersPanel.setBorder(border); 1314 1315 constraints.gridx = 2; 1316 constraints.gridy = 4; 1317 constraints.gridwidth = 1; 1318 constraints.gridheight = 1; 1319 constraints.weighty = 1.0; 1320 constraints.weightx = 1.0; 1321 constraints.fill = GridBagConstraints.NONE; 1322 layout.addLayoutComponent(usersPanel, constraints); 1323 add(usersPanel); 1324 } 1325 1326 // ---------------------------------------------------- 1327 // edit box that contains the suggested program group 1328 // name, which can be modfied or substituted from the 1329 // list by the user 1330 // ---------------------------------------------------- 1331 programGroup = new JTextField(suggestedProgramGroup, 40); // 40? 1332 1333 constraints.gridx = 0; 1334 constraints.gridy = 5; 1335 constraints.gridwidth = 2; 1336 constraints.gridheight = 1; 1337 constraints.weighty = 1.0; 1338 constraints.weightx = 10.0; 1339 constraints.fill = GridBagConstraints.HORIZONTAL; 1340 layout.addLayoutComponent(programGroup, constraints); 1341 add(programGroup); 1342 1343 // ---------------------------------------------------- 1344 // reset button that allows the user to revert to the 1345 // original suggestion for the program group 1346 // ---------------------------------------------------- 1347 defaultButton = ButtonFactory.createButton(parent.langpack 1348 .getString("ShortcutPanel.regular.default"), idata.buttonsHColor); 1349 defaultButton.addActionListener(this); 1350 1351 constraints.gridx = 2; 1352 constraints.gridy = 5; 1353 constraints.gridwidth = 1; 1354 constraints.gridheight = 1; 1355 constraints.fill = GridBagConstraints.NONE; 1356 layout.addLayoutComponent(defaultButton, constraints); 1357 add(defaultButton); 1358 } 1359 1360 /** 1361 * 1362 * @param groups 1363 */ 1364 private void addSelectionList(File groups, int aGridx, int aGridy, int aGridwidth, int aGridheight, int aFill) 1365 { 1366 Vector dirEntries = new Vector(); 1367 1368 File[] entries = groups.listFiles(); 1369 1370 // Quickfix prevent NullPointer on non default compliant Linux - KDEs 1371 // i.e Mandrake 2005 LE stores from now also in "applnk" instead in prior "applnk-mdk": 1372 if( entries != null ) 1373 for (int idx = 0; idx < entries.length; idx++) 1374 { 1375 if (entries[idx].isDirectory()) 1376 { 1377 dirEntries.add(entries[idx].getName()); 1378 } 1379 } 1380 groupList = new JList(dirEntries); 1381 groupList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 1382 groupList.getSelectionModel().addListSelectionListener(this); 1383 1384 JScrollPane scrollPane = new JScrollPane(groupList); 1385 1386 constraints.gridx = aGridx; 1387 constraints.gridy = aGridy; 1388 constraints.gridwidth = aGridwidth; 1389 constraints.gridheight = aGridheight; 1390 constraints.weightx = 10.0; 1391 constraints.weighty = 1.5; 1392 constraints.insets = new Insets(5, 5, 5, 5); 1393 constraints.fill = aFill; 1394 layout.addLayoutComponent(scrollPane, constraints); 1395 add(scrollPane); 1396 } 1397 1398 1399 /*--------------------------------------------------------------------------*/ 1400 1401 /** 1402 * This method creates an alternative UI for this panel. This UI can be used when the creation 1403 * of shortcuts is not supported on the target system. It displays an apology for the inability 1404 * to create shortcuts on this system, along with information about the intended targets. In 1405 * addition, there is a button that allows the user to save more complete information in a text 1406 * file. Based on this information the user might be able to create the necessary shortcut him 1407 * or herself. At least there will be information about how to launch the application. 1408 */ 1409 1410 /*--------------------------------------------------------------------------*/ 1411 private void buildAlternateUI() 1412 { 1413 layout = new GridBagLayout(); 1414 constraints = new GridBagConstraints(); 1415 setLayout(layout); 1416 1417 // ---------------------------------------------------- 1418 // static text a the top of the panel, that apologizes 1419 // about the fact that we can not create shortcuts on 1420 // this particular target OS. 1421 // ---------------------------------------------------- 1422 MultiLineLabel apologyLabel = new MultiLineLabel(parent.langpack 1423 .getString("ShortcutPanel.alternate.apology"), 0, 0); 1424 1425 constraints.gridx = 0; 1426 constraints.gridy = 0; 1427 constraints.gridwidth = 1; 1428 constraints.gridheight = 1; 1429 constraints.weightx = 1.0; 1430 constraints.weighty = 1.0; 1431 constraints.insets = new Insets(5, 5, 5, 5); 1432 constraints.fill = GridBagConstraints.HORIZONTAL; 1433 constraints.anchor = GridBagConstraints.WEST; 1434 layout.addLayoutComponent(apologyLabel, constraints); 1435 add(apologyLabel); 1436 1437 // ---------------------------------------------------- 1438 // label that explains the significance ot the list box 1439 // ---------------------------------------------------- 1440 MultiLineLabel listLabel = new MultiLineLabel(parent.langpack 1441 .getString("ShortcutPanel.alternate.targetsLabel"), 0, 0); 1442 1443 constraints.gridx = 0; 1444 constraints.gridy = 1; 1445 constraints.gridwidth = 1; 1446 constraints.gridheight = 1; 1447 constraints.weightx = 1.0; 1448 constraints.weighty = 1.0; 1449 layout.addLayoutComponent(listLabel, constraints); 1450 add(listLabel); 1451 1452 // ---------------------------------------------------- 1453 // list box to list all of the intended shortcut targets 1454 // ---------------------------------------------------- 1455 Vector targets = new Vector(); 1456 1457 for (int i = 0; i < shortcuts.size(); i++) 1458 { 1459 targets.add(((ShortcutData) shortcuts.elementAt(i)).target); 1460 } 1461 1462 targetList = new JList(targets); 1463 1464 JScrollPane scrollPane = new JScrollPane(targetList); 1465 1466 constraints.gridx = 0; 1467 constraints.gridy = 2; 1468 constraints.fill = GridBagConstraints.BOTH; 1469 layout.addLayoutComponent(scrollPane, constraints); 1470 add(scrollPane); 1471 1472 // ---------------------------------------------------- 1473 // static text that explains about the text file 1474 // ---------------------------------------------------- 1475 MultiLineLabel fileExplanation = new MultiLineLabel(parent.langpack 1476 .getString("ShortcutPanel.alternate.textFileExplanation"), 0, 0); 1477 1478 constraints.gridx = 0; 1479 constraints.gridy = 3; 1480 constraints.weightx = 1.0; 1481 constraints.weighty = 1.0; 1482 constraints.fill = GridBagConstraints.HORIZONTAL; 1483 layout.addLayoutComponent(fileExplanation, constraints); 1484 add(fileExplanation); 1485 1486 // ---------------------------------------------------- 1487 // button to save the text file 1488 // ---------------------------------------------------- 1489 saveButton = ButtonFactory.createButton(parent.langpack 1490 .getString("ShortcutPanel.alternate.saveButton"), idata.buttonsHColor); 1491 saveButton.addActionListener(this); 1492 1493 constraints.gridx = 0; 1494 constraints.gridy = 4; 1495 constraints.gridwidth = 1; 1496 constraints.gridheight = 1; 1497 constraints.fill = GridBagConstraints.NONE; 1498 constraints.anchor = GridBagConstraints.CENTER; 1499 layout.addLayoutComponent(saveButton, constraints); 1500 add(saveButton); 1501 } 1502 1503 /*--------------------------------------------------------------------------*/ 1504 1505 /** 1506 * Overriding the superclass implementation. This method returns the size of the container. 1507 * 1508 * @return the size of the container 1509 */ 1510 1511 /*--------------------------------------------------------------------------*/ 1512 public Dimension getSize() 1513 { 1514 Dimension size = getParent().getSize(); 1515 Insets insets = getInsets(); 1516 Border border = getBorder(); 1517 Insets borderInsets = new Insets(0, 0, 0, 0); 1518 1519 if (border != null) 1520 { 1521 borderInsets = border.getBorderInsets(this); 1522 } 1523 1524 size.height = size.height - insets.top - insets.bottom - borderInsets.top 1525 - borderInsets.bottom - 50; 1526 size.width = size.width - insets.left - insets.right - borderInsets.left 1527 - borderInsets.right - 50; 1528 1529 return (size); 1530 } 1531 1532 /*--------------------------------------------------------------------------*/ 1533 1534 /** 1535 * This method saves all shortcut information to a text file. 1536 */ 1537 1538 /*--------------------------------------------------------------------------*/ 1539 private void saveToFile() 1540 { 1541 File file = null; 1542 1543 // ---------------------------------------------------- 1544 // open a file chooser dialog to get a path / file name 1545 // ---------------------------------------------------- 1546 JFileChooser fileDialog = new JFileChooser(idata.getInstallPath()); 1547 fileDialog.setSelectedFile(new File(TEXT_FILE_NAME)); 1548 1549 if (fileDialog.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) 1550 { 1551 file = fileDialog.getSelectedFile(); 1552 } 1553 else 1554 { 1555 return; 1556 } 1557 1558 // ---------------------------------------------------- 1559 // save to the file 1560 // ---------------------------------------------------- 1561 FileWriter output = null; 1562 StringBuffer buffer = new StringBuffer(); 1563 String header = parent.langpack.getString("ShortcutPanel.textFile.header"); 1564 1565 String newline = System.getProperty("line.separator", "\n"); 1566 1567 try 1568 { 1569 output = new FileWriter(file); 1570 } 1571 catch (Throwable exception) 1572 { 1573 // !!! show an error dialog 1574 return; 1575 } 1576 1577 // ---------------------------------------------------- 1578 // break the header down into multiple lines based 1579 // on '\n' line breaks. 1580 // ---------------------------------------------------- 1581 int nextIndex = 0; 1582 int currentIndex = 0; 1583 1584 do 1585 { 1586 nextIndex = header.indexOf("\\n", currentIndex); 1587 1588 if (nextIndex > -1) 1589 { 1590 buffer.append(header.substring(currentIndex, nextIndex)); 1591 buffer.append(newline); 1592 currentIndex = nextIndex + 2; 1593 } 1594 else 1595 { 1596 buffer.append(header.substring(currentIndex, header.length())); 1597 buffer.append(newline); 1598 } 1599 } 1600 while (nextIndex > -1); 1601 1602 buffer.append(SEPARATOR_LINE); 1603 buffer.append(newline); 1604 buffer.append(newline); 1605 1606 for (int i = 0; i < shortcuts.size(); i++) 1607 { 1608 ShortcutData data = (ShortcutData) shortcuts.elementAt(i); 1609 1610 buffer.append(parent.langpack.getString("ShortcutPanel.textFile.name")); 1611 buffer.append(data.name); 1612 buffer.append(newline); 1613 1614 buffer.append(parent.langpack.getString("ShortcutPanel.textFile.location")); 1615 1616 switch (data.type) 1617 { 1618 case Shortcut.DESKTOP: { 1619 buffer.append(parent.langpack.getString("ShortcutPanel.location.desktop")); 1620 1621 break; 1622 } 1623 1624 case Shortcut.APPLICATIONS: { 1625 buffer.append(parent.langpack.getString("ShortcutPanel.location.applications")); 1626 1627 break; 1628 } 1629 1630 case Shortcut.START_MENU: { 1631 buffer.append(parent.langpack.getString("ShortcutPanel.location.startMenu")); 1632 1633 break; 1634 } 1635 1636 case Shortcut.START_UP: { 1637 buffer.append(parent.langpack.getString("ShortcutPanel.location.startup")); 1638 1639 break; 1640 } 1641 } 1642 1643 buffer.append(newline); 1644 1645 buffer.append(parent.langpack.getString("ShortcutPanel.textFile.description")); 1646 buffer.append(data.description); 1647 buffer.append(newline); 1648 1649 buffer.append(parent.langpack.getString("ShortcutPanel.textFile.target")); 1650 buffer.append(data.target); 1651 buffer.append(newline); 1652 1653 buffer.append(parent.langpack.getString("ShortcutPanel.textFile.command")); 1654 buffer.append(data.commandLine); 1655 buffer.append(newline); 1656 1657 buffer.append(parent.langpack.getString("ShortcutPanel.textFile.iconName")); 1658 buffer.append(data.iconFile); 1659 buffer.append(newline); 1660 1661 buffer.append(parent.langpack.getString("ShortcutPanel.textFile.iconIndex")); 1662 buffer.append(data.iconIndex); 1663 buffer.append(newline); 1664 1665 buffer.append(parent.langpack.getString("ShortcutPanel.textFile.work")); 1666 buffer.append(data.workingDirectory); 1667 buffer.append(newline); 1668 1669 buffer.append(newline); 1670 buffer.append(SEPARATOR_LINE); 1671 buffer.append(newline); 1672 buffer.append(newline); 1673 } 1674 1675 try 1676 { 1677 output.write(buffer.toString()); 1678 } 1679 catch (Throwable exception) 1680 {} 1681 finally 1682 { 1683 try 1684 { 1685 output.flush(); 1686 output.close(); 1687 files.add(file.getPath()); 1688 } 1689 catch (Throwable exception) 1690 { 1691 // not really anything I can do here, maybe should show a dialog that 1692 // tells the user that data might not have been saved completely!? 1693 } 1694 } 1695 } 1696 1697 /*--------------------------------------------------------------------------*/ 1698 1699 /** 1700 * Adds all files and directories to the uninstaller. 1701 */ 1702 1703 /*--------------------------------------------------------------------------*/ 1704 private void addToUninstaller() 1705 { 1706 UninstallData uninstallData = UninstallData.getInstance(); 1707 1708 for (int i = 0; i < files.size(); i++) 1709 { 1710 uninstallData.addFile((String) files.elementAt(i)); 1711 } 1712 } 1713 1714 /*--------------------------------------------------------------------------*/ 1715 1716 /** 1717 * Adds iformation about the shortcuts that have been created during the installation to the XML 1718 * tree. 1719 * 1720 * @param panelRoot the root of the XML tree 1721 */ 1722 1723 /*--------------------------------------------------------------------------*/ 1724 /* 1725 * $ @design 1726 * 1727 * The information needed to create shortcuts has been collected in the Vector 'shortcuts'. Take 1728 * the data from there and package it in XML form for storage by the installer. The group name 1729 * is only stored once in a separate XML element, since there is only one. 1730 * -------------------------------------------------------------------------- 1731 */ 1732 public void makeXMLData(XMLElement panelRoot) 1733 { 1734 // ---------------------------------------------------- 1735 // if there are no shortcuts to create, shortcuts are 1736 // not supported, or we should simulate that they are 1737 // not supported, then we have nothing to add. Just 1738 // return 1739 // ---------------------------------------------------- 1740 if (!shortcutsToCreate || !shortcut.supported() || groupName == null || simulteNotSupported) { return; } 1741 1742 ShortcutData data; 1743 XMLElement dataElement; 1744 1745 // ---------------------------------------------------- 1746 // add the item that defines the name of the program group 1747 // ---------------------------------------------------- 1748 dataElement = new XMLElement(AUTO_KEY_PROGRAM_GROUP); 1749 dataElement.setAttribute(AUTO_ATTRIBUTE_NAME, groupName); 1750 panelRoot.addChild(dataElement); 1751 1752 // ---------------------------------------------------- 1753 // add the details for each of the shortcuts 1754 // ---------------------------------------------------- 1755 for (int i = 0; i < shortcuts.size(); i++) 1756 { 1757 data = (ShortcutData) shortcuts.elementAt(i); 1758 dataElement = new XMLElement(AUTO_KEY_SHORTCUT); 1759 1760 dataElement.setAttribute(AUTO_ATTRIBUTE_NAME, data.name); 1761 dataElement.setAttribute(AUTO_ATTRIBUTE_GROUP, Boolean.valueOf(data.addToGroup) 1762 .toString()); 1763 dataElement.setAttribute(AUTO_ATTRIBUTE_TYPE, Integer.toString(data.type)); 1764 dataElement.setAttribute(AUTO_ATTRIBUTE_COMMAND, data.commandLine); 1765 dataElement.setAttribute(AUTO_ATTRIBUTE_DESCRIPTION, data.description); 1766 dataElement.setAttribute(AUTO_ATTRIBUTE_ICON, data.iconFile); 1767 dataElement.setAttribute(AUTO_ATTRIBUTE_ICON_INDEX, Integer.toString(data.iconIndex)); 1768 dataElement.setAttribute(AUTO_ATTRIBUTE_INITIAL_STATE, Integer 1769 .toString(data.initialState)); 1770 dataElement.setAttribute(AUTO_ATTRIBUTE_TARGET, data.target); 1771 dataElement.setAttribute(AUTO_ATTRIBUTE_WORKING_DIR, data.workingDirectory); 1772 1773 // ---------------------------------------------- 1774 // add the shortcut only if it is either not on 1775 // the desktop or if it is on the desktop and 1776 // the user has signalled that it is ok to place 1777 // shortcuts on the desktop. 1778 // ---------------------------------------------- 1779 if ((data.type != Shortcut.DESKTOP) 1780 || ((data.type == Shortcut.DESKTOP) && allowDesktopShortcut.isSelected())) 1781 { 1782 panelRoot.addChild(dataElement); 1783 } 1784 } 1785 } 1786 1787 /*--------------------------------------------------------------------------*/ 1788 1789 /** 1790 * Creates shortcuts based on teh information in <code>panelRoot</code> without UI. 1791 * 1792 * @param panelRoot the root of the XML tree 1793 */ 1794 1795 /*--------------------------------------------------------------------------*/ 1796 /* 1797 * $ @design 1798 * 1799 * Reconstitute the information needed to create shortcuts from XML data that was previously 1800 * stored by the installer through makeXMLData(). Create a new Vector containing this data and 1801 * stroe it in 'shortcuts' for use by createShortcuts(). Once this has been completed, call 1802 * createShortcuts() to complete the operation. 1803 * -------------------------------------------------------------------------- 1804 */ 1805 public void runAutomated(XMLElement panelRoot) 1806 { 1807 // ---------------------------------------------------- 1808 // if shortcuts are not supported, then we can not 1809 // create shortcuts, even if there was any install 1810 // data. Just return. 1811 // ---------------------------------------------------- 1812 if (!shortcut.supported()) { return; } 1813 1814 if (!OsConstraint.oneMatchesCurrentSystem(panelRoot)) { return; } 1815 1816 shortcuts = new Vector(); 1817 Vector shortcutElements; 1818 ShortcutData data; 1819 XMLElement dataElement; 1820 1821 // ---------------------------------------------------- 1822 // set the name of the program group 1823 // ---------------------------------------------------- 1824 dataElement = panelRoot.getFirstChildNamed(AUTO_KEY_PROGRAM_GROUP); 1825 groupName = dataElement.getAttribute(AUTO_ATTRIBUTE_NAME); 1826 1827 if (groupName == null) 1828 { 1829 groupName = ""; 1830 } 1831 1832 // ---------------------------------------------------- 1833 // add the details for each of the shortcuts 1834 // ---------------------------------------------------- 1835 shortcutElements = panelRoot.getChildrenNamed(AUTO_KEY_SHORTCUT); 1836 1837 for (int i = 0; i < shortcutElements.size(); i++) 1838 { 1839 data = new ShortcutData(); 1840 dataElement = (XMLElement) shortcutElements.elementAt(i); 1841 1842 data.name = dataElement.getAttribute(AUTO_ATTRIBUTE_NAME); 1843 data.addToGroup = Boolean.valueOf(dataElement.getAttribute(AUTO_ATTRIBUTE_GROUP)) 1844 .booleanValue(); 1845 data.type = Integer.valueOf(dataElement.getAttribute(AUTO_ATTRIBUTE_TYPE)).intValue(); 1846 data.commandLine = dataElement.getAttribute(AUTO_ATTRIBUTE_COMMAND); 1847 data.description = dataElement.getAttribute(AUTO_ATTRIBUTE_DESCRIPTION); 1848 data.iconFile = dataElement.getAttribute(AUTO_ATTRIBUTE_ICON); 1849 data.iconIndex = Integer.valueOf(dataElement.getAttribute(AUTO_ATTRIBUTE_ICON_INDEX)) 1850 .intValue(); 1851 data.initialState = Integer.valueOf( 1852 dataElement.getAttribute(AUTO_ATTRIBUTE_INITIAL_STATE)).intValue(); 1853 data.target = dataElement.getAttribute(AUTO_ATTRIBUTE_TARGET); 1854 data.workingDirectory = dataElement.getAttribute(AUTO_ATTRIBUTE_WORKING_DIR); 1855 1856 shortcuts.add(data); 1857 } 1858 1859 createShortcuts(); 1860 } 1861 1862 1863} 1864 1865/*---------------------------------------------------------------------------*/