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; 026import java.util.Vector; 027 028import com.izforge.izpack.util.Debug; 029import com.izforge.izpack.util.StringTool; 030 031/*---------------------------------------------------------------------------*/ 032/** 033 * This is the Microsoft Windows specific implementation of <code>Shortcut</code>. 034 * 035 * @version 0.0.1 / 3/4/02 036 * @author Elmar Grom 037 */ 038/*---------------------------------------------------------------------------*/ 039public class Win_Shortcut extends Shortcut 040{ 041 042 // ------------------------------------------------------------------------ 043 // Constant Definitions 044 // ------------------------------------------------------------------------ 045 046 // ------------------------------------------------------------------------ 047 // Variable Declarations 048 // ------------------------------------------------------------------------ 049 private ShellLink shortcut; 050 051 private static String myClass = Win_Shortcut.class.getName() + ": "; 052 053 private static final String CLASS = "Class: "; 054 055 /** SUPPORTED = true */ 056 private static final boolean SUPPORTED = true; 057 058 /*--------------------------------------------------------------------------*/ 059 /** 060 * This method initializes the object. It is used as a replacement for the constructor because 061 * of the way it is instantiated through the <code>TargetFactory</code>. 062 * 063 * @param type the type or classification of the program group in which the link should exist. 064 * The following types are recognized: <br> 065 * <ul> 066 * <li>{@link com.izforge.izpack.util.os.Shortcut#APPLICATIONS} 067 * <li>{@link com.izforge.izpack.util.os.Shortcut#START_MENU} 068 * <li>{@link com.izforge.izpack.util.os.Shortcut#DESKTOP} 069 * <li>{@link com.izforge.izpack.util.os.Shortcut#START_UP} 070 * </ul> 071 * @param name the name of the shortcut. 072 */ 073 public void initialize(int type, String name) throws Exception 074 { 075 Debug.log( CLASS + myClass + ".initialize() '" + Integer.toString(type)+ "', '" + name + "'" ); 076 switch (type) 077 { 078 case APPLICATIONS: { 079 shortcut = new ShellLink(ShellLink.PROGRAM_MENU, name); 080 break; 081 } 082 case START_MENU: { 083 shortcut = new ShellLink(ShellLink.START_MENU, name); 084 break; 085 } 086 case DESKTOP: { 087 shortcut = new ShellLink(ShellLink.DESKTOP, name); 088 break; 089 } 090 case START_UP: { 091 shortcut = new ShellLink(ShellLink.STARTUP, name); 092 break; 093 } 094 default: { 095 shortcut = new ShellLink(ShellLink.PROGRAM_MENU, name); 096 break; 097 } 098 } 099 } 100 101 /*--------------------------------------------------------------------------*/ 102 /** 103 * Returns the base path of the shortcut depending on type. The base path is the directory that 104 * the short cut, (or its program group) will be created in. For instance, on Windows NT, a 105 * shortcut with user-type ALL_USERS, and link-type DESKTOP might have the base path 106 * "C:\Program Files\All Users\Desktop" 107 * 108 * @see #setLinkType(int) 109 * @see #setUserType(int) 110 * 111 * translates from ShellLink-UserTypes to Shortcut-UserTypes. 112 */ 113 public String getBasePath() throws Exception 114 { 115 String result = shortcut.getLinkPath(shortcut.getUserType()); 116 Debug.log( CLASS + myClass + ".getBasePath() '" + result + "'" ); 117 return result; 118 } 119 120 /** 121 * Returns a list of currently existing program groups, based on the requested type. For example 122 * if the type is <code>APPLICATIONS</code> then all the names of the program groups in the 123 * Start Menu\Programs menu would be returned. 124 * 125 * @param userType the type of user for the program group set. (as Shortcut.utype) 126 * 127 * @return a <code>Vector</code> of <code>String</code> objects that represent the names of 128 * the existing program groups. It is theoretically possible that this list is empty. 129 * 130 * @see #APPLICATIONS 131 * @see #START_MENU 132 */ 133 public Vector getProgramGroups(int userType) 134 { 135 int logentry = 0; 136 Debug.log( CLASS + myClass + ".getProgramGroups()-" + logentry++ + " '" + Integer.toString(userType) + "'" ); 137 // ---------------------------------------------------- 138 // translate the user type 139 // ---------------------------------------------------- 140 int type = ShellLink.CURRENT_USER; 141 142 if (userType == ALL_USERS) 143 { 144 type = ShellLink.ALL_USERS; 145 } 146 else 147 { 148 type = ShellLink.CURRENT_USER; 149 } 150 151 // ---------------------------------------------------- 152 // get a list of all files and directories that are 153 // located at the link path. 154 // ---------------------------------------------------- 155 String linkPath = shortcut.getLinkPath(type); 156 157 Debug.log( CLASS + myClass + ".getProgramGroups()-" + logentry++ + " '" + linkPath + "'" ); 158 159 // in case there is a problem obtaining a path return 160 // an empty vector (there are no preexisting program 161 // groups) 162 if (linkPath == null) { return (new Vector()); } 163 164 File path = new File(linkPath); 165 File[] file = path.listFiles(); 166 167 // ---------------------------------------------------- 168 // build a vector that contains only the names of 169 // the directories. 170 // ---------------------------------------------------- 171 Vector groups = new Vector(); 172 173 if (file != null) 174 { 175 for (int i = 0; i < file.length; i++) 176 { 177 File aFile = file[i]; 178 String aFilename = aFile.getName(); 179 if (aFile.isDirectory()) 180 { 181 182 Debug.log( CLASS + myClass + ".getProgramGroups()-" + logentry++ + " '" + aFilename + "'" ); 183 groups.add( aFilename ); 184 } 185 else 186 Debug.log( CLASS + myClass + ".getProgramGroups()-" + logentry++ + " Skip (NoDirectory): '" + aFilename + "'" ); 187 } 188 } 189 190 return (groups); 191 } 192 193 /*--------------------------------------------------------------------------*/ 194 /** 195 * Returns the fully qualified file name under which the link is saved on disk. <b>Note: </b> 196 * this method returns valid results only if the instance was created from a file on disk or 197 * after a successful save operation. 198 * 199 * @return the fully qualified file name for the shell link 200 */ 201 public String getFileName() 202 { 203 String aFilename = shortcut.getFileName(); 204 Debug.log( CLASS + myClass + ".getFileName() '" + aFilename + "'" ); 205 return( aFilename ); 206 } 207 208 /*--------------------------------------------------------------------------*/ 209 /** 210 * Returns the path of the directory where the link file is stored, if it was necessary during 211 * the previous save operation to create the directory. This method returns <code>null</code> 212 * if no save operation was carried out or there was no need to create a directory during the 213 * previous save operation. 214 * 215 * @return the path of the directory where the link file is stored or <code>null</code> if no 216 * save operation was carried out or there was no need to create a directory during the previous 217 * save operation. 218 */ 219 public String getDirectoryCreated() 220 { 221 String directoryCreated = shortcut.getDirectoryCreated(); 222 Debug.log( CLASS + myClass + ".getDirectoryCreated() '" + directoryCreated + "'" ); 223 return( directoryCreated ); 224 } 225 226 /*--------------------------------------------------------------------------*/ 227 /** 228 * Returns <code>true</code> if the target OS supports current user and all users. 229 * 230 * @return <code>true</code> if the target OS supports current and all users. 231 */ 232 public boolean multipleUsers() 233 { 234 boolean result = false; 235 // Win NT4 won't have PROGRAMS for CURRENT_USER. 236 // Win 98 may not have 'Start Menu\Programs' for ALL_USERS 237 String allUsers = shortcut.getallUsersLinkPath(); 238 239 Debug.log( CLASS + myClass + ".multipleUsers()-1 '" + allUsers + "'" ); 240 241 String currentUsers = shortcut.getcurrentUserLinkPath(); 242 Debug.log( CLASS + myClass + ".multipleUsers()-2 '" + currentUsers + "'" ); 243 244 if( allUsers == null || currentUsers == null ) 245 result = false; 246 else 247 result = allUsers.length() > 0 && currentUsers.length() > 0; 248 249 Debug.log( CLASS + myClass + ".multipleUsers()-3 '" + result + "'" ); 250 return (result); 251 } 252 253 /*--------------------------------------------------------------------------*/ 254 /** 255 * Signals that this flavor of <code>{@link com.izforge.izpack.util.os.Shortcut}</code> 256 * supports the creation of shortcuts. 257 * 258 * @return always <code>true</code> 259 */ 260 public boolean supported() 261 { 262 Debug.log( CLASS + myClass + ".supported() '" + SUPPORTED + "'" ); 263 return( SUPPORTED ); 264 } 265 266 /*--------------------------------------------------------------------------*/ 267 /** 268 * Sets the command line arguments that will be passed to the target when the link is activated. 269 * 270 * @param arguments the command line arguments 271 */ 272 public void setArguments(String arguments) 273 { 274 Debug.log( CLASS + myClass + ".setArguments() '" + arguments + "'" ); 275 shortcut.setArguments(arguments); 276 } 277 278 /*--------------------------------------------------------------------------*/ 279 /** 280 * Sets the description string that is used to identify the link in a menu or on the desktop. 281 * 282 * @param description the descriptiojn string 283 */ 284 public void setDescription(String description) 285 { 286 Debug.log( CLASS + myClass + ".setDescription() '" + description + "'" ); 287 shortcut.setDescription( description ); 288 } 289 290 /*--------------------------------------------------------------------------*/ 291 /** 292 * Sets the location of the icon that is shown for the shortcut on the desktop. 293 * 294 * @param path a fully qualified file name of a file that contains the icon. 295 * @param index the index of the specific icon to use in the file. If there is only one icon in 296 * the file, use an index of 0. 297 */ 298 public void setIconLocation(String path, int index) 299 { 300 Debug.log( CLASS + myClass + ".setIconLocation() '" + path + "', '" + Integer.toString(index) + "'" ); 301 shortcut.setIconLocation(path, index); 302 } 303 304 /*--------------------------------------------------------------------------*/ 305 /** 306 * returns icon Location 307 * 308 * @return iconLocation 309 */ 310 public String getIconLocation() 311 { 312 String result = shortcut.getIconLocation(); 313 Debug.log( CLASS + myClass + ".getIconLocation() '" + result + "'" ); 314 return result; 315 } 316 317 /*--------------------------------------------------------------------------*/ 318 /** 319 * Sets the name of the program group this ShellLinbk should be placed in. 320 * 321 * @param groupName the name of the program group 322 */ 323 public void setProgramGroup(String groupName) 324 { 325 Debug.log( CLASS + myClass + ".setProgramGroup() '" + groupName + "'" ); 326 shortcut.setProgramGroup(groupName); 327 } 328 329 /*--------------------------------------------------------------------------*/ 330 /** 331 * Sets the show command that is passed to the target application when the link is activated. 332 * The show command determines if the the window will be restored to the previous size, 333 * minimized, maximized or visible at all. <br> 334 * <br> 335 * <b>Note: </b> <br> 336 * Using <code>HIDE</code> will cause the target window not to show at all. There is not even 337 * a button on the taskbar. This is a very useful setting when batch files are used to launch a 338 * Java application as it will then appear to run just like any native Windows application. <br> 339 * 340 * 341 * @param show the show command. Valid settings are: <br> 342 * <ul> 343 * <li>{@link com.izforge.izpack.util.os.Shortcut#HIDE} 344 * <li>{@link com.izforge.izpack.util.os.Shortcut#NORMAL} 345 * <li>{@link com.izforge.izpack.util.os.Shortcut#MINIMIZED} 346 * <li>{@link com.izforge.izpack.util.os.Shortcut#MAXIMIZED} 347 * </ul> 348 * 349 * @see #getShowCommand internally maps from Shortcut. to ShellLink. 350 */ 351 public void setShowCommand(int show) throws IllegalArgumentException 352 { 353 Debug.log( CLASS + myClass + ".setShowCommand() '" + Integer.toString(show) + "'" ); 354 switch (show) 355 { 356 case HIDE: { 357 shortcut.setShowCommand(ShellLink.MINNOACTIVE); 358 break; 359 } 360 case NORMAL: { 361 shortcut.setShowCommand(ShellLink.NORMAL); 362 break; 363 } 364 case MINIMIZED: { 365 shortcut.setShowCommand(ShellLink.MINNOACTIVE); 366 break; 367 } 368 case MAXIMIZED: { 369 shortcut.setShowCommand(ShellLink.MAXIMIZED); 370 break; 371 } 372 default: { 373 throw (new IllegalArgumentException(show + "is not recognized as a show command")); 374 } 375 } 376 } 377 378 /* 379 * returns current showCommand. internally maps from ShellLink. to Shortcut. 380 * 381 */ 382 public int getShowCommand() 383 { 384 int showCommand = shortcut.getShowCommand(); 385 386 Debug.log( CLASS + myClass + ".getShowCommand() '" + Integer.toString(showCommand) + "'" ); 387 388 switch (showCommand) 389 { 390 case ShellLink.NORMAL: 391 showCommand = NORMAL; 392 break; 393 // both MINNOACTIVE and MINIMIZED map to Shortcut.MINIMIZED 394 case ShellLink.MINNOACTIVE: 395 case ShellLink.MINIMIZED: 396 showCommand = MINIMIZED; 397 break; 398 case ShellLink.MAXIMIZED: 399 showCommand = MAXIMIZED; 400 break; 401 default: 402 break; 403 } 404 405 return showCommand; 406 } 407 408 /*--------------------------------------------------------------------------*/ 409 /** 410 * Sets the absolute path to the shortcut target. 411 * 412 * @param path the fully qualified file name of the target 413 */ 414 public void setTargetPath(String path) 415 { 416 Debug.log( CLASS + myClass + ".setTargetPath() '" + path + "'" ); 417 shortcut.setTargetPath(path); 418 } 419 420 /*--------------------------------------------------------------------------*/ 421 /** 422 * Sets the working directory for the link target. 423 * 424 * @param dir the working directory 425 */ 426 public void setWorkingDirectory(String dir) 427 { 428 Debug.log( CLASS + myClass + ".setWorkingDirectory() '" + dir + "'" ); 429 shortcut.setWorkingDirectory(dir); 430 } 431 432 /*--------------------------------------------------------------------------*/ 433 /** 434 * Gets the working directory for the link target. 435 * 436 * @return the working directory. 437 */ 438 public String getWorkingDirectory() 439 { 440 String result = shortcut.getWorkingDirectory(); 441 Debug.log( CLASS + myClass + ".getWorkingDirectory() '" + result + "'" ); 442 return result; 443 } 444 445 /*--------------------------------------------------------------------------*/ 446 /** 447 * Sets the name shown in a menu or on the desktop for the link. 448 * 449 * @param name The name that the link should display on a menu or on the desktop. Do not include 450 * a file extension. 451 */ 452 public void setLinkName(String name) 453 { 454 Debug.log( CLASS + myClass + ".setLinkName() '" + name + "'" ); 455 shortcut.setLinkName(name); 456 } 457 458 /*--------------------------------------------------------------------------*/ 459 /** 460 * Gets the type of link types are: <br> 461 * <ul> 462 * <li>{@link com.izforge.izpack.util.os.Shortcut#DESKTOP} 463 * <li>{@link com.izforge.izpack.util.os.Shortcut#APPLICATIONS} 464 * <li>{@link com.izforge.izpack.util.os.Shortcut#START_MENU} 465 * <li>{@link com.izforge.izpack.util.os.Shortcut#START_UP} 466 * </ul> 467 * maps from ShellLink-types to Shortcut-types. 468 */ 469 public int getLinkType() 470 { 471 int typ = shortcut.getLinkType(); 472 Debug.log( CLASS + myClass + ".getLinkType() '" + typ + "'" ); 473 switch (typ) 474 { 475 case ShellLink.DESKTOP: 476 typ = DESKTOP; 477 break; 478 case ShellLink.PROGRAM_MENU: 479 typ = APPLICATIONS; 480 break; 481 case ShellLink.START_MENU: 482 typ = START_MENU; 483 break; 484 case ShellLink.STARTUP: 485 typ = START_UP; 486 break; 487 default: 488 break; 489 } 490 491 return typ; 492 } 493 494 /*--------------------------------------------------------------------------*/ 495 /** 496 * Sets the type of link 497 * 498 * @param type The type of link desired. The following values can be set: <br> 499 * (note APPLICATION on Windows is 'Start Menu\Programs') APPLICATION is a Mac term. 500 * <ul> 501 * <li>{@link com.izforge.izpack.util.os.Shortcut#DESKTOP} 502 * <li>{@link com.izforge.izpack.util.os.Shortcut#APPLICATIONS} 503 * <li>{@link com.izforge.izpack.util.os.Shortcut#START_MENU} 504 * <li>{@link com.izforge.izpack.util.os.Shortcut#START_UP} 505 * </ul> 506 * 507 * @exception IllegalArgumentException if an an invalid type is passed 508 * @throws UnsupportedEncodingException 509 */ 510 public void setLinkType(int type) throws IllegalArgumentException, UnsupportedEncodingException 511 { 512 Debug.log( CLASS + myClass + ".setLinkType() '" + type + "'" ); 513 switch (type) 514 { 515 case DESKTOP: { 516 shortcut.setLinkType(ShellLink.DESKTOP); 517 break; 518 } 519 case APPLICATIONS: { 520 shortcut.setLinkType(ShellLink.PROGRAM_MENU); 521 break; 522 } 523 case START_MENU: { 524 shortcut.setLinkType(ShellLink.START_MENU); 525 break; 526 } 527 case START_UP: { 528 shortcut.setLinkType(ShellLink.STARTUP); 529 break; 530 } 531 default: { 532 throw (new IllegalArgumentException(type + "is not recognized as a valid link type")); 533 } 534 } 535 } 536 537 /*--------------------------------------------------------------------------*/ 538 /** 539 * Gets the user type for the link 540 * 541 * @return userType 542 * @see #CURRENT_USER 543 * @see #ALL_USERS 544 */ 545 public int getUserType() 546 { 547 int utype = shortcut.getUserType(); 548 549 Debug.log( CLASS + myClass + ".getUserType() '" + utype + "'" ); 550 551 switch (utype) 552 { 553 case ShellLink.ALL_USERS: 554 utype = ALL_USERS; 555 break; 556 557 case ShellLink.CURRENT_USER: 558 utype = CURRENT_USER; 559 break; 560 } 561 562 return utype; 563 } 564 565 /*--------------------------------------------------------------------------*/ 566 /** 567 * Sets the user type for the link 568 * 569 * @param type the type of user for the link. 570 * 571 * @see Shortcut#CURRENT_USER 572 * @see Shortcut#ALL_USERS 573 * 574 * if the linkPath for that type is empty, refuse to set. 575 */ 576 /*--------------------------------------------------------------------------*/ 577 public void setUserType(int type) 578 { 579 Debug.log( CLASS + myClass + ".setUserType() '" + type + "'" ); 580 if (type == CURRENT_USER) 581 { 582 if (shortcut.getcurrentUserLinkPath().length() > 0) 583 { 584 shortcut.setUserType(ShellLink.CURRENT_USER); 585 } 586 } 587 else if (type == ALL_USERS) 588 { 589 if (shortcut.getallUsersLinkPath().length() > 0) 590 { 591 shortcut.setUserType(ShellLink.ALL_USERS); 592 } 593 } 594 } 595 596 /*--------------------------------------------------------------------------*/ 597 /** 598 * Saves this link. 599 * 600 * @exception Exception if problems are encountered 601 */ 602 public void save() throws Exception 603 { 604 605 shortcut.save(); 606 } 607 608 /*--------------------------------------------------------------------------*/ 609 /** 610 * Gets the link hotKey 611 * 612 * @return int hotKey 613 */ 614 public int getHotkey() 615 { 616 int result = shortcut.getHotkey(); 617 Debug.log( CLASS + myClass + ".getHotkey() '" + result + "'" ); 618 return result; 619 } 620 621 /*--------------------------------------------------------------------------*/ 622 /** 623 * Sets the link hotKey 624 * 625 * @param hotkey 626 * 627 * incoming 2 byte hotkey is: high byte modifier: SHIFT = 0x01 CONTROL= 0x02 ALT = 0x04 EXT = 628 * 0x08 629 * 630 * lower byte contains ascii letter. ie 0x0278 represents CTRL+x 0x068a represents CTRL+ALT+z 631 */ 632 public void setHotkey(int hotkey) 633 { 634 Debug.log( CLASS + myClass + ".setHotkey() '" + hotkey + "'" ); 635 shortcut.setHotkey(hotkey); 636 } 637 638 /** 639 * Gets the Folders where to place the program-groups and their shortcuts, for the given 640 * usertype. 641 * @throws UnsupportedEncodingException 642 * 643 * @see com.izforge.izpack.util.os.Shortcut#getProgramsFolder(int) 644 */ 645 public String getProgramsFolder(int current_user) 646 { 647 String result = null; 648 try 649 { 650 result = new String( shortcut.getLinkPath(current_user).getBytes( StringTool.getPlatformEncoding() ), StringTool.getPlatformEncoding() ); 651 } 652 catch (UnsupportedEncodingException e) 653 { 654 // TODO Auto-generated catch block 655 e.printStackTrace(); 656 } 657 Debug.log( CLASS + myClass + ".getProgramsFolder() '" + current_user + "', '" + result + "'" ); 658 return result; 659 } 660} 661/*---------------------------------------------------------------------------*/ 662