Statistics
| Revision:

root / import / ext3D / trunk / install-extension3d / IzPack / src / lib / com / izforge / izpack / util / os / ShellLink.java @ 15280

History | View | Annotate | Download (38.1 KB)

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

    
27
package   com.izforge.izpack.util.os;
28

    
29
import java.io.File;
30

    
31
import com.izforge.izpack.util.Librarian;
32
import com.izforge.izpack.util.NativeLibraryClient;
33

    
34
/*---------------------------------------------------------------------------*/
35
/**
36
 * This class represents a MS-Windows shell link, aka shortcut. It
37
 * supports creation, modification and deletion as well as reporting on
38
 * details of shell links. This class uses a number of native methods to
39
 * access the MS-Windows registry and load save and manipulate link data.
40
 * The native code is contained in the file <code>ShellLink.cpp</code>.
41
 * <br><br>
42
 * For more detailed information on Windows shortcuts read the win32
43
 * documentation from Microsoft on the IShellLink interface. There are
44
 * also useful articles on this topic on the MIcrosoft website.
45
 * <br><br>
46
 * <A HREF=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmgmt/html/msdn_shellnk1.asp>Using Shell Links in Windows 95</A><br>
47
 * <A HREF=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/ishelllink/ishelllink.asp>The IShellLink interface</a><br>
48
 * <A HREF=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/Shell/IFaces/IShellLink/IShellLink.asp>IShellLink</A>
49
 *
50
 * @version  0.0.1 / 1/21/02
51
 * @author   Elmar Grom
52
 */
