0001: /*
0002: * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved.
0003: *
0004: * http://izpack.org/
0005: * http://izpack.codehaus.org/
0006: *
0007: * Copyright 2002 Elmar Grom
0008: *
0009: * Licensed under the Apache License, Version 2.0 (the "License");
0010: * you may not use this file except in compliance with the License.
0011: * You may obtain a copy of the License at
0012: *
0013: * http://www.apache.org/licenses/LICENSE-2.0
0014: *
0015: * Unless required by applicable law or agreed to in writing, software
0016: * distributed under the License is distributed on an "AS IS" BASIS,
0017: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0018: * See the License for the specific language governing permissions and
0019: * limitations under the License.
0020: */
0021:
0022: package com.izforge.izpack.util.os;
0023:
0024: import java.io.File;
0025: import java.io.UnsupportedEncodingException;
0026:
0027: import com.izforge.izpack.util.Librarian;
0028: import com.izforge.izpack.util.NativeLibraryClient;
0029:
0030: /*---------------------------------------------------------------------------*/
0031: /**
0032: * This class represents a MS-Windows shell link, aka shortcut. It supports creation, modification
0033: * and deletion as well as reporting on details of shell links. This class uses a number of native
0034: * methods to access the MS-Windows registry and load save and manipulate link data. The native code
0035: * is contained in the file <code>ShellLink.cpp</code>. <br>
0036: * <br>
0037: * For more detailed information on Windows shortcuts read the win32 documentation from Microsoft on
0038: * the IShellLink interface. There are also useful articles on this topic on the MIcrosoft website.
0039: * <br>
0040: * <br>
0041: * <A
0042: * HREF=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmgmt/html/msdn_shellnk1.asp>Using
0043: * Shell Links in Windows 95</A><br>
0044: * <A
0045: * HREF=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/ishelllink/ishelllink.asp>The
0046: * IShellLink interface</a><br>
0047: * <A
0048: * HREF=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/Shell/IFaces/IShellLink/IShellLink.asp>IShellLink</A>
0049: *
0050: * @version 0.0.1 / 1/21/02
0051: * @author Elmar Grom
0052: */
0053: /*---------------------------------------------------------------------------*/
0054: public class ShellLink implements NativeLibraryClient {
0055:
0056: // ------------------------------------------------------------------------
0057: // Constant Definitions
0058: // ------------------------------------------------------------------------
0059: /**
0060: * Note: each of the subclasses will convert these values as appropriate before calling the OS's
0061: * routines. For example Win 98 & up will use SW_SNOWMINNOACTIVE (7) when passed HIDE (0) or
0062: * MINIMIZED (2) <br>
0063: * <br>
0064: * and this conversion is done in Win_Shortcut.java
0065: */
0066: /**
0067: * Hide the window when starting. This is particularly useful when launching from a *.bat file,
0068: * because no DOS window and no button for the DOS window on the task bar will show! <br>
0069: * <br>
0070: * <b>Note:</b> this option is not available through the Windows 98+ UI!
0071: */
0072: public static final int HIDE = 0;
0073:
0074: /**
0075: * Show the window 'normal' when starting. Restores the window properties at the last shut-down.
0076: */
0077: public static final int NORMAL = 1;
0078:
0079: /**
0080: * Show the window minimized when starting. The window will not show but a corresponding button
0081: * in the task bar will. <p>
0082: *
0083: * Newer IShellLink only allows Normal, MinNoActive, Maximized.
0084: */
0085: public static final int MINIMIZED = 2;
0086:
0087: /** Show the window maximized when starting. */
0088: public static final int MAXIMIZED = 3;
0089:
0090: /**
0091: * Show the window minimized when starting. Note: for win98 and newer, use MINNOACTIVE instead
0092: * of MINIMIZED.
0093: */
0094: public static final int MINNOACTIVE = 7;
0095:
0096: private static final int MIN_SHOW = 0;
0097:
0098: private static final int MAX_SHOW = 7;
0099:
0100: // ------------------------------------------------------
0101: // Shortcut types
0102: // specific to ShellLink (Shortcut has different numbers).
0103: // ------------------------------------------------------
0104: /** This type of shortcut shows on the desktop */
0105: public static final int DESKTOP = 1;
0106:
0107: /** This type of shortcut shows in the program menu */
0108: public static final int PROGRAM_MENU = 2;
0109:
0110: /** This type of shortcut shows in the start menu */
0111: public static final int START_MENU = 3;
0112:
0113: /** This type of shortcut is executed at OS launch time */
0114: public static final int STARTUP = 4;
0115:
0116: private static final int MIN_TYPE = 1;
0117:
0118: private static final int MAX_TYPE = 4;
0119:
0120: // ------------------------------------------------------
0121: // Return values from nafive methods
0122: // ------------------------------------------------------
0123: /** Returned from native calls if the call was successful */
0124: private static final int SL_OK = 1;
0125:
0126: /** Unspecific return if a native call was not successful */
0127: private static final int SL_ERROR = -1;
0128:
0129: /**
0130: * Return value from native initialization functions if already initialized
0131: */
0132: private static final int SL_INITIALIZED = -2;
0133:
0134: /**
0135: * Return value from native uninitialization functions if never initialized
0136: */
0137: private static final int SL_NOT_INITIALIZED = -3;
0138:
0139: /**
0140: * Return value from native uninitialization functions if there are no more interface handles
0141: * available
0142: */
0143: private static final int SL_OUT_OF_HANDLES = -4;
0144:
0145: /**
0146: * Return value from native uninitialization functions if nohandle for the IPersist interface
0147: * could be obtained
0148: */
0149: private static final int SL_NO_IPERSIST = -5;
0150:
0151: /**
0152: * Return value from native uninitialization functions if the save operation fort the link
0153: * failed
0154: */
0155: private static final int SL_NO_SAVE = -6;
0156:
0157: /**
0158: * Return value if the function called had to deal with unexpected data types. This might be
0159: * returned by registry functions if they receive an unexpected data type from the registry.
0160: */
0161: private static final int SL_WRONG_DATA_TYPE = -7;
0162:
0163: // ------------------------------------------------------
0164: // Miscellaneous constants
0165: // ------------------------------------------------------
0166: private static final int UNINITIALIZED = -1;
0167:
0168: /** the extension that must be used for link files */
0169: private static final String LINK_EXTENSION = ".lnk";
0170:
0171: /** CURRENT_USER = 0; the constant to use for selecting the current user. */
0172: public static final int CURRENT_USER = 0;
0173:
0174: /** ALL_USERS = 1; the constant to use for selecting the all users. */
0175: public static final int ALL_USERS = 1;
0176:
0177: // ------------------------------------------------------------------------
0178: // Variable Declarations
0179: // ------------------------------------------------------------------------
0180: /**
0181: * This handle links us to a specific native instance. Do not use or modify, the variable is for
0182: * exclusive use by the native side.
0183: */
0184: private int nativeHandle = UNINITIALIZED;
0185:
0186: /**
0187: * Path to the location where links for the current user are stored. The exact content depends
0188: * on the circumstances. It can be set during object construction or from native code. It will
0189: * point to the location where links of the most recently requested type are stored.
0190: */
0191: private String currentUserLinkPath;
0192:
0193: /**
0194: * Path to the location where links for all users are stored. The exact content depends on the
0195: * circumstances. It can be set during object construction or from native code. It will point to
0196: * the location where links of the most recently requested type are stored.
0197: */
0198: private String allUsersLinkPath;
0199:
0200: private String groupName = "";
0201:
0202: private String linkName = "";
0203:
0204: /**
0205: * this is the fully qualified name of the link on disk. Note that this variable contains only
0206: * valid data if the link was created from a disk file or after a successful save operation. At
0207: * other times the content is upredicatable.
0208: */
0209: private String linkFileName = "";
0210:
0211: /**
0212: * Contains the directory where the link file is stored after any save operation that needs to
0213: * create that directory. Otherwise it contains <code>null</code>.
0214: */
0215: private String linkDirectory = "";
0216:
0217: private String arguments = "";
0218:
0219: private String description = "";
0220:
0221: private String iconPath = "";
0222:
0223: private String targetPath = "";
0224:
0225: private String workingDirectory = "";
0226:
0227: /**
0228: * there seems to be an error in JNI that causes an access violation if a String that is
0229: * accessed from native code borders on another type of variable. This caused problems in
0230: * <code>set()</code> For this reason, the dummy string is placed here. Observed with version:
0231: *
0232: * <pre>
0233: *
0234: *
0235: *
0236: * java version "1.3.0"
0237: * Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
0238: * Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)
0239: *
0240: *
0241: * </pre>
0242: */
0243: private String dummyString = "";
0244:
0245: private int hotkey = 0;
0246:
0247: private int iconIndex = 0;
0248:
0249: private int showCommand = NORMAL;
0250:
0251: private int linkType = DESKTOP;
0252:
0253: private int userType = CURRENT_USER;
0254:
0255: private boolean initializeSucceeded = false;
0256:
0257: // ------------------------------------------------------------------------
0258: // Native Methods
0259: // ------------------------------------------------------------------------
0260: // For documentation on these methods see ShellLink.cpp
0261: // ------------------------------------------------------------------------
0262: private native int initializeCOM();
0263:
0264: private native int releaseCOM();
0265:
0266: private native int getInterface();
0267:
0268: private native int releaseInterface();
0269:
0270: private native int GetArguments();
0271:
0272: private native int GetDescription();
0273:
0274: private native int GetHotkey();
0275:
0276: private native int GetIconLocation();
0277:
0278: private native int GetPath();
0279:
0280: private native int GetShowCommand();
0281:
0282: private native int GetWorkingDirectory();
0283:
0284: private native int Resolve();
0285:
0286: private native int SetArguments();
0287:
0288: private native int SetDescription();
0289:
0290: private native int SetHotkey();
0291:
0292: private native int SetIconLocation();
0293:
0294: private native int SetPath();
0295:
0296: private native int SetShowCommand();
0297:
0298: private native int SetWorkingDirectory();
0299:
0300: private native int saveLink(String name);
0301:
0302: private native int loadLink(String name);
0303:
0304: private native int GetFullLinkPath(int usertype, int linktype);
0305:
0306: /**
0307: * This method is used to free the library at the end of progam execution. After this call, any
0308: * instance of this calss will not be usable any more!
0309: */
0310: private native void FreeLibrary(String name);
0311:
0312: /**
0313: * Creates an instance of <code>ShellLink</code> of a specific type. Initializes
0314: * currentUserLinkPath and allUsersLinkPath.
0315: * <p>
0316: *
0317: * A LinkPath is empty if the combination of linkType and userType, are not valid.
0318: * <p>
0319: *
0320: * Note: If a linkPath is empty, the userType is reset to the other userType.
0321: * <p>
0322: *
0323: * If both linkPaths are empty, an IllegalArgumentException is thrown.
0324: *
0325: * @param type The type of link desired. The following values can be set:<br>
0326: * <ul>
0327: * <li><code>ShellLink.DESKTOP</code>
0328: * <li><code>ShellLink.PROGRAM_MENU</code>
0329: * <li><code>ShellLink.START_MENU</code>
0330: * <li><code>ShellLink.STARTUP</code>
0331: * </ul>
0332: * @param name The name that the link should display on a menu or on the desktop. Do not include
0333: * a file extension.
0334: *
0335: * @exception IllegalArgumentException if any of the call parameters are incorrect, or if no
0336: * linkPaths are returned.
0337: * @exception Exception if problems are encountered in initializing the native interface
0338: */
0339: public ShellLink(int type, String name) throws Exception,
0340: IllegalArgumentException {
0341: if ((type < MIN_TYPE) || (type > MAX_TYPE)) {
0342: throw (new IllegalArgumentException(
0343: "the type parameter used an illegal value"));
0344: }
0345: if (name == null) {
0346: throw (new IllegalArgumentException(
0347: "the name parameter was null"));
0348: }
0349:
0350: linkName = name;
0351: linkType = type;
0352:
0353: initialize(); // com
0354:
0355: // set curretnUsersLinkPath, allUsersLinkPath, sets userType to valid.
0356: setAllLinkPaths();
0357: }
0358:
0359: /*--------------------------------------------------------------------------*/
0360: /**
0361: * Creates an instance of <code>ShellLink</code> from an existing shell link on disk.
0362: *
0363: * @param name the fully qualified file name of the link.
0364: * @param userType the type of user for the link path.
0365: *
0366: * @see #CURRENT_USER
0367: * @see #ALL_USERS
0368: *
0369: * @exception IllegalArgumentException if the name was null
0370: * @exception Exception if problems are encountered in reading the file
0371: */
0372: public ShellLink(String name, int userType) throws Exception,
0373: IllegalArgumentException {
0374: if (name == null) {
0375: throw (new IllegalArgumentException(
0376: "the name parameter was null"));
0377: }
0378:
0379: this .userType = userType;
0380:
0381: initialize(); // com
0382:
0383: // store the individual parts of the path for later use
0384: int pathEnd = name.lastIndexOf(File.separator);
0385: int nameStart = pathEnd + 1;
0386: int nameEnd = name.lastIndexOf('.');
0387: if (nameEnd < 0) {
0388: throw (new Exception("illegal file name"));
0389: }
0390: linkName = name.substring(nameStart, nameEnd);
0391:
0392: if (userType == CURRENT_USER) {
0393: currentUserLinkPath = name.substring(0, pathEnd);
0394: } else {
0395: allUsersLinkPath = name.substring(0, pathEnd);
0396: }
0397:
0398: linkFileName = fullLinkName(userType);
0399: if (loadLink(linkFileName) != SL_OK) {
0400: throw (new Exception("reading of the file did not succeed"));
0401: }
0402:
0403: // get all settings from the native side
0404: get();
0405: }
0406:
0407: /*--------------------------------------------------------------------------*/
0408: /**
0409: * Creates an instance of <code>ShellLink</code> from an existing shell link on disk.
0410: *
0411: * @param type The type of link, one of the following values: <br>
0412: * <ul>
0413: * <li><code>ShellLink.DESKTOP</code>
0414: * <li><code>ShellLink.PROGRAM_MENU</code>
0415: * <li><code>ShellLink.START_MENU</code>
0416: * <li><code>ShellLink.STARTUP</code>
0417: * </ul>
0418: * @param userType the type of user for the link path.
0419: * @param group The program group (directory) of this link. If the link is not part of a program
0420: * group, pass an empty string or null for this parameter. (...\\Desktop\\group).
0421: * @param name The file name of this link. Do not include a file extension.
0422: *
0423: * @see #CURRENT_USER
0424: * @see #ALL_USERS
0425: *
0426: * @exception IllegalArgumentException if any of the call parameters are incorrect
0427: * @exception Exception if problems are encountered in initializing the native interface
0428: */
0429: public ShellLink(int type, int userType, String group, String name)
0430: throws Exception, IllegalArgumentException {
0431: if ((type < MIN_TYPE) || (type > MAX_TYPE)) {
0432: throw (new IllegalArgumentException(
0433: "the type parameter used an illegal value"));
0434: }
0435: if (name == null) {
0436: throw (new IllegalArgumentException(
0437: "the name parameter was null"));
0438: }
0439:
0440: this .userType = userType;
0441:
0442: initialize(); // com
0443:
0444: // set the variables for currentUserLinkPath and allUsersLinkPath
0445: setAllLinkPaths();
0446:
0447: if (group != null) {
0448: groupName = group;
0449: }
0450: linkName = name;
0451:
0452: // load the link
0453: linkFileName = fullLinkName(userType);
0454: if (loadLink(linkFileName) != SL_OK) {
0455: throw (new Exception("reading of the file did not succeed"));
0456: }
0457:
0458: // get a settings from the native side
0459: get();
0460: }
0461:
0462: /*--------------------------------------------------------------------------*/
0463: /**
0464: * Initializes COM and gets an instance of the IShellLink interface.
0465: *
0466: * @exception Exception if problems are encountered
0467: */
0468: private void initialize() throws Exception {
0469: try {
0470: Librarian.getInstance().loadLibrary("ShellLink", this );
0471: } catch (UnsatisfiedLinkError exception) {
0472: throw (new Exception("could not locate native library"));
0473: }
0474:
0475: try {
0476: if (initializeCOM() != SL_OK) {
0477: throw (new Exception("could not initialize COM"));
0478: } else {
0479: initializeSucceeded = true;
0480: }
0481: } catch (Throwable exception) {
0482: throw (new Exception(
0483: "unidentified problem initializing COM\n"
0484: + exception.toString()));
0485: }
0486:
0487: int successCode = getInterface();
0488: if (successCode != SL_OK) {
0489: releaseCOM();
0490: initializeSucceeded = false;
0491:
0492: if (successCode == SL_OUT_OF_HANDLES) {
0493: throw (new Exception(
0494: "could not get an instance of IShellLink, no more handles available"));
0495: } else {
0496: throw (new Exception(
0497: "could not get an instance of IShellLink, failed to co-create instance"));
0498: }
0499: }
0500: }
0501:
0502: /*--------------------------------------------------------------------------*/
0503: /**
0504: * Destructor, releases COM and frees native resources.
0505: */
0506: protected void finalize() throws Throwable {
0507: releaseInterface();
0508:
0509: if (initializeSucceeded) {
0510: releaseCOM();
0511: initializeSucceeded = false;
0512: }
0513: super .finalize();
0514: }
0515:
0516: /*--------------------------------------------------------------------------*/
0517: /**
0518: * This method is used to free the library at the end of progam execution. After this call, any
0519: * instance of this calss will not be usable any more! <b><i><u>Note that this method does NOT
0520: * return!</u></i></b> <br>
0521: * <br>
0522: * <b>DO NOT CALL THIS METHOD DIRECTLY!</b><br>
0523: * It is used by the librarian to free the native library before physically deleting it from its
0524: * temporary loaction. A call to this method will freeze the application irrecoverably!
0525: *
0526: * @param name the name of the library to free. Use only the name and extension but not the
0527: * path.
0528: *
0529: * @see com.izforge.izpack.util.NativeLibraryClient#freeLibrary
0530: */
0531: public void freeLibrary(String name) {
0532: int result = releaseInterface();
0533:
0534: if (initializeSucceeded) {
0535: result = releaseCOM();
0536: initializeSucceeded = false;
0537: }
0538:
0539: FreeLibrary(name);
0540: }
0541:
0542: /*--------------------------------------------------------------------------*/
0543: /**
0544: * Constructs and returns the full path for the link file.
0545: *
0546: * @param userType the type of user for the link path.
0547: *
0548: * @return the path to use for storing the link
0549: *
0550: * @see #CURRENT_USER
0551: * @see #ALL_USERS
0552: */
0553: private String fullLinkPath(int userType) {
0554: StringBuffer path = new StringBuffer();
0555:
0556: // ----------------------------------------------------
0557: // build the complete name
0558: // ----------------------------------------------------
0559: if (userType == CURRENT_USER) {
0560: path.append(currentUserLinkPath);
0561: } else {
0562: path.append(allUsersLinkPath);
0563: }
0564:
0565: if ((groupName != null) && (groupName.length() > 0)) {
0566: path.append(File.separator);
0567: path.append(groupName);
0568: }
0569:
0570: return (path.toString());
0571: }
0572:
0573: /*--------------------------------------------------------------------------*/
0574: /**
0575: * Constructs and returns the fully qualified name for the link file.
0576: *
0577: * @param userType the type of user for the link path.
0578: *
0579: * @return the fully qualified file name to use for storing the link
0580: *
0581: * @see #CURRENT_USER
0582: * @see #ALL_USERS
0583: */
0584: private String fullLinkName(int userType) {
0585: StringBuffer name = new StringBuffer();
0586:
0587: name.append(fullLinkPath(userType));
0588:
0589: name.append(File.separator);
0590: name.append(linkName);
0591: name.append(LINK_EXTENSION);
0592:
0593: return (name.toString());
0594: }
0595:
0596: /*--------------------------------------------------------------------------*/
0597: /**
0598: * Sets all members on the native side.
0599: *
0600: * @exception Exception if any problem is encountered during this operation.
0601: */
0602: private void set() throws Exception {
0603: if (SetArguments() != SL_OK) {
0604: throw (new Exception("could not set arguments"));
0605: }
0606: if (SetDescription() != SL_OK) {
0607: throw (new Exception("could not set description"));
0608: }
0609: if (SetHotkey() != SL_OK) {
0610: throw (new Exception("could not set hotkey"));
0611: }
0612: if (SetIconLocation() != SL_OK) {
0613: throw (new Exception("could not set icon location"));
0614: }
0615: if (SetPath() != SL_OK) {
0616: throw (new Exception("could not set target path"));
0617: }
0618: if (SetShowCommand() != SL_OK) {
0619: throw (new Exception("could not set show command"));
0620: }
0621: if (SetWorkingDirectory() != SL_OK) {
0622: throw (new Exception("could not set working directory"));
0623: }
0624:
0625: }
0626:
0627: /*--------------------------------------------------------------------------*/
0628: /**
0629: * Gets all members from the native side.
0630: *
0631: * @exception Exception if any problem is encountered during this operation.
0632: *
0633: */
0634: private void get() throws Exception {
0635: if (GetArguments() != SL_OK) {
0636: throw (new Exception("could not get arguments"));
0637: }
0638: if (GetDescription() != SL_OK) {
0639: throw (new Exception("could not get description"));
0640: }
0641: if (GetHotkey() != SL_OK) {
0642: throw (new Exception("could not get hotkey"));
0643: }
0644: if (GetIconLocation() != SL_OK) {
0645: throw (new Exception("could not get icon location"));
0646: }
0647: if (GetPath() != SL_OK) {
0648: throw (new Exception("could not get target ath"));
0649: }
0650: if (GetShowCommand() != SL_OK) {
0651: throw (new Exception("could not get show command"));
0652: }
0653: if (GetWorkingDirectory() != SL_OK) {
0654: throw (new Exception("could not get working directory"));
0655: }
0656: }
0657:
0658: /*--------------------------------------------------------------------------*/
0659: /**
0660: * Sets the name of the program group this ShellLinbk should be placed in.
0661: *
0662: * @param groupName the name of the program group
0663: */
0664: public void setProgramGroup(String groupName) {
0665: this .groupName = groupName;
0666: }
0667:
0668: /*--------------------------------------------------------------------------*/
0669: /**
0670: * Sets the command line arguments that will be passed to the target when the link is activated.
0671: *
0672: * @param arguments the command line arguments
0673: *
0674: * @see #getArguments
0675: */
0676: public void setArguments(String arguments) {
0677: this .arguments = arguments;
0678: }
0679:
0680: /*--------------------------------------------------------------------------*/
0681: /**
0682: * Sets the description string that is used to identify the link in a menu or on the desktop.
0683: *
0684: * @param description the descriptiojn string
0685: *
0686: * @see #getDescription
0687: */
0688: public void setDescription(String description) {
0689: this .description = description;
0690: }
0691:
0692: /*--------------------------------------------------------------------------*/
0693: /**
0694: * Sets the hotkey that can be used to activate the link.
0695: *
0696: * @param hotkey a valid Windows virtual key code. Modifiers (e.g. for alt or shift key) are
0697: * added in the upper byte. Note that only the lower 16 bits for tis parameter are used.
0698: *
0699: * @see #getHotkey
0700: */
0701: public void setHotkey(int hotkey) {
0702: this .hotkey = hotkey;
0703: }
0704:
0705: /*--------------------------------------------------------------------------*/
0706: /**
0707: * Sets the location of the icon that is shown for the shortcut on the desktop.
0708: *
0709: * @param path a fully qualified file name of a file that contains the icon.
0710: * @param index the index of the specific icon to use in the file. If there is only one icon in
0711: * the file, use an index of 0.
0712: *
0713: * @see #getIconLocation
0714: */
0715: public void setIconLocation(String path, int index) {
0716: this .iconPath = path;
0717: this .iconIndex = index;
0718: }
0719:
0720: /*--------------------------------------------------------------------------*/
0721: /**
0722: * Sets the absolute path to the shortcut target.
0723: *
0724: * @param path the fully qualified file name of the target
0725: *
0726: * @see #getTargetPath
0727: */
0728: public void setTargetPath(String path) {
0729: this .targetPath = path;
0730: }
0731:
0732: /*--------------------------------------------------------------------------*/
0733: /**
0734: * Sets the show command that is passed to the target application when the link is activated.
0735: * The show command determines if the the window will be restored to the previous size,
0736: * minimized, maximized or visible at all. <br>
0737: * <br>
0738: * <b>Note:</b><br>
0739: * Using <code>HIDE</code> will cause the target window not to show at all. There is not even
0740: * a button on the taskbar. This is a very useful setting when batch files are used to launch a
0741: * Java application as it will then appear to run just like any native Windows application.<br>
0742: * <b>Note1:</b><br>
0743: * <code>HIDE</code> doesn't work in Win98 and newer systems.<br>
0744: * use MINIMIZED (MINNOACTIVE), instead.<br>
0745: *
0746: * @param show the show command. Valid settings are: <br>
0747: * <ul>
0748: * <li><code>ShellLink.HIDE</code> (deprecated)
0749: * <li><code>ShellLink.NORMAL</code>
0750: * <li><code>ShellLink.MINNOACTIVE</code>
0751: * <li><code>ShellLink.MAXIMIZED</code>
0752: * </ul>
0753: *
0754: * @see #getShowCommand
0755: */
0756: public void setShowCommand(int show) {
0757: if ((show < MIN_SHOW) || (show > MAX_SHOW)) {
0758: throw (new IllegalArgumentException(
0759: "illegal value for show command " + show));
0760: }
0761:
0762: this .showCommand = show;
0763: }
0764:
0765: /*--------------------------------------------------------------------------*/
0766: /**
0767: * Sets the working directory for the link target.
0768: *
0769: * @param dir the working directory
0770: *
0771: * @see #getWorkingDirectory
0772: */
0773: public void setWorkingDirectory(String dir) {
0774: this .workingDirectory = dir;
0775: }
0776:
0777: /*--------------------------------------------------------------------------*/
0778: /**
0779: * Sets the name shown in a menu or on the desktop for the link.
0780: *
0781: * @param name The name that the link should display on a menu or on the desktop. Do not include
0782: * a file extension.
0783: */
0784: public void setLinkName(String name) {
0785: linkName = name;
0786: }
0787:
0788: /*--------------------------------------------------------------------------*/
0789: /**
0790: * Sets the type of link
0791: *
0792: * @param type The type of link desired. The following values can be set:<br>
0793: * <ul>
0794: * <li>{@link #DESKTOP}
0795: * <li>{@link #PROGRAM_MENU}
0796: * <li>{@link #START_MENU}
0797: * <li>{@link #STARTUP}
0798: * </ul>
0799: *
0800: * @exception IllegalArgumentException if an an invalid type is passed
0801: * @throws UnsupportedEncodingException
0802: */
0803: public void setLinkType(int type) throws IllegalArgumentException,
0804: UnsupportedEncodingException {
0805: if ((type < MIN_TYPE) || (type > MAX_TYPE)) {
0806: throw (new IllegalArgumentException(
0807: "illegal value for type"));
0808: }
0809:
0810: linkType = type;
0811:
0812: // set curretnUsersLinkPath, allUsersLinkPath, sets userType to valid.
0813: setAllLinkPaths();
0814: }
0815:
0816: /**
0817: * Returns the user type for the link. <br>
0818: * <ul>
0819: * <li>{@link #DESKTOP}
0820: * <li>{@link #PROGRAM_MENU}
0821: * <li>{@link #START_MENU}
0822: * <li>{@link #STARTUP}
0823: * </ul>
0824: * <br>
0825: *
0826: * @see #setLinkType
0827: */
0828: public int getLinkType() {
0829: return linkType;
0830: }
0831:
0832: /*--------------------------------------------------------------------------*/
0833: /**
0834: * Sets the (ShellLink) user type for link
0835: *
0836: * @param type the type of user for the link.
0837: *
0838: * @see #CURRENT_USER
0839: * @see #ALL_USERS
0840: *
0841: * @exception IllegalArgumentException if an an invalid type is passed
0842: */
0843: public void setUserType(int type) throws IllegalArgumentException {
0844: if ((type == CURRENT_USER) || (type == ALL_USERS)) {
0845: userType = type;
0846: } else {
0847: throw (new IllegalArgumentException(type
0848: + " is not a recognized user type"));
0849: }
0850: }
0851:
0852: /*--------------------------------------------------------------------------*/
0853: /**
0854: * Returns the (ShellLink) user type for the link. Either {@link #CURRENT_USER} or
0855: * {@link #ALL_USERS}
0856: *
0857: * @see #setUserType
0858: */
0859: public int getUserType() {
0860: return userType;
0861: }
0862:
0863: /*--------------------------------------------------------------------------*/
0864: /**
0865: * Returns the path where the links of the selected type are stroed. This method is useful for
0866: * discovering which program groups already exist.
0867: *
0868: * @param userType the type of user for the link path. One of {@link #CURRENT_USER} or
0869: * {@link #ALL_USERS}
0870: *
0871: * @return the path to the type of link set for this instance.
0872: */
0873: public String getLinkPath(int userType) {
0874: String result = null;
0875: if (userType == CURRENT_USER) {
0876: result = currentUserLinkPath;
0877: } else {
0878: result = allUsersLinkPath;
0879: }
0880: return result;
0881: }
0882:
0883: /*--------------------------------------------------------------------------*/
0884: /**
0885: * Returns the command line that the link passes to the target.
0886: *
0887: * @return the command line
0888: *
0889: * @see #setArguments
0890: */
0891: public String getArguments() {
0892: return (arguments);
0893: }
0894:
0895: /*--------------------------------------------------------------------------*/
0896: /**
0897: * Returns the description for the link.
0898: *
0899: * @return the description
0900: *
0901: * @see #setDescription
0902: */
0903: public String getDescription() {
0904: return (description);
0905: }
0906:
0907: /*--------------------------------------------------------------------------*/
0908: /**
0909: * Retruns the hotkey that can be used to activate the link.
0910: *
0911: * @return the virtual keycode for the hotkey
0912: *
0913: * @see #setHotkey
0914: */
0915: public int getHotkey() {
0916: return (hotkey);
0917: }
0918:
0919: /*--------------------------------------------------------------------------*/
0920: /**
0921: * Returns the path and file name of the file that contains the icon that is associated with the
0922: * link.
0923: *
0924: * @return the path to the icon
0925: *
0926: * @see #setIconLocation
0927: */
0928: public String getIconLocation() {
0929: return (iconPath);
0930: }
0931:
0932: /*--------------------------------------------------------------------------*/
0933: /**
0934: * Returns the index of the icon with the icon or resource file
0935: *
0936: * @return the index
0937: *
0938: * @see #setIconLocation
0939: */
0940: public int getIconIndex() {
0941: return (iconIndex);
0942: }
0943:
0944: /*--------------------------------------------------------------------------*/
0945: /**
0946: * Retruns the absolute path of the link target
0947: *
0948: * @return the path
0949: *
0950: * @see #setTargetPath
0951: */
0952: public String getTargetPath() {
0953: return (targetPath);
0954: }
0955:
0956: /*--------------------------------------------------------------------------*/
0957: /**
0958: * Returns the initial condition of the target window (HIDE, NORMAL, MINIMIZED, MAXIMIZED).
0959: *
0960: * @return the target show command
0961: *
0962: * @see #setShowCommand
0963: */
0964: public int getShowCommand() {
0965: return (showCommand);
0966: }
0967:
0968: /*--------------------------------------------------------------------------*/
0969: /**
0970: * Retruns the working deirectory for the link target.
0971: *
0972: * @return the working directory
0973: *
0974: * @see #setWorkingDirectory
0975: */
0976: public String getWorkingDirectory() {
0977: return (workingDirectory);
0978: }
0979:
0980: /*--------------------------------------------------------------------------*/
0981: /**
0982: * Returns the fully qualified file name under which the link is saved on disk. <b>Note:</b>
0983: * this method returns valid results only if the instance was created from a file on disk or
0984: * after a successful save operation.
0985: *
0986: * @return the fully qualified file name for the shell link
0987: */
0988: public String getFileName() {
0989: return (linkFileName);
0990: }
0991:
0992: /*--------------------------------------------------------------------------*/
0993: /**
0994: * Returns the path of the directory where the link file is stored, if it was necessary during
0995: * the previous save operation to create the directory. This method returns <code>null</code>
0996: * if no save operation was carried out or there was no need to create a directory during the
0997: * previous save operation.
0998: *
0999: * @return the path of the directory where the link file is stored or <code>null</code> if no
1000: * save operation was carried out or there was no need to create a directory during the previous
1001: * save operation.
1002: */
1003: public String getDirectoryCreated() {
1004: return (linkDirectory);
1005: }
1006:
1007: /*--------------------------------------------------------------------------*/
1008: /**
1009: * Returns the name shown in a menu or on the desktop for the link.
1010: *
1011: * @return the name
1012: */
1013: public String getLinkName() {
1014: return (linkName);
1015: }
1016:
1017: /*--------------------------------------------------------------------------*/
1018: /**
1019: * Returns the path for currentusersLink
1020: *
1021: * @return currentUsersLinkPath
1022: */
1023: public String getcurrentUserLinkPath() {
1024: return currentUserLinkPath;
1025: }
1026:
1027: /*--------------------------------------------------------------------------*/
1028: /**
1029: * Returns the path for allusersLink
1030: *
1031: * @return allusersLinkPath
1032: */
1033: public String getallUsersLinkPath() {
1034: return allUsersLinkPath;
1035: }
1036:
1037: /*--------------------------------------------------------------------------*/
1038: /**
1039: * Saves this link.
1040: *
1041: * @exception Exception if problems are encountered
1042: */
1043: public void save() throws Exception {
1044: // set all values on the native side
1045: set();
1046:
1047: // make sure the target actually resolves
1048: int result = Resolve();
1049:
1050: if (result != SL_OK) {
1051: throw (new Exception("cannot resolve target"));
1052: }
1053:
1054: // make sure the directory exists
1055: File directory = new File(fullLinkPath(userType));
1056:
1057: if (!directory.exists()) {
1058: directory.mkdirs();
1059: linkDirectory = directory.getPath();
1060: } else {
1061: linkDirectory = "";
1062: }
1063:
1064: // perform the save operation
1065: String saveTo = fullLinkName(userType);
1066:
1067: result = saveLink(saveTo);
1068:
1069: if (result == SL_NO_IPERSIST) {
1070: throw (new Exception("could not get handle for IPesist"));
1071: } else if (result == SL_NO_SAVE) {
1072: throw (new Exception("the save operation failed"));
1073: }
1074:
1075: linkFileName = saveTo;
1076: }
1077:
1078: /*--------------------------------------------------------------------------*/
1079: /**
1080: * Saves this link to any desired location.
1081: *
1082: * @param name the fully qualified file name for the link
1083: *
1084: * @exception IllegalArgumentException if the parameter was null
1085: * @exception Exception if the save operation could not be carried out
1086: */
1087: public void save(String name) throws Exception {
1088: if (name == null) {
1089: throw (new IllegalArgumentException("name was null"));
1090: }
1091:
1092: // set all values on the native side
1093: set();
1094:
1095: // make sure the target actually resolves
1096: if (Resolve() != SL_OK) {
1097: throw (new Exception("cannot resolve target"));
1098: }
1099:
1100: // make sure the directory exists
1101: File directory = new File(name.substring(0, name
1102: .lastIndexOf(File.separatorChar)));
1103: if (!directory.exists()) {
1104: directory.mkdirs();
1105: linkDirectory = directory.getPath();
1106: } else {
1107: linkDirectory = null;
1108: }
1109:
1110: // perform the save operation
1111: if (saveLink(name) != SL_OK) {
1112: throw (new Exception("the save operation failed"));
1113: }
1114:
1115: linkFileName = name;
1116: }
1117:
1118: /*--------------------------------------------------------------------------*/
1119: /**
1120: * sets currentUsersLinkPath and allUsersLinkPath. If the path is empty, resets userType to a
1121: * valid userType for this type of link. If no linkPaths are valid, an IllegalArgumentException
1122: * is thrown.
1123: *
1124: * @throws IllegalArgumentException
1125: * @throws UnsupportedEncodingException
1126: */
1127: private void setAllLinkPaths() throws IllegalArgumentException {
1128: // sets currentUsersLinkPath and allUsersLinkPath
1129: GetFullLinkPath(CURRENT_USER, linkType);
1130: GetFullLinkPath(ALL_USERS, linkType);
1131:
1132: // be sure userType is valid. Override initial choice if not.
1133: if (userType == CURRENT_USER
1134: && currentUserLinkPath.length() == 0) {
1135: userType = ALL_USERS;
1136: } else if (userType == ALL_USERS
1137: && allUsersLinkPath.length() == 0) {
1138: userType = CURRENT_USER;
1139: }
1140:
1141: if (allUsersLinkPath.length() == 0
1142: && currentUserLinkPath.length() == 0) {
1143: throw (new IllegalArgumentException("linkType " + linkType
1144: + " is invalid."));
1145: }
1146: }
1147:
1148: }
1149: /*---------------------------------------------------------------------------*/
|