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.util.os; 023 024import java.io.File; 025import java.io.UnsupportedEncodingException; 026 027import com.izforge.izpack.util.Librarian; 028import com.izforge.izpack.util.NativeLibraryClient; 029 030/*---------------------------------------------------------------------------*/ 031/** 032 * This class represents a MS-Windows shell link, aka shortcut. It supports creation, modification 033 * and deletion as well as reporting on details of shell links. This class uses a number of native 034 * methods to access the MS-Windows registry and load save and manipulate link data. The native code 035 * is contained in the file <code>ShellLink.cpp</code>. <br> 036 * <br> 037 * For more detailed information on Windows shortcuts read the win32 documentation from Microsoft on 038 * the IShellLink interface. There are also useful articles on this topic on the MIcrosoft website. 039 * <br> 040 * <br> 041 * <A 042 * HREF=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmgmt/html/msdn_shellnk1.asp>Using 043 * Shell Links in Windows 95</A><br> 044 * <A 045 * HREF=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/ishelllink/ishelllink.asp>The 046 * IShellLink interface</a><br> 047 * <A 048 * HREF=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/Shell/IFaces/IShellLink/IShellLink.asp>IShellLink</A> 049 * 050 * @version 0.0.1 / 1/21/02 051 * @author Elmar Grom 052 */ 053/*---------------------------------------------------------------------------*/ 054public class ShellLink implements NativeLibraryClient 055{ 056 057 // ------------------------------------------------------------------------ 058 // Constant Definitions 059 // ------------------------------------------------------------------------ 060 /** 061 * Note: each of the subclasses will convert these values as appropriate before calling the OS's 062 * routines. For example Win 98 & up will use SW_SNOWMINNOACTIVE (7) when passed HIDE (0) or 063 * MINIMIZED (2) <br> 064 * <br> 065 * and this conversion is done in Win_Shortcut.java 066 */ 067 /** 068 * Hide the window when starting. This is particularly useful when launching from a *.bat file, 069 * because no DOS window and no button for the DOS window on the task bar will show! <br> 070 * <br> 071 * <b>Note:</b> this option is not available through the Windows 98+ UI! 072 */ 073 public static final int HIDE = 0; 074 075 /** 076 * Show the window 'normal' when starting. Restores the window properties at the last shut-down. 077 */ 078 public static final int NORMAL = 1; 079 080 /** 081 * Show the window minimized when starting. The window will not show but a corresponding button 082 * in the task bar will. <p> 083 * 084 * Newer IShellLink only allows Normal, MinNoActive, Maximized. 085 */ 086 public static final int MINIMIZED = 2; 087 088 /** Show the window maximized when starting. */ 089 public static final int MAXIMIZED = 3; 090 091 /** 092 * Show the window minimized when starting. Note: for win98 and newer, use MINNOACTIVE instead 093 * of MINIMIZED. 094 */ 095 public static final int MINNOACTIVE = 7; 096 097 private static final int MIN_SHOW = 0; 098 099 private static final int MAX_SHOW = 7; 100 101 // ------------------------------------------------------ 102 // Shortcut types 103 // specific to ShellLink (Shortcut has different numbers). 104 // ------------------------------------------------------ 105 /** This type of shortcut shows on the desktop */ 106 public static final int DESKTOP = 1; 107 108 /** This type of shortcut shows in the program menu */ 109 public static final int PROGRAM_MENU = 2; 110 111 /** This type of shortcut shows in the start menu */ 112 public static final int START_MENU = 3; 113 114 /** This type of shortcut is executed at OS launch time */ 115 public static final int STARTUP = 4; 116 117 private static final int MIN_TYPE = 1; 118 119 private static final int MAX_TYPE = 4; 120 121 // ------------------------------------------------------ 122 // Return values from nafive methods 123 // ------------------------------------------------------ 124 /** Returned from native calls if the call was successful */ 125 private static final int SL_OK = 1; 126 127 /** Unspecific return if a native call was not successful */ 128 private static final int SL_ERROR = -1; 129 130 /** 131 * Return value from native initialization functions if already initialized 132 */ 133 private static final int SL_INITIALIZED = -2; 134 135 /** 136 * Return value from native uninitialization functions if never initialized 137 */ 138 private static final int SL_NOT_INITIALIZED = -3; 139 140 /** 141 * Return value from native uninitialization functions if there are no more interface handles 142 * available 143 */ 144 private static final int SL_OUT_OF_HANDLES = -4; 145 146 /** 147 * Return value from native uninitialization functions if nohandle for the IPersist interface 148 * could be obtained 149 */ 150 private static final int SL_NO_IPERSIST = -5; 151 152 /** 153 * Return value from native uninitialization functions if the save operation fort the link 154 * failed 155 */ 156 private static final int SL_NO_SAVE = -6; 157 158 /** 159 * Return value if the function called had to deal with unexpected data types. This might be 160 * returned by registry functions if they receive an unexpected data type from the registry. 161 */ 162 private static final int SL_WRONG_DATA_TYPE = -7; 163 164 // ------------------------------------------------------ 165 // Miscellaneous constants 166 // ------------------------------------------------------ 167 private static final int UNINITIALIZED = -1; 168 169 /** the extension that must be used for link files */ 170 private static final String LINK_EXTENSION = ".lnk"; 171 172 /** CURRENT_USER = 0; the constant to use for selecting the current user. */ 173 public static final int CURRENT_USER = 0; 174 175 /** the constant to use for selecting the all users. */ 176 public static final int ALL_USERS = 1; 177 178 // ------------------------------------------------------------------------ 179 // Variable Declarations 180 // ------------------------------------------------------------------------ 181 /** 182 * This handle links us to a specific native instance. Do not use or modify, the variable is for 183 * exclusive use by the native side. 184 */ 185 private int nativeHandle = UNINITIALIZED; 186 187 /** 188 * Path to the location where links for the current user are stored. The exact content depends 189 * on the circumstances. It can be set during object construction or from native code. It will 190 * point to the location where links of the most recently requested type are stored. 191 */ 192 private String currentUserLinkPath; 193 194 /** 195 * Path to the location where links for all users are stored. The exact content depends on the 196 * circumstances. It can be set during object construction or from native code. It will point to 197 * the location where links of the most recently requested type are stored. 198 */ 199 private String allUsersLinkPath; 200 201 private String groupName = ""; 202 203 private String linkName = ""; 204 205 /** 206 * this is the fully qualified name of the link on disk. Note that this variable contains only 207 * valid data if the link was created from a disk file or after a successful save operation. At 208 * other times the content is upredicatable. 209 */ 210 private String linkFileName = ""; 211 212 /** 213 * Contains the directory where the link file is stored after any save operation that needs to 214 * create that directory. Otherwise it contains <code>null</code>. 215 */ 216 private String linkDirectory = ""; 217 218 private String arguments = ""; 219 220 private String description = ""; 221 222 private String iconPath = ""; 223 224 private String targetPath = ""; 225 226 private String workingDirectory = ""; 227 228 /** 229 * there seems to be an error in JNI that causes an access violation if a String that is 230 * accessed from native code borders on another type of variable. This caused problems in 231 * <code>set()</code> For this reason, the dummy string is placed here. Observed with version: 232 * 233 * <pre> 234 * 235 * 236 * 237 * java version "1.3.0" 238 * Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C) 239 * Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode) 240 * 241 * 242 * </pre> 243 */ 244 private String dummyString = ""; 245 246 private int hotkey = 0; 247 248 private int iconIndex = 0; 249 250 private int showCommand = NORMAL; 251 252 private int linkType = DESKTOP; 253 254 private int userType = CURRENT_USER; 255 256 private boolean initializeSucceeded = false; 257 258 // ------------------------------------------------------------------------ 259 // Native Methods 260 // ------------------------------------------------------------------------ 261 // For documentation on these methods see ShellLink.cpp 262 // ------------------------------------------------------------------------ 263 private native int initializeCOM(); 264 265 private native int releaseCOM(); 266 267 private native int getInterface(); 268 269 private native int releaseInterface(); 270 271 private native int GetArguments(); 272 273 private native int GetDescription(); 274 275 private native int GetHotkey(); 276 277 private native int GetIconLocation(); 278 279 private native int GetPath(); 280 281 private native int GetShowCommand(); 282 283 private native int GetWorkingDirectory(); 284 285 private native int Resolve(); 286 287 private native int SetArguments(); 288 289 private native int SetDescription(); 290 291 private native int SetHotkey(); 292 293 private native int SetIconLocation(); 294 295 private native int SetPath(); 296 297 private native int SetShowCommand(); 298 299 private native int SetWorkingDirectory(); 300 301 private native int saveLink(String name); 302 303 private native int loadLink(String name); 304 305 private native int GetFullLinkPath(int usertype, int linktype); 306 307 /** 308 * This method is used to free the library at the end of progam execution. After this call, any 309 * instance of this calss will not be usable any more! 310 */ 311 private native void FreeLibrary(String name); 312 313 /** 314 * Creates an instance of <code>ShellLink</code> of a specific type. Initializes 315 * currentUserLinkPath and allUsersLinkPath. 316 * <p> 317 * 318 * A LinkPath is empty if the combination of linkType and userType, are not valid. 319 * <p> 320 * 321 * Note: If a linkPath is empty, the userType is reset to the other userType. 322 * <p> 323 * 324 * If both linkPaths are empty, an IllegalArgumentException is thrown. 325 * 326 * @param type The type of link desired. The following values can be set:<br> 327 * <ul> 328 * <li><code>ShellLink.DESKTOP</code> 329 * <li><code>ShellLink.PROGRAM_MENU</code> 330 * <li><code>ShellLink.START_MENU</code> 331 * <li><code>ShellLink.STARTUP</code> 332 * </ul> 333 * @param name The name that the link should display on a menu or on the desktop. Do not include 334 * a file extension. 335 * 336 * @exception IllegalArgumentException if any of the call parameters are incorrect, or if no 337 * linkPaths are returned. 338 * @exception Exception if problems are encountered in initializing the native interface 339 */ 340 public ShellLink(int type, String name) throws Exception, IllegalArgumentException 341 { 342 if ((type < MIN_TYPE) || (type > MAX_TYPE)) { throw (new IllegalArgumentException( 343 "the type parameter used an illegal value")); } 344 if (name == null) { throw (new IllegalArgumentException("the name parameter was null")); } 345 346 linkName = name; 347 linkType = type; 348 349 initialize(); // com 350 351 // set curretnUsersLinkPath, allUsersLinkPath, sets userType to valid. 352 setAllLinkPaths(); 353 } 354 355 /*--------------------------------------------------------------------------*/ 356 /** 357 * Creates an instance of <code>ShellLink</code> from an existing shell link on disk. 358 * 359 * @param name the fully qualified file name of the link. 360 * @param userType the type of user for the link path. 361 * 362 * @see #CURRENT_USER 363 * @see #ALL_USERS 364 * 365 * @exception IllegalArgumentException if the name was null 366 * @exception Exception if problems are encountered in reading the file 367 */ 368 public ShellLink(String name, int userType) throws Exception, IllegalArgumentException 369 { 370 if (name == null) { throw (new IllegalArgumentException("the name parameter was null")); } 371 372 this.userType = userType; 373 374 initialize(); // com 375 376 // store the individual parts of the path for later use 377 int pathEnd = name.lastIndexOf(File.separator); 378 int nameStart = pathEnd + 1; 379 int nameEnd = name.lastIndexOf('.'); 380 if (nameEnd < 0) { throw (new Exception("illegal file name")); } 381 linkName = name.substring(nameStart, nameEnd); 382 383 if (userType == CURRENT_USER) 384 { 385 currentUserLinkPath = name.substring(0, pathEnd); 386 } 387 else 388 { 389 allUsersLinkPath = name.substring(0, pathEnd); 390 } 391 392 linkFileName = fullLinkName(userType); 393 if (loadLink(linkFileName) != SL_OK) { throw (new Exception( 394 "reading of the file did not succeed")); } 395 396 // get all settings from the native side 397 get(); 398 } 399 400 /*--------------------------------------------------------------------------*/ 401 /** 402 * Creates an instance of <code>ShellLink</code> from an existing shell link on disk. 403 * 404 * @param type The type of link, one of the following values: <br> 405 * <ul> 406 * <li><code>ShellLink.DESKTOP</code> 407 * <li><code>ShellLink.PROGRAM_MENU</code> 408 * <li><code>ShellLink.START_MENU</code> 409 * <li><code>ShellLink.STARTUP</code> 410 * </ul> 411 * @param userType the type of user for the link path. 412 * @param group The program group (directory) of this link. If the link is not part of a program 413 * group, pass an empty string or null for this parameter. (...\\Desktop\\group). 414 * @param name The file name of this link. Do not include a file extension. 415 * 416 * @see #CURRENT_USER 417 * @see #ALL_USERS 418 * 419 * @exception IllegalArgumentException if any of the call parameters are incorrect 420 * @exception Exception if problems are encountered in initializing the native interface 421 */ 422 public ShellLink(int type, int userType, String group, String name) throws Exception, 423 IllegalArgumentException 424 { 425 if ((type < MIN_TYPE) || (type > MAX_TYPE)) { throw (new IllegalArgumentException( 426 "the type parameter used an illegal value")); } 427 if (name == null) { throw (new IllegalArgumentException("the name parameter was null")); } 428 429 this.userType = userType; 430 431 initialize(); // com 432 433 // set the variables for currentUserLinkPath and allUsersLinkPath 434 setAllLinkPaths(); 435 436 if (group != null) 437 { 438 groupName = group; 439 } 440 linkName = name; 441 442 // load the link 443 linkFileName = fullLinkName(userType); 444 if (loadLink(linkFileName) != SL_OK) { throw (new Exception( 445 "reading of the file did not succeed")); } 446 447 // get a settings from the native side 448 get(); 449 } 450 451 /*--------------------------------------------------------------------------*/ 452 /** 453 * Initializes COM and gets an instance of the IShellLink interface. 454 * 455 * @exception Exception if problems are encountered 456 */ 457 private void initialize() throws Exception 458 { 459 try 460 { 461 Librarian.getInstance().loadLibrary("ShellLink", this); 462 } 463 catch (UnsatisfiedLinkError exception) 464 { 465 throw (new Exception("could not locate native library")); 466 } 467 468 try 469 { 470 if (initializeCOM() != SL_OK) 471 { 472 throw (new Exception("could not initialize COM")); 473 } 474 else 475 { 476 initializeSucceeded = true; 477 } 478 } 479 catch (Throwable exception) 480 { 481 throw (new Exception("unidentified problem initializing COM\n" + exception.toString())); 482 } 483 484 int successCode = getInterface(); 485 if (successCode != SL_OK) 486 { 487 releaseCOM(); 488 initializeSucceeded = false; 489 490 if (successCode == SL_OUT_OF_HANDLES) 491 { 492 throw (new Exception( 493 "could not get an instance of IShellLink, no more handles available")); 494 } 495 else 496 { 497 throw (new Exception( 498 "could not get an instance of IShellLink, failed to co-create instance")); 499 } 500 } 501 } 502 503 /*--------------------------------------------------------------------------*/ 504 /** 505 * Destructor, releases COM and frees native resources. 506 */ 507 protected void finalize() 508 { 509 releaseInterface(); 510 511 if (initializeSucceeded) 512 { 513 releaseCOM(); 514 initializeSucceeded = false; 515 } 516 } 517 518 /*--------------------------------------------------------------------------*/ 519 /** 520 * This method is used to free the library at the end of progam execution. After this call, any 521 * instance of this calss will not be usable any more! <b><i><u>Note that this method does NOT 522 * return!</u></i></b> <br> 523 * <br> 524 * <b>DO NOT CALL THIS METHOD DIRECTLY!</b><br> 525 * It is used by the librarian to free the native library before physically deleting it from its 526 * temporary loaction. A call to this method will freeze the application irrecoverably! 527 * 528 * @param name the name of the library to free. Use only the name and extension but not the 529 * path. 530 * 531 * @see com.izforge.izpack.util.NativeLibraryClient#freeLibrary 532 */ 533 public void freeLibrary(String name) 534 { 535 int result = releaseInterface(); 536 537 if (initializeSucceeded) 538 { 539 result = releaseCOM(); 540 initializeSucceeded = false; 541 } 542 543 FreeLibrary(name); 544 } 545 546 /*--------------------------------------------------------------------------*/ 547 /** 548 * Constructs and returns the full path for the link file. 549 * 550 * @param userType the type of user for the link path. 551 * 552 * @return the path to use for storing the link 553 * 554 * @see #CURRENT_USER 555 * @see #ALL_USERS 556 */ 557 private String fullLinkPath(int userType) 558 { 559 StringBuffer path = new StringBuffer(); 560 561 // ---------------------------------------------------- 562 // build the complete name 563 // ---------------------------------------------------- 564 if (userType == CURRENT_USER) 565 { 566 path.append(currentUserLinkPath); 567 } 568 else 569 { 570 path.append(allUsersLinkPath); 571 } 572 573 if ((groupName != null) && (groupName.length() > 0)) 574 { 575 path.append(File.separator); 576 path.append(groupName); 577 } 578 579 return (path.toString()); 580 } 581 582 /*--------------------------------------------------------------------------*/ 583 /** 584 * Constructs and returns the fully qualified name for the link file. 585 * 586 * @param userType the type of user for the link path. 587 * 588 * @return the fully qualified file name to use for storing the link 589 * 590 * @see #CURRENT_USER 591 * @see #ALL_USERS 592 */ 593 private String fullLinkName(int userType) 594 { 595 StringBuffer name = new StringBuffer(); 596 597 name.append(fullLinkPath(userType)); 598 599 name.append(File.separator); 600 name.append(linkName); 601 name.append(LINK_EXTENSION); 602 603 return (name.toString()); 604 } 605 606 /*--------------------------------------------------------------------------*/ 607 /** 608 * Sets all members on the native side. 609 * 610 * @exception Exception if any problem is encountered during this operation. 611 */ 612 private void set() throws Exception 613 { 614 if (SetArguments() != SL_OK) { throw (new Exception("could not set arguments")); } 615 if (SetDescription() != SL_OK) { throw (new Exception("could not set description")); } 616 if (SetHotkey() != SL_OK) { throw (new Exception("could not set hotkey")); } 617 if (SetIconLocation() != SL_OK) { throw (new Exception("could not set icon location")); } 618 if (SetPath() != SL_OK) { throw (new Exception("could not set target path")); } 619 if (SetShowCommand() != SL_OK) { throw (new Exception("could not set show command")); } 620 if (SetWorkingDirectory() != SL_OK) { throw (new Exception( 621 "could not set working directory")); } 622 623 } 624 625 /*--------------------------------------------------------------------------*/ 626 /** 627 * Gets all members from the native side. 628 * 629 * @exception Exception if any problem is encountered during this operation. 630 * 631 */ 632 private void get() throws Exception 633 { 634 if (GetArguments() != SL_OK) { throw (new Exception("could not get arguments")); } 635 if (GetDescription() != SL_OK) { throw (new Exception("could not get description")); } 636 if (GetHotkey() != SL_OK) { throw (new Exception("could not get hotkey")); } 637 if (GetIconLocation() != SL_OK) { throw (new Exception("could not get icon location")); } 638 if (GetPath() != SL_OK) { throw (new Exception("could not get target ath")); } 639 if (GetShowCommand() != SL_OK) { throw (new Exception("could not get show command")); } 640 if (GetWorkingDirectory() != SL_OK) { throw (new Exception( 641 "could not get working directory")); } 642 } 643 644 /*--------------------------------------------------------------------------*/ 645 /** 646 * Sets the name of the program group this ShellLinbk should be placed in. 647 * 648 * @param groupName the name of the program group 649 */ 650 public void setProgramGroup(String groupName) 651 { 652 this.groupName = groupName; 653 } 654 655 /*--------------------------------------------------------------------------*/ 656 /** 657 * Sets the command line arguments that will be passed to the target when the link is activated. 658 * 659 * @param arguments the command line arguments 660 * 661 * @see #getArguments 662 */ 663 public void setArguments(String arguments) 664 { 665 this.arguments = arguments; 666 } 667 668 /*--------------------------------------------------------------------------*/ 669 /** 670 * Sets the description string that is used to identify the link in a menu or on the desktop. 671 * 672 * @param description the descriptiojn string 673 * 674 * @see #getDescription 675 */ 676 public void setDescription(String description) 677 { 678 this.description = description; 679 } 680 681 /*--------------------------------------------------------------------------*/ 682 /** 683 * Sets the hotkey that can be used to activate the link. 684 * 685 * @param hotkey a valid Windows virtual key code. Modifiers (e.g. for alt or shift key) are 686 * added in the upper byte. Note that only the lower 16 bits for tis parameter are used. 687 * 688 * @see #getHotkey 689 */ 690 public void setHotkey(int hotkey) 691 { 692 this.hotkey = hotkey; 693 } 694 695 /*--------------------------------------------------------------------------*/ 696 /** 697 * Sets the location of the icon that is shown for the shortcut on the desktop. 698 * 699 * @param path a fully qualified file name of a file that contains the icon. 700 * @param index the index of the specific icon to use in the file. If there is only one icon in 701 * the file, use an index of 0. 702 * 703 * @see #getIconLocation 704 */ 705 public void setIconLocation(String path, int index) 706 { 707 this.iconPath = path; 708 this.iconIndex = index; 709 } 710 711 /*--------------------------------------------------------------------------*/ 712 /** 713 * Sets the absolute path to the shortcut target. 714 * 715 * @param path the fully qualified file name of the target 716 * 717 * @see #getTargetPath 718 */ 719 public void setTargetPath(String path) 720 { 721 this.targetPath = path; 722 } 723 724 /*--------------------------------------------------------------------------*/ 725 /** 726 * Sets the show command that is passed to the target application when the link is activated. 727 * The show command determines if the the window will be restored to the previous size, 728 * minimized, maximized or visible at all. <br> 729 * <br> 730 * <b>Note:</b><br> 731 * Using <code>HIDE</code> will cause the target window not to show at all. There is not even 732 * a button on the taskbar. This is a very useful setting when batch files are used to launch a 733 * Java application as it will then appear to run just like any native Windows application.<br> 734 * <b>Note1:</b><br> 735 * <code>HIDE</code> doesn't work in Win98 and newer systems.<br> 736 * use MINIMIZED (MINNOACTIVE), instead.<br> 737 * 738 * @param show the show command. Valid settings are: <br> 739 * <ul> 740 * <li><code>ShellLink.HIDE</code> (deprecated) 741 * <li><code>ShellLink.NORMAL</code> 742 * <li><code>ShellLink.MINNOACTIVE</code> 743 * <li><code>ShellLink.MAXIMIZED</code> 744 * </ul> 745 * 746 * @see #getShowCommand 747 */ 748 public void setShowCommand(int show) 749 { 750 if ((show < MIN_SHOW) || (show > MAX_SHOW)) { throw (new IllegalArgumentException( 751 "illegal value for show command " + show)); } 752 753 this.showCommand = show; 754 } 755 756 /*--------------------------------------------------------------------------*/ 757 /** 758 * Sets the working directory for the link target. 759 * 760 * @param dir the working directory 761 * 762 * @see #getWorkingDirectory 763 */ 764 public void setWorkingDirectory(String dir) 765 { 766 this.workingDirectory = dir; 767 } 768 769 /*--------------------------------------------------------------------------*/ 770 /** 771 * Sets the name shown in a menu or on the desktop for the link. 772 * 773 * @param name The name that the link should display on a menu or on the desktop. Do not include 774 * a file extension. 775 */ 776 public void setLinkName(String name) 777 { 778 linkName = name; 779 } 780 781 /*--------------------------------------------------------------------------*/ 782 /** 783 * Sets the type of link 784 * 785 * @param type The type of link desired. The following values can be set:<br> 786 * <ul> 787 * <li>{@link #DESKTOP} 788 * <li>{@link #PROGRAM_MENU} 789 * <li>{@link #START_MENU} 790 * <li>{@link #STARTUP} 791 * </ul> 792 * 793 * @exception IllegalArgumentException if an an invalid type is passed 794 * @throws UnsupportedEncodingException 795 */ 796 public void setLinkType(int type) throws IllegalArgumentException, UnsupportedEncodingException 797 { 798 if ((type < MIN_TYPE) || (type > MAX_TYPE)) { throw (new IllegalArgumentException( 799 "illegal value for type")); } 800 801 linkType = type; 802 803 // set curretnUsersLinkPath, allUsersLinkPath, sets userType to valid. 804 setAllLinkPaths(); 805 } 806 807 /** 808 * Returns the user type for the link. <br> 809 * <ul> 810 * <li>{@link #DESKTOP} 811 * <li>{@link #PROGRAM_MENU} 812 * <li>{@link #START_MENU} 813 * <li>{@link #STARTUP} 814 * </ul> 815 * <br> 816 * 817 * @see #setLinkType 818 */ 819 public int getLinkType() 820 { 821 return linkType; 822 } 823 824 /*--------------------------------------------------------------------------*/ 825 /** 826 * Sets the (ShellLink) user type for link 827 * 828 * @param type the type of user for the link. 829 * 830 * @see #CURRENT_USER 831 * @see #ALL_USERS 832 * 833 * @exception IllegalArgumentException if an an invalid type is passed 834 */ 835 public void setUserType(int type) throws IllegalArgumentException 836 { 837 if ((type == CURRENT_USER) || (type == ALL_USERS)) 838 { 839 userType = type; 840 } 841 else 842 { 843 throw (new IllegalArgumentException(type + " is not a recognized user type")); 844 } 845 } 846 847 /*--------------------------------------------------------------------------*/ 848 /** 849 * Returns the (ShellLink) user type for the link. Either {@link #CURRENT_USER} or 850 * {@link #ALL_USERS} 851 * 852 * @see #setUserType 853 */ 854 public int getUserType() 855 { 856 return userType; 857 } 858 859 /*--------------------------------------------------------------------------*/ 860 /** 861 * Returns the path where the links of the selected type are stroed. This method is useful for 862 * discovering which program groups already exist. 863 * 864 * @param userType the type of user for the link path. One of {@link #CURRENT_USER} or 865 * {@link #ALL_USERS} 866 * 867 * @return the path to the type of link set for this instance. 868 */ 869 public String getLinkPath(int userType) 870 { 871 String result = null; 872 if (userType == CURRENT_USER) 873 { 874 result = currentUserLinkPath; 875 } 876 else 877 { 878 result = allUsersLinkPath; 879 } 880 return result; 881 } 882 883 /*--------------------------------------------------------------------------*/ 884 /** 885 * Returns the command line that the link passes to the target. 886 * 887 * @return the command line 888 * 889 * @see #setArguments 890 */ 891 public String getArguments() 892 { 893 return (arguments); 894 } 895 896 /*--------------------------------------------------------------------------*/ 897 /** 898 * Returns the description for the link. 899 * 900 * @return the description 901 * 902 * @see #setDescription 903 */ 904 public String getDescription() 905 { 906 return (description); 907 } 908 909 /*--------------------------------------------------------------------------*/ 910 /** 911 * Retruns the hotkey that can be used to activate the link. 912 * 913 * @return the virtual keycode for the hotkey 914 * 915 * @see #setHotkey 916 */ 917 public int getHotkey() 918 { 919 return (hotkey); 920 } 921 922 /*--------------------------------------------------------------------------*/ 923 /** 924 * Returns the path and file name of the file that contains the icon that is associated with the 925 * link. 926 * 927 * @return the path to the icon 928 * 929 * @see #setIconLocation 930 */ 931 public String getIconLocation() 932 { 933 return (iconPath); 934 } 935 936 /*--------------------------------------------------------------------------*/ 937 /** 938 * Returns the index of the icon with the icon or resource file 939 * 940 * @return the index 941 * 942 * @see #setIconLocation 943 */ 944 public int getIconIndex() 945 { 946 return (iconIndex); 947 } 948 949 /*--------------------------------------------------------------------------*/ 950 /** 951 * Retruns the absolute path of the link target 952 * 953 * @return the path 954 * 955 * @see #setTargetPath 956 */ 957 public String getTargetPath() 958 { 959 return (targetPath); 960 } 961 962 /*--------------------------------------------------------------------------*/ 963 /** 964 * Returns the initial condition of the target window (HIDE, NORMAL, MINIMIZED, MAXIMIZED). 965 * 966 * @return the target show command 967 * 968 * @see #setShowCommand 969 */ 970 public int getShowCommand() 971 { 972 return (showCommand); 973 } 974 975 /*--------------------------------------------------------------------------*/ 976 /** 977 * Retruns the working deirectory for the link target. 978 * 979 * @return the working directory 980 * 981 * @see #setWorkingDirectory 982 */ 983 public String getWorkingDirectory() 984 { 985 return (workingDirectory); 986 } 987 988 /*--------------------------------------------------------------------------*/ 989 /** 990 * Returns the fully qualified file name under which the link is saved on disk. <b>Note:</b> 991 * this method returns valid results only if the instance was created from a file on disk or 992 * after a successful save operation. 993 * 994 * @return the fully qualified file name for the shell link 995 */ 996 public String getFileName() 997 { 998 return (linkFileName); 999 } 1000 1001 /*--------------------------------------------------------------------------*/ 1002 /** 1003 * Returns the path of the directory where the link file is stored, if it was necessary during 1004 * the previous save operation to create the directory. This method returns <code>null</code> 1005 * if no save operation was carried out or there was no need to create a directory during the 1006 * previous save operation. 1007 * 1008 * @return the path of the directory where the link file is stored or <code>null</code> if no 1009 * save operation was carried out or there was no need to create a directory during the previous 1010 * save operation. 1011 */ 1012 public String getDirectoryCreated() 1013 { 1014 return (linkDirectory); 1015 } 1016 1017 /*--------------------------------------------------------------------------*/ 1018 /** 1019 * Returns the name shown in a menu or on the desktop for the link. 1020 * 1021 * @return the name 1022 */ 1023 public String getLinkName() 1024 { 1025 return (linkName); 1026 } 1027 1028 /*--------------------------------------------------------------------------*/ 1029 /** 1030 * Returns the path for currentusersLink 1031 * 1032 * @return currentUsersLinkPath 1033 */ 1034 public String getcurrentUserLinkPath() 1035 { 1036 return currentUserLinkPath; 1037 } 1038 1039 /*--------------------------------------------------------------------------*/ 1040 /** 1041 * Returns the path for allusersLink 1042 * 1043 * @return allusersLinkPath 1044 */ 1045 public String getallUsersLinkPath() 1046 { 1047 return allUsersLinkPath; 1048 } 1049 1050 /*--------------------------------------------------------------------------*/ 1051 /** 1052 * Saves this link. 1053 * 1054 * @exception Exception if problems are encountered 1055 */ 1056 public void save() throws Exception 1057 { 1058 // set all values on the native side 1059 set(); 1060 1061 // make sure the target actually resolves 1062 int result = Resolve(); 1063 1064 if (result != SL_OK) { throw (new Exception("cannot resolve target")); } 1065 1066 // make sure the directory exists 1067 File directory = new File(fullLinkPath(userType)); 1068 1069 if (!directory.exists()) 1070 { 1071 directory.mkdirs(); 1072 linkDirectory = directory.getPath(); 1073 } 1074 else 1075 { 1076 linkDirectory = ""; 1077 } 1078 1079 // perform the save operation 1080 String saveTo = fullLinkName(userType); 1081 1082 result = saveLink(saveTo); 1083 1084 if (result == SL_NO_IPERSIST) 1085 { 1086 throw (new Exception("could not get handle for IPesist")); 1087 } 1088 else if (result == SL_NO_SAVE) { throw (new Exception("the save operation failed")); } 1089 1090 linkFileName = saveTo; 1091 } 1092 1093 /*--------------------------------------------------------------------------*/ 1094 /** 1095 * Saves this link to any desired location. 1096 * 1097 * @param name the fully qualified file name for the link 1098 * 1099 * @exception IllegalArgumentException if the parameter was null 1100 * @exception Exception if the save operation could not be carried out 1101 */ 1102 public void save(String name) throws Exception 1103 { 1104 if (name == null) { throw (new IllegalArgumentException("name was null")); } 1105 1106 // set all values on the native side 1107 set(); 1108 1109 // make sure the target actually resolves 1110 if (Resolve() != SL_OK) { throw (new Exception("cannot resolve target")); } 1111 1112 // make sure the directory exists 1113 File directory = new File(name.substring(0, name.lastIndexOf(File.separatorChar))); 1114 if (!directory.exists()) 1115 { 1116 directory.mkdirs(); 1117 linkDirectory = directory.getPath(); 1118 } 1119 else 1120 { 1121 linkDirectory = null; 1122 } 1123 1124 // perform the save operation 1125 if (saveLink(name) != SL_OK) { throw (new Exception("the save operation failed")); } 1126 1127 linkFileName = name; 1128 } 1129 1130 /*--------------------------------------------------------------------------*/ 1131 /** 1132 * sets currentUsersLinkPath and allUsersLinkPath. If the path is empty, resets userType to a 1133 * valid userType for this type of link. If no linkPaths are valid, an IllegalArgumentException 1134 * is thrown. 1135 * 1136 * @throws IllegalArgumentException 1137 * @throws UnsupportedEncodingException 1138 */ 1139 private void setAllLinkPaths() throws IllegalArgumentException 1140 { 1141 // sets currentUsersLinkPath and allUsersLinkPath 1142 GetFullLinkPath(CURRENT_USER, linkType); 1143 GetFullLinkPath(ALL_USERS, linkType); 1144 1145 // be sure userType is valid. Override initial choice if not. 1146 if (userType == CURRENT_USER && currentUserLinkPath.length() == 0) 1147 { 1148 userType = ALL_USERS; 1149 } 1150 else if (userType == ALL_USERS && allUsersLinkPath.length() == 0) 1151 { 1152 userType = CURRENT_USER; 1153 } 1154 1155 if ( allUsersLinkPath.length() == 0 && currentUserLinkPath.length() == 0) { throw (new IllegalArgumentException( 1156 "linkType " + linkType + " is invalid.")); } 1157 } 1158 1159} 1160/*---------------------------------------------------------------------------*/ 1161