53
/*---------------------------------------------------------------------------*/
54
public class ShellLink implements NativeLibraryClient
55
{
56
  // ------------------------------------------------------------------------
57
  // Constant Definitions
58
  // ------------------------------------------------------------------------
59
  /** Note: each of the subclasses will convert these values as appropriate
60
      before calling the OS's routines.  For example Win 98 & up will use
61
          SW_SNOWMINNOACTIVE (7) when passed HIDE (0) or MINIMIZED (2) <br><br>
62
          and this conversion is done in Win_Shortcut.java */
63
  /** Hide the window when starting. This is particularly useful when
64
      launching from a *.bat file, because no DOS window and no button
65
      for the DOS window on the task bar will show!
66
      <br><br>
67
      <b>Note:</b> this option is not available through the Windows 98+ UI! */
68
  public  static final int      HIDE          = 0;
69
  /** Show the window 'normal' when starting. Restores the window properties
70
      at the last shut-down. */
71
  public  static final int      NORMAL        = 1;
72
  /** Show the window minimized when starting. The window will not show but
73
      a corresponding button in the task bar will. */
74
  /** newer IShellLink only allows Normal, MinNoActive, Maximized.  */
75
  public  static final int      MINIMIZED     = 2;
76
  /** Show the window maximized when starting. */
77
  public  static final int      MAXIMIZED     = 3;
78
  /** Show the window minimized when starting. 
79
          note- for win98 and newer,
80
          use MINNOACTIVE instead of MINIMIZED */
81
  public  static final int      MINNOACTIVE   = 7;
82

    
83
  private static final int      MIN_SHOW      = 0;  
84
  private static final int      MAX_SHOW      = 7;  
85

    
86
  // ------------------------------------------------------
87
  // Shortcut types
88
  // specific to ShellLink (Shortcut has different numbers).
89
  // ------------------------------------------------------
90
  /** This type of shortcut shows on the desktop */
91
  public  static final int      DESKTOP       = 1;
92
  /** This type of shortcut shows in the program menu */
93
  public  static final int      PROGRAM_MENU  = 2;
94
  /** This type of shortcut shows in the start menu */
95
  public  static final int      START_MENU    = 3;
96
  /** This type of shortcut is executed at OS launch time  */
97
  public  static final int      STARTUP       = 4;
98

    
99
  private static final int      MIN_TYPE      = 1;  
100
  private static final int      MAX_TYPE      = 4;  
101

    
102
  // ------------------------------------------------------
103
  // Return values from nafive methods
104
  // ------------------------------------------------------
105
  /** Returned from native calls if the call was successful */
106
  private static final int      SL_OK               =  1;
107
  /** Unspecific return if a native call was not successful */
108
  private static final int      SL_ERROR            = -1;
109
  /** Return value from native initialization functions if
110
      already initialized */
111
  private static final int      SL_INITIALIZED      = -2;
112
/** Return value from native uninitialization functions if
113
      never initialized */
114
  private static final int      SL_NOT_INITIALIZED  = -3;
115
  /** Return value from native uninitialization functions if
116
      there are no more interface handles available */
117
  private static final int      SL_OUT_OF_HANDLES   = -4;
118
  /** Return value from native uninitialization functions if 
119
      nohandle for the IPersist interface could be obtained */
120
  private static final int      SL_NO_IPERSIST      = -5;
121
  /** Return value from native uninitialization functions if
122
      the save operation fort the link failed */
123
  private static final int      SL_NO_SAVE          = -6;
124
  /** Return value if the function called had to deal with
125
      unexpected data types. This might be returned by
126
      registry functions if they receive an unexpected
127
      data type from the registry. */
128
  private static final int      SL_WRONG_DATA_TYPE  = -7;
129

    
130
  // ------------------------------------------------------
131
  // Miscellaneous constants
132
  // ------------------------------------------------------
133
  private static final int      UNINITIALIZED       = -1;
134
  /** the extension that must be used for link files */
135
  private static final String   LINK_EXTENSION      = ".lnk";
136
  /** the constant to use for selecting the current user. */
137
  public  static final int      CURRENT_USER        = 0;
138
  /** the constant to use for selecting the all users. */
139
  public  static final int      ALL_USERS           = 1;  
140

    
141
  // ------------------------------------------------------------------------
142
  // Variable Declarations
143
  // ------------------------------------------------------------------------
144
  /** This handle links us to a specific native instance. Do not use or
145
      modify, the variable is for exclusive use by the native side. */
146
  private int     nativeHandle            = UNINITIALIZED;
147

    
148
  /** Path to the location where links for the current user are stored. The
149
      exact content depends on the circumstances. It can be set during object 
150
      construction or from native code. It will point to the location where 
151
      links of the most recently requested type are stored. */
152
  private String  currentUserLinkPath     = "";
153
  /** Path to the location where links for all users are stored. The exact
154
      content depends on the circumstances. It can be set during object 
155
      construction or from native code. It will point to the location where 
156
      links of the most recently requested type are stored. */
157
  private String  allUsersLinkPath        = "";
158
  private String  groupName               = "";
159
  private String  linkName                = "";
160
  /** this is the fully qualified name of the link on disk. Note that this
161
      variable contains only valid data if the link was created from a disk
162
      file or after a successful save operation. At other times the content
163
      is upredicatable. */
164
  private String  linkFileName            = "";
165
  /** Contains the directory where the link file is stored after any save
166
      operation that needs to create that directory. Otherwise it contains
167
      <code>null</code>. */
168
  private String  linkDirectory           = "";
169

    
170
  private String  arguments               = "";
171
  private String  description             = "";
172
  private String  iconPath                = "";
173
  private String  targetPath              = "";
174
  private String  workingDirectory        = "";
175
  /** there seems to be an error in JNI that causes an access violation if
176
      a String that is accessed from native code borders on another type of
177
      variable. This caused problems in <code>set()</code> For this reason,
178
      the dummy string is placed here. Observed with version: <pre>
179
      java version "1.3.0"
180
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
181
      Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode) </pre> */
182
  private String  dummyString             = "";
183

    
184
  private int     hotkey                  = 0;
185
  private int     iconIndex               = 0;
186
  private int     showCommand             = NORMAL;
187
  private int     linkType                = DESKTOP;
188
  private int     userType                = CURRENT_USER;
189

    
190
  private boolean initializeSucceeded     = false;
191

    
192
  // ------------------------------------------------------------------------
193
  // Native Methods
194
  // ------------------------------------------------------------------------
195
  // For documentation on these methods see ShellLink.cpp
196
  // ------------------------------------------------------------------------
197
  private native int initializeCOM ();
198
  private native int releaseCOM ();
199
  private native int getInterface ();
200
  private native int releaseInterface ();
201
  private native int GetArguments ();
202
  private native int GetDescription ();
203
  private native int GetHotkey ();
204
  private native int GetIconLocation ();
205
  private native int GetPath ();
206
  private native int GetShowCommand ();
207
  private native int GetWorkingDirectory ();
208
  private native int Resolve ();
209
  private native int SetArguments ();
210
  private native int SetDescription ();
211
  private native int SetHotkey ();
212
  private native int SetIconLocation ();
213
  private native int SetPath ();
214
  private native int SetShowCommand ();
215
  private native int SetWorkingDirectory ();
216
  private native int saveLink (String name);
217
  private native int loadLink (String name);
218
  private native int GetFullLinkPath (int usertype, int linktype);
219
  
220
  /**
221
   * This method is used to free the library at the end of progam execution.
222
   * After this call, any instance of this calss will not be usable any more!
223
   */
224
  private native void FreeLibrary (String name);
225

    
226
 /**
227
  * Creates an instance of <code>ShellLink</code> of a specific
228
  * type. Initializes currentUserLinkPath and allUsersLinkPath.<p>
229
  *
230
  * A LinkPath is empty if the combination of linkType and userType, are not
231
  * valid.<p>
232
  *
233
  * Note: If a linkPath is empty, the userType is reset to the other
234
  * userType.<p>
235
  *
236
  * If both linkPaths are empty, an IllegalArgumentException is thrown.
237
  *
238
  * @param     type   The type of link desired. The following values can be set:<br>
239
  *                   <ul>
240
  *                   <li><code>ShellLink.DESKTOP</code>
241
  *                   <li><code>ShellLink.PROGRAM_MENU</code>
242
  *                   <li><code>ShellLink.START_MENU</code>
243
  *                   <li><code>ShellLink.STARTUP</code>
244
  *                   </ul>
245
  * @param     name   The name that the link should display on a menu or on
246
  *                   the desktop. Do not include a file extension.
247
  *
248
  * @exception IllegalArgumentException if any of the call parameters are
249
  *                  incorrect, or if no linkPaths are returned.
250
  * @exception Exception if problems are encountered in initializing the
251
  *                      native interface
252
  */
253
  public ShellLink (int    type,
254
                    String name)  throws Exception, IllegalArgumentException
255
  {
256
    if ((type < MIN_TYPE) || 
257
        (type > MAX_TYPE)   )
258
    {
259
      throw (new IllegalArgumentException ("the type parameter used an illegal value"));
260
    }
261
    if (name == null)
262
    {
263
      throw (new IllegalArgumentException ("the name parameter was null"));
264
    }
265
                
266
    linkName = name;
267
    linkType = type;
268
    
269
    initialize ();  //com
270

    
271
        // set curretnUsersLinkPath, allUsersLinkPath, sets userType to valid.
272
        setAllLinkPaths();
273
  }
274

    
275
 /*--------------------------------------------------------------------------*/
276
 /**
277
  * Creates an instance of <code>ShellLink</code> from an existing shell link
278
  * on disk.
279
  *
280
  * @param     name      the fully qualified file name of the link.
281
  * @param     userType  the type of user for the link path.
282
  * 
283
  * @see       #CURRENT_USER
284
  * @see       #ALL_USERS
285
  *
286
  * @exception IllegalArgumentException if the name was null
287
  * @exception Exception if problems are encountered in reading the file
288
  */
289
  public ShellLink (String name,
290
                    int    userType) throws Exception, IllegalArgumentException
291
  {
292
    if (name == null)
293
    {
294
      throw (new IllegalArgumentException ("the name parameter was null"));
295
    }
296

    
297
    this.userType = userType;
298

    
299
    initialize ();  //com
300

    
301
    // store the individual parts of the path for later use    
302
    int pathEnd         = name.lastIndexOf (File.separator);
303
    int nameStart       = pathEnd + 1;
304
    int nameEnd         = name.lastIndexOf ('.');
305
    if (nameEnd < 0)
306
    {
307
      throw (new Exception ("illegal file name"));
308
    }
309
    linkName            = name.substring (nameStart, nameEnd);
310

    
311
    if (userType == CURRENT_USER)
312
    {
313
      currentUserLinkPath = name.substring (0, pathEnd);
314
    }
315
    else
316
    {
317
      allUsersLinkPath = name.substring (0, pathEnd);
318
    }
319

    
320
    linkFileName = fullLinkName (userType);
321
    if (loadLink (linkFileName) != SL_OK)
322
    {
323
      throw (new Exception ("reading of the file did not succeed"));
324
    }
325

    
326
    // get all settings from the native side
327
    get ();
328
  }
329

    
330
 /*--------------------------------------------------------------------------*/
331
 /**
332
  * Creates an instance of <code>ShellLink</code> from an existing shell link
333
  * on disk.
334
  *
335
  * @param     type     The type of link, one of the following values: <br>
336
  *                     <ul>
337
  *                     <li><code>ShellLink.DESKTOP</code>
338
  *                     <li><code>ShellLink.PROGRAM_MENU</code>
339
  *                     <li><code>ShellLink.START_MENU</code>
340
  *                     <li><code>ShellLink.STARTUP</code>
341
  *                     </ul>
342
  * @param     userType  the type of user for the link path.
343
  * @param     group    The program group (directory) of this link. If the
344
  *                     link is not part of a program group, pass an empty
345
  *                     string or null for this parameter. (...\\Desktop\\group).
346
  * @param     name     The file name of this link. Do not include a file
347
  *                     extension.
348
  *
349
  * @see       #CURRENT_USER
350
  * @see       #ALL_USERS
351
  *
352
  * @exception IllegalArgumentException if any of the call parameters are
353
  *                                     incorrect
354
  * @exception Exception if problems are encountered in initializing the
355
  *                      native interface
356
  */
357
  public ShellLink (int    type,
358
                    int    userType,
359
                    String group, 
360
                    String name) throws Exception, IllegalArgumentException
361
  {
362
    if ((type < MIN_TYPE) || 
363
        (type > MAX_TYPE)   )
364
    {
365
      throw (new IllegalArgumentException ("the type parameter used an illegal value"));
366
    }
367
    if (name == null)
368
    {
369
      throw (new IllegalArgumentException ("the name parameter was null"));
370
    }
371

    
372
    this.userType = userType;
373
    
374
    initialize ();  //com
375

    
376
    // set the variables for currentUserLinkPath and allUsersLinkPath
377
        setAllLinkPaths();
378

    
379
    if (group != null)
380
    {
381
      groupName = group;
382
    }
383
    linkName = name;
384
    
385
    // load the link
386
    linkFileName = fullLinkName (userType);
387
    if (loadLink(linkFileName) != SL_OK)
388
    {
389
      throw (new Exception ("reading of the file did not succeed"));
390
    }
391
        
392
    // get a settings from the native side
393
    get ();
394
  }
395

    
396
 /*--------------------------------------------------------------------------*/
397
 /**
398
  * Initializes COM and gets an instance of the IShellLink interface.
399
  *
400
  * @exception Exception if problems are encountered
401
  */
402
  private void initialize () throws Exception
403
  {
404
    try
405
    {
406
      Librarian.getInstance ().loadLibrary ("ShellLink", this);
407
    }
408
    catch (UnsatisfiedLinkError exception)
409
    {
410
      throw (new Exception ("could not locate native library"));
411
    }
412

    
413
    try
414
    {
415
      if (initializeCOM () != SL_OK)
416
      {
417
        throw (new Exception ("could not initialize COM"));
418
      }
419
      else
420
      {
421
        initializeSucceeded = true;
422
      }
423
    }
424
    catch (Throwable exception)
425
    {
426
      throw (new Exception ("unidentified problem initializing COM\n" + exception.toString ()));
427
    }
428

    
429
    int successCode = getInterface ();
430
    if (successCode != SL_OK)
431
    {
432
      releaseCOM ();
433
      initializeSucceeded = false;
434
      
435
      if (successCode == SL_OUT_OF_HANDLES)
436
      {
437
        throw (new Exception ("could not get an instance of IShellLink, no more handles available"));
438
      }
439
      else
440
      {
441
        throw (new Exception ("could not get an instance of IShellLink, failed to co-create instance"));
442
      }
443
    }
444
  }
445

    
446
 /*--------------------------------------------------------------------------*/
447
 /**
448
  * Destructor, releases COM and frees native resources.
449
  */
450
  protected void finalize ()
451
  {
452
    releaseInterface ();
453

    
454
    if (initializeSucceeded)
455
    {
456
      releaseCOM ();
457
      initializeSucceeded = false;
458
    }
459
  }
460

    
461
 /*--------------------------------------------------------------------------*/
462
 /**
463
  * This method is used to free the library at the end of progam execution.
464
  * After this call, any instance of this calss will not be usable any more!
465
  * <b><i><u>Note that this method does NOT return!</u></i></b>
466
  * <br><br>
467
  * <b>DO NOT CALL THIS METHOD DIRECTLY!</b><br>
468
  * It is used by the librarian to free the native library before physically
469
  * deleting it from its temporary loaction. A call to this method will
470
  * freeze the application irrecoverably!
471
  * 
472
  * @param    name    the name of the library to free. Use only the name and
473
  *                   extension but not the path.
474
  *
475
  * @see      com.izforge.izpack.util.NativeLibraryClient#freeLibrary
476
  */
477
  public void freeLibrary (String name)
478
  {
479
    int result = releaseInterface ();
480

    
481
    if (initializeSucceeded)
482
    {
483
      result = releaseCOM ();
484
      initializeSucceeded = false;
485
    }
486

    
487
    FreeLibrary (name);
488
  }
489

    
490
 /*--------------------------------------------------------------------------*/
491
 /**
492
  * Constructs and returns the full path for the link file.
493
  *
494
  * @param     userType  the type of user for the link path.
495
  *
496
  * @return    the path to use for storing the link
497
  * 
498
  * @see       #CURRENT_USER
499
  * @see       #ALL_USERS
500
  */
501
  private String fullLinkPath (int userType)
502
  {
503
    StringBuffer path = new StringBuffer ();
504
    
505
    // ----------------------------------------------------
506
    // build the complete name    
507
    // ----------------------------------------------------
508
    if (userType == CURRENT_USER)
509
    {
510
      path.append (currentUserLinkPath);
511
    }
512
    else
513
    {
514
      path.append (allUsersLinkPath);
515
    } 
516

    
517
    if ((groupName != null) && (groupName.length () > 0))
518
    {
519
      path.append (File.separator);
520
      path.append (groupName);
521
    }
522

    
523
    return (path.toString ());
524
  }
525

    
526
 /*--------------------------------------------------------------------------*/
527
 /**
528
  * Constructs and returns the fully qualified name for the link file.
529
  *
530
  * @param     userType  the type of user for the link path.
531
  *
532
  * @return    the fully qualified file name to use for storing the link
533
  * 
534
  * @see       #CURRENT_USER
535
  * @see       #ALL_USERS
536
  */
537
  private String fullLinkName (int userType)
538
  {
539
    StringBuffer name = new StringBuffer ();
540

    
541
    name.append (fullLinkPath (userType));    
542

    
543
        name.append (File.separator);
544
        name.append (linkName);
545
        name.append (LINK_EXTENSION);
546

    
547
    return (name.toString ());
548
  }
549

    
550
 /*--------------------------------------------------------------------------*/
551
 /**
552
  * Sets all members on the native side.
553
  *
554
  * @exception Exception if any problem is encountered during this operation.
555
  */
556
  private void set () throws Exception
557
  {
558
    if (SetArguments () != SL_OK)
559
    {
560
      throw (new Exception ("could not set arguments"));
561
    }
562
    if (SetDescription () != SL_OK)
563
    {
564
      throw (new Exception ("could not set description"));
565
    }
566
    if (SetHotkey () != SL_OK)
567
    {
568
      throw (new Exception ("could not set hotkey"));
569
    }
570
    if (SetIconLocation () != SL_OK)
571
    {
572
      throw (new Exception ("could not set icon location"));
573
    }
574
    if (SetPath () != SL_OK)
575
    {
576
      throw (new Exception ("could not set target path"));
577
    }
578
    if (SetShowCommand () != SL_OK)
579
    {
580
      throw (new Exception ("could not set show command"));
581
    }
582
    if (SetWorkingDirectory () != SL_OK)
583
    {
584
      throw (new Exception ("could not set working directory"));
585
    }
586

    
587
  }
588

    
589
 /*--------------------------------------------------------------------------*/
590
 /**
591
  * Gets all members from the native side.
592
  *
593
  * @exception Exception if any problem is encountered during this operation.
594
  *
595
  */
596
  private void get () throws Exception
597
  {
598
    if (GetArguments () != SL_OK)
599
    {
600
      throw (new Exception ("could not get arguments"));
601
    }
602
    if (GetDescription () != SL_OK)
603
    {
604
      throw (new Exception ("could not get description"));
605
    }
606
    if (GetHotkey () != SL_OK)
607
    {
608
      throw (new Exception ("could not get hotkey"));
609
    }
610
    if (GetIconLocation () != SL_OK)
611
    {
612
      throw (new Exception ("could not get icon location"));
613
    }
614
    if (GetPath () != SL_OK)
615
    {
616
      throw (new Exception ("could not get target ath"));
617
    }
618
    if (GetShowCommand () != SL_OK)
619
    {
620
      throw (new Exception ("could not get show command"));
621
    }
622
    if (GetWorkingDirectory () != SL_OK)
623
    {
624
      throw (new Exception ("could not get working directory"));
625
    }
626
  }
627

    
628
 /*--------------------------------------------------------------------------*/
629
 /**
630
  * Sets the name of the program group this ShellLinbk should be placed in.
631
  *
632
  * @param     groupName    the name of the program group
633
  */
634
  public void setProgramGroup (String groupName)
635
  {
636
    this.groupName = groupName;
637
  }
638

    
639
 /*--------------------------------------------------------------------------*/
640
 /**
641
  * Sets the command line arguments that will be passed to the target when
642
  * the link is activated.
643
  *
644
  * @param     arguments    the command line arguments
645
  *
646
  * @see       #getArguments
647
  */
648
  public void setArguments (String arguments)
649
  {
650
    this.arguments = arguments;
651
  }
652

    
653
 /*--------------------------------------------------------------------------*/
654
 /**
655
  * Sets the description string that is used to identify the link in a menu
656
  * or on the desktop.
657
  *
658
  * @param     description  the descriptiojn string
659
  *
660
  * @see       #getDescription
661
  */
662
  public void setDescription (String description)
663
  {
664
    this.description = description;
665
  }
666

    
667
 /*--------------------------------------------------------------------------*/
668
 /**
669
  * Sets the hotkey that can be used to activate the link.
670
  *
671
  * @param     hotkey   a valid Windows virtual key code. Modifiers (e.g. for
672
  *                     alt or shift key) are added in the upper byte. Note
673
  *                     that only the lower 16 bits for tis parameter are used.
674
  *
675
  * @see       #getHotkey
676
  */
677
  public void setHotkey (int hotkey)
678
  {
679
    this.hotkey = hotkey;
680
  }
681

    
682
 /*--------------------------------------------------------------------------*/
683
 /**
684
  * Sets the location of the icon that is shown for the shortcut on the
685
  * desktop.
686
  *
687
  * @param     path   a fully qualified file name of a file that contains
688
  *                   the icon.
689
  * @param     index  the index of the specific icon to use in the file.
690
  *                   If there is only one icon in the file, use an index
691
  *                   of 0.
692
  *
693
  * @see       #getIconLocation
694
  */
695
  public void setIconLocation (String path,
696
                               int    index)
697
  {
698
    this.iconPath  = path;
699
    this.iconIndex = index;
700
  }
701

    
702
 /*--------------------------------------------------------------------------*/
703
 /**
704
  * Sets the absolute path to the shortcut target.
705
  *
706
  * @param     path     the fully qualified file name of the target
707
  *
708
  * @see       #getTargetPath
709
  */
710
  public void setTargetPath (String path)
711
  {
712
    this.targetPath = path;
713
  }
714

    
715
 /*--------------------------------------------------------------------------*/
716
 /**
717
  * Sets the show command that is passed to the target application when the
718
  * link is activated. The show command determines if the the window will be
719
  * restored to the previous size, minimized, maximized or visible at all. 
720
  * <br><br>
721
  * <b>Note:</b><br>
722
  * Using <code>HIDE</code> will cause the target window not to show at
723
  * all. There is not even a button on the taskbar. This is a very useful
724
  * setting when batch files are used to launch a Java application as it
725
  * will then appear to run just like any native Windows application.<br>
726
  * <b>Note1:</b><br>
727
  * <code>HIDE</code> doesn't work in Win98 and newer systems.<br>
728
  * use MINIMIZED (MINNOACTIVE), instead.<br>
729
  *
730
  * @param     show   the show command. Valid settings are: <br>
731
  *                   <ul>
732
  *                   <li><code>ShellLink.HIDE</code>  (deprecated)
733
  *                   <li><code>ShellLink.NORMAL</code>
734
  *                   <li><code>ShellLink.MINNOACTIVE</code>
735
  *                   <li><code>ShellLink.MAXIMIZED</code>
736
  *                   </ul>
737
  *
738
  * @see       #getShowCommand
739
  */
740
  public void setShowCommand (int show)
741
  {
742
    if ((show < MIN_SHOW) || (show > MAX_SHOW))
743
    {
744
      throw (new IllegalArgumentException ("illegal value for show command " + show));
745
    }
746
  
747
    this.showCommand = show;
748
  }
749

    
750
 /*--------------------------------------------------------------------------*/
751
 /**
752
  * Sets the working directory for the link target.
753
  *
754
  * @param     dir    the working directory
755
  *
756
  * @see       #getWorkingDirectory
757
  */
758
  public void setWorkingDirectory (String dir)
759
  {
760
    this.workingDirectory = dir;
761
  }
762

    
763
 /*--------------------------------------------------------------------------*/
764
 /**
765
  * Sets the name shown in a menu or on the desktop for the link.
766
  *
767
  * @param     name   The name that the link should display on a menu or on
768
  *                   the desktop. Do not include a file extension.
769
  */
770
  public void setLinkName (String name)
771
  {
772
    linkName = name;
773
  }
774

    
775
 /*--------------------------------------------------------------------------*/
776
 /**
777
  * Sets the type of link
778
  *
779
  * @param     type   The type of link desired. The following values can be set:<br>
780
  *                   <ul>
781
  *                   <li>{@link #DESKTOP}
782
  *                   <li>{@link #PROGRAM_MENU}
783
  *                   <li>{@link #START_MENU}
784
  *                   <li>{@link #STARTUP}
785
  *                   </ul>
786
  *
787
  * @exception IllegalArgumentException if an an invalid type is passed
788
  */
789
  public void setLinkType (int type) throws IllegalArgumentException
790
  {
791
    if ((type < MIN_TYPE) || 
792
        (type > MAX_TYPE)   )
793
    {
794
      throw (new IllegalArgumentException ("illegal value for type"));
795
    }
796
                
797
    linkType = type;
798

    
799
        // set curretnUsersLinkPath, allUsersLinkPath, sets userType to valid.
800
        setAllLinkPaths();
801
  }
802

    
803
 /**
804
  * Returns the user type for the link. <br>
805
  *                   <ul>
806
  *                   <li>{@link #DESKTOP}
807
  *                   <li>{@link #PROGRAM_MENU}
808
  *                   <li>{@link #START_MENU}
809
  *                   <li>{@link #STARTUP}
810
  *                   </ul>
811
  *<br>
812
  *
813
  * @see #setLinkType
814
  */
815
  public int getLinkType()
816
  {
817
          return linkType;
818
  }
819

    
820
 /*--------------------------------------------------------------------------*/
821
 /**
822
  * Sets the (ShellLink) user type for link
823
  *
824
  * @param     type  the type of user for the link.
825
  * 
826
  * @see       #CURRENT_USER
827
  * @see       #ALL_USERS
828
  *
829
  * @exception IllegalArgumentException if an an invalid type is passed
830
  */
831
  public void setUserType (int type) throws IllegalArgumentException
832
  {
833
    if ((type == CURRENT_USER) || (type == ALL_USERS))
834
    {
835
      userType = type;
836
    }
837
    else
838
    {
839
      throw (new IllegalArgumentException (type + " is not a recognized user type"));
840
    }
841
  }
842

    
843
 /*--------------------------------------------------------------------------*/
844
 /**
845
  * Returns the (ShellLink) user type for the link. Either {@link #CURRENT_USER} or
846
  * {@link #ALL_USERS}
847
  *
848
  * @see #setUserType
849
  */
850
  public int getUserType ()
851
  {
852
    return userType;
853
  }
854

    
855
 /*--------------------------------------------------------------------------*/
856
 /**
857
  * Returns the path where the links of the selected type are stroed. This
858
  * method is useful for discovering which program groups already exist.
859
  *
860
  * @param userType the type of user for the link path. One of {@link
861
  * #CURRENT_USER} or {@link #ALL_USERS}
862
  *
863
  * @return    the path to the type of link set for this instance. 
864
  */           
865
  public String getLinkPath (int userType)
866
  {
867
    if (userType == CURRENT_USER)
868
    {
869
      return (currentUserLinkPath);
870
    }
871
    else
872
    {
873
      return (allUsersLinkPath);
874
    }
875
  }
876

    
877
 /*--------------------------------------------------------------------------*/
878
 /**
879
  * Returns the command line that the link passes to the target.
880
  *
881
  * @return    the command line
882
  *
883
  * @see       #setArguments
884
  */
885
  public String getArguments ()
886
  {
887
    return (arguments);
888
  }
889

    
890
 /*--------------------------------------------------------------------------*/
891
 /**
892
  * Returns the description for the link.
893
  *
894
  * @return    the description
895
  *
896
  * @see       #setDescription
897
  */
898
  public String getDescription ()
899
  {
900
    return (description);
901
  }
902

    
903
 /*--------------------------------------------------------------------------*/
904
 /**
905
  * Retruns the hotkey that can be used to activate the link.
906
  *
907
  * @return    the virtual keycode for the hotkey
908
  *
909
  * @see       #setHotkey
910
  */
911
  public int getHotkey ()
912
  {
913
    return (hotkey);
914
  }
915

    
916
 /*--------------------------------------------------------------------------*/
917
 /**
918
  * Returns the path and file name of the file that contains the icon that
919
  * is associated with the link.
920
  *
921
  * @return    the path to the icon
922
  *
923
  * @see       #setIconLocation
924
  */
925
  public String getIconLocation ()
926
  {
927
    return (iconPath);
928
  }
929

    
930
 /*--------------------------------------------------------------------------*/
931
 /**
932
  * Returns the index of the icon with the icon or resource file
933
  *
934
  * @return    the index
935
  *
936
  * @see       #setIconLocation
937
  */
938
  public int getIconIndex ()
939
  {
940
    return (iconIndex);
941
  }
942

    
943
 /*--------------------------------------------------------------------------*/
944
 /**
945
  * Retruns the absolute path of the link target
946
  *
947
  * @return    the path
948
  *
949
  * @see       #setTargetPath
950
  */
951
  public String getTargetPath ()
952
  {
953
    return (targetPath);
954
  }
955

    
956
 /*--------------------------------------------------------------------------*/
957
 /**
958
  * Returns the initial condition of the target window (HIDE, NORMAL, 
959
  * MINIMIZED, MAXIMIZED).
960
  *
961
  * @return    the target show command
962
  *
963
  * @see       #setShowCommand
964
  */
965
  public int getShowCommand ()
966
  {
967
    return (showCommand);
968
  }
969

    
970
 /*--------------------------------------------------------------------------*/
971
 /**
972
  * Retruns the working deirectory for the link target.
973
  *
974
  * @return    the working directory
975
  *
976
  * @see       #setWorkingDirectory
977
  */
978
  public String getWorkingDirectory ()
979
  {
980
    return (workingDirectory);
981
  }
982

    
983
 /*--------------------------------------------------------------------------*/
984
 /**
985
  * Returns the fully qualified file name under which the link is saved on
986
  * disk. <b>Note:</b> this method returns valid results only if the instance
987
  * was created from a file on disk or after a successful save operation.
988
  *
989
  * @return    the fully qualified file name for the shell link
990
  */
991
  public String getFileName ()
992
  {
993
    return (linkFileName);
994
  }
995

    
996
 /*--------------------------------------------------------------------------*/
997
 /**
998
  * Returns the path of the directory where the link file is stored, if it
999
  * was necessary during the previous save operation to create the directory.
1000
  * This method returns <code>null</code> if no save operation was carried
1001
  * out or there was no need to create a directory during the previous save
1002
  * operation.
1003
  *
1004
  * @return    the path of the directory where the link file is stored or
1005
  *            <code>null</code> if no save operation was carried out or
1006
  *            there was no need to create a directory during the previous
1007
  *            save operation.
1008
  */
1009
  public String getDirectoryCreated ()
1010
  {
1011
    return (linkDirectory);
1012
  }
1013

    
1014
 /*--------------------------------------------------------------------------*/
1015
 /**
1016
  * Returns the name shown in a menu or on the desktop for the link.
1017
  *
1018
  * @return    the name
1019
  */
1020
  public String getLinkName ()
1021
  {
1022
    return (linkName);
1023
  }
1024

    
1025
 /*--------------------------------------------------------------------------*/
1026
 /**
1027
  * Returns the path for currentusersLink
1028
  *
1029
  * @return    currentUsersLinkPath
1030
  */
1031
  public String getcurrentUserLinkPath ()
1032
  {
1033
    return (currentUserLinkPath);
1034
  }
1035

    
1036
 /*--------------------------------------------------------------------------*/
1037
 /**
1038
  * Returns the path for allusersLink
1039
  *
1040
  * @return    allusersLinkPath
1041
  */
1042
  public String getallUsersLinkPath ()
1043
  {
1044
    return (allUsersLinkPath);
1045
  }
1046

    
1047
 /*--------------------------------------------------------------------------*/
1048
 /**
1049
  * Saves this link.
1050
  *
1051
  * @exception Exception if problems are encountered
1052
  */
1053
  public void save () throws Exception
1054
  {
1055
    // set all values on the native side
1056
    set ();   
1057

    
1058
    // make sure the target actually resolves
1059
    int result = Resolve ();
1060

    
1061
    if (result != SL_OK)
1062
    {
1063
      throw (new Exception ("cannot resolve target"));
1064
    }
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

    
1080
    // perform the save operation
1081
    String saveTo = fullLinkName (userType);
1082

    
1083
    result        = saveLink (saveTo);
1084
    
1085
    if (result == SL_NO_IPERSIST)
1086
    {
1087
      throw (new Exception ("could not get handle for IPesist"));
1088
    }
1089
    else if (result == SL_NO_SAVE)
1090
    {
1091
      throw (new Exception ("the save operation failed"));
1092
    }
1093
    
1094
    linkFileName = saveTo;
1095
  }
1096

    
1097
 /*--------------------------------------------------------------------------*/
1098
 /**
1099
  * Saves this link to any desired location.
1100
  *
1101
  * @param     name     the fully qualified file name for the link
1102
  *
1103
  * @exception IllegalArgumentException if the parameter was null
1104
  * @exception Exception if the save operation could not be carried out
1105
  */
1106
  public void save (String name) throws Exception
1107
  {
1108
    if (name == null)
1109
    {
1110
      throw (new IllegalArgumentException ("name was null"));
1111
    }
1112

    
1113
    // set all values on the native side
1114
    set ();   
1115

    
1116
    // make sure the target actually resolves
1117
    if (Resolve () != SL_OK)
1118
    {
1119
      throw (new Exception ("cannot resolve target"));
1120
    }
1121

    
1122
    // make sure the directory exists
1123
    File directory = new File (name.substring (0, name.lastIndexOf (File.separatorChar)));
1124
    if (!directory.exists ())
1125
    {
1126
      directory.mkdirs ();
1127
      linkDirectory = directory.getPath ();
1128
    }
1129
    else
1130
    {
1131
      linkDirectory = null;
1132
    }
1133

    
1134
    // perform the save operation
1135
    if (saveLink (name) != SL_OK)
1136
    {
1137
      throw (new Exception ("the save operation failed"));
1138
    }
1139
    
1140
    linkFileName = name;
1141
  }
1142
  
1143
 /*--------------------------------------------------------------------------*/
1144
  /**
1145
   *  sets currentUsersLinkPath and allUsersLinkPath. If the path is empty,
1146
   *  resets userType to a valid userType for this type of link.  If no
1147
   *  linkPaths are valid, an IllegalArgumentException is thrown.
1148
   *
1149
   * @throws IllegalArgumentException
1150
   */
1151
  private void setAllLinkPaths() 
1152
    throws IllegalArgumentException
1153
  {
1154
        // sets currentUsersLinkPath and allUsersLinkPath
1155
    GetFullLinkPath (CURRENT_USER, linkType);
1156
    GetFullLinkPath (ALL_USERS, linkType);
1157

    
1158
    // be sure userType is valid. Override initial choice if not.
1159
    if ( userType == CURRENT_USER && currentUserLinkPath.length() == 0 )
1160
    {
1161
        userType = ALL_USERS;
1162
    }
1163
    else if ( userType == ALL_USERS && allUsersLinkPath.length() == 0 )
1164
    {
1165
        userType = CURRENT_USER;
1166
    }
1167

    
1168
        if ( allUsersLinkPath.length() == 0 && currentUserLinkPath.length() == 0 )
1169
        {
1170
                throw (new IllegalArgumentException (
1171
                  "linkType " + linkType + " is invalid."));
1172
        }
1173
  }
1174

    
1175
}
1176
/*---------------------------------------------------------------------------*/
1177