/*******************************************************************************
* Copyright (c) 2014 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Mentor Graphics - initial API and implementation
*******************************************************************************/
package com.codesourcery.internal.installer.actions;
import java.io.File;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.codesourcery.installer.IInstallMode;
import com.codesourcery.installer.IInstallPlatform;
import com.codesourcery.installer.IInstallProduct;
import com.codesourcery.installer.Installer;
import com.codesourcery.installer.IInstallPlatform.ShortcutFolder;
import com.codesourcery.installer.actions.AbstractInstallAction;
import com.codesourcery.internal.installer.IInstallConstants;
import com.codesourcery.internal.installer.InstallMessages;
import com.codesourcery.internal.installer.InstallUtils;
/**
* Action to install and uninstall a shortcut. can be used to create short-cuts
* to any files installed via P2 or files that are part of the uninstaller
*/
public class ShortcutAction extends AbstractInstallAction {
/** Action identifier */
private static final String ID = "com.codesourcery.installer.shortcutAction";
/** Path attribute */
private static final String ATTRIBUTE_PATH = "path";
/** Name attribute */
private static final String ATTRIBUTE_NAME = "name";
/** Remove folder attribute */
private static final String ATTRIBUTE_REMOVE_PATH = "removePath";
/** Short-cut path */
private IPath path;
/** Short-cut path to remove on uninstallation or <code>null</code> */
private IPath removePath;
/** Shortcut name */
private String name;
/** Shortcut target */
private IPath target;
/** Shortcut icon */
private IPath iconPath;
/** Arguments */
private String[] args;
/** Shortcut working directory */
private IPath workingDirectory;
/**
* Constructor
*/
public ShortcutAction() {
super(ID);
}
/**
* Constructor
*
* @param path Path to short-cut directory
* @param removePath Path to remove when short-cut is installed or
* <code>null</code>.
* @param name Name for shortcut
* @param target Target for shortcut
* @param iconPath Path to the shortcut icon or <code>null</code> to use
* target file for icon if needed.
* @param workingDirectory Working directory for shortcut
* @param args Command-line arguments for the shortcut
* folder on uninstallation.
*/
public ShortcutAction(IPath path, IPath removePath,
String name, IPath target, IPath iconPath, IPath workingDirectory, String[] args) {
super(ID);
this.path = path;
this.removePath = removePath;
this.name = name;
this.target = target;
this.iconPath = iconPath;
this.args = args;
this.workingDirectory = workingDirectory;
}
/**
* Returns the path of the short-cut directory.
*
* @return Base path
*/
protected IPath getPath() {
return path;
}
/**
* Returns the path to remove for the short-cut.
*
* @return Remove path
*/
protected IPath getRemovePath() {
return removePath;
}
/**
* Returns the name of the shortcut.
*
* @return Name
*/
protected String getName() {
return name;
}
/**
* Returns the target for the shortcut.
*
* @return Target
*/
protected IPath getTarget() {
return target;
}
/**
* Returns the icon path for the shortcut.
*
* @return Icon path
*/
protected IPath getIconPath() {
return iconPath;
}
/**
* Returns the invocation arguments for the shortcut.
*
* @return Args
*/
protected String[] getArguments() {
return args;
}
/**
* Returns the working directory for the
* shortcut.
*
* @return Working directory
*/
protected IPath getWorkingDirectory() {
return workingDirectory;
}
@Override
public void run(IProvisioningAgent agent, IInstallProduct product, IInstallMode mode, IProgressMonitor pm) throws CoreException {
IInstallPlatform platform = Installer.getDefault().getInstallPlatform();
IPath shortcutFolder = getPath();
String fileName = InstallUtils.makeFileNameSafe(getName());
try {
// Install
if (mode.isInstall()) {
pm.beginTask(InstallMessages.CreatingShortcut, 1);
pm.setTaskName(InstallMessages.CreatingShortcut);
// Target of short-cut exist?
if (doesTargetExist()) {
StringBuffer argsBuffer = new StringBuffer();
if (args != null)
for (int i = 0; i < args.length; i++) {
String arg = args[i];
/// Handle {installFolder} variable.
if (arg.contains("{installFolder}")) {
String installFolder = product.getLocation().toOSString();
arg = arg.replace("{installFolder}", installFolder);
}
argsBuffer.append(arg);
if (i < args.length - 1) {
argsBuffer.append(" ");
}
}
// Create short-cut
platform.createShortcut(
shortcutFolder,
fileName,
getTarget(),
argsBuffer.toString(),
getWorkingDirectory(),
(getIconPath() != null) ? getIconPath() : getTarget(),
0);
}
else {
Installer.log("Short-cut target does not exist: " + getTarget());
}
pm.worked(1);
}
// Uninstall
else {
pm.beginTask(InstallMessages.RemovingShortcut, 1);
pm.setTaskName(InstallMessages.RemovingShortcut);
// Remove short-cut
try {
platform.deleteShortcut(shortcutFolder, fileName);
}
catch (Exception e) {
// Do not fail if short-cut can't be removed, just log the error.
Installer.log(e);
}
// Remove short-cut directories (if empty)
try {
// Root short-cut folder
IPath baseShortcutFolder = getRemovePath();
while (!shortcutFolder.isRoot()) {
// Do not attempt to remove desktop folder
if (shortcutFolder.equals(platform.getShortcutFolder(ShortcutFolder.DESKTOP)))
break;
// Do not attempt to remove Programs folder on Windows
if (Installer.isWindows() && shortcutFolder.equals(platform.getShortcutFolder(ShortcutFolder.PROGRAMS)))
break;
// Do not attempt to remove installation folder on Linux
if (Installer.isLinux() && shortcutFolder.equals(product.getLocation()))
break;
// Delete short-cut directory
platform.deleteDirectory(shortcutFolder.toOSString(), true);
// If we removed last short-cut folder then exit
if (shortcutFolder.equals(baseShortcutFolder))
break;
// Move to parent short-cut folder
shortcutFolder = shortcutFolder.removeLastSegments(1);
}
}
catch (Exception e) {
// Do not fail if short-cut directory can't be removed, just
// log the error.
Installer.log(e);
}
pm.worked(1);
}
}
finally {
pm.done();
}
}
@Override
public void save(Document document, Element element) throws CoreException {
element.setAttribute(ATTRIBUTE_PATH, getPath().toOSString());
String fileName = InstallUtils.makeFileNameSafe(getName());
element.setAttribute(ATTRIBUTE_NAME, fileName);
if (getRemovePath() != null)
element.setAttribute(ATTRIBUTE_REMOVE_PATH, getRemovePath().toOSString());
}
@Override
public void load(Element element) throws CoreException {
this.path = new Path(element.getAttribute(ATTRIBUTE_PATH));
this.name = element.getAttribute(ATTRIBUTE_NAME);
String value = element.getAttribute(ATTRIBUTE_REMOVE_PATH);
if (value != null)
this.removePath = new Path(value);
}
/**
* Determine if the target file exists. Typically used to decide whether or
* not to create the shortcut. The notable exception is if the target file
* is contained with the "uninstall" directory; if so, true is always
* returned.
*
* @return <code>true</code> if target exists
*/
protected boolean doesTargetExist() {
IPath uninstallDir = Installer.getDefault().getInstallManager().getInstallDescription().getRootLocation().append(IInstallConstants.UNINSTALL_DIRECTORY);
if (uninstallDir.isPrefixOf(getTarget())){
return true;
}
else {
return (getTarget().toFile().exists());
}
}
/**
* Returns if the target is a directory.
*
* @return <code>true</code> if target is directory
*/
protected boolean isTargetDirectory() {
File targetFile = getTarget().toFile();
return targetFile.exists() && targetFile.isDirectory();
}
}