/*******************************************************************************
* 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;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.program.Program;
import com.codesourcery.installer.IInstallAction;
import com.codesourcery.installer.IInstallComponent;
import com.codesourcery.installer.IInstallData;
import com.codesourcery.installer.IInstallDescription;
import com.codesourcery.installer.IInstallManager;
import com.codesourcery.installer.IInstallManifest;
import com.codesourcery.installer.IInstallMode;
import com.codesourcery.installer.IInstallModule;
import com.codesourcery.installer.IInstallProduct;
import com.codesourcery.installer.IInstallVerifier;
import com.codesourcery.installer.IInstallWizardPage;
import com.codesourcery.installer.IInstalledProduct;
import com.codesourcery.installer.IProductRange;
import com.codesourcery.installer.InstallPageTitle;
import com.codesourcery.installer.Installer;
import com.codesourcery.installer.LaunchItem;
import com.codesourcery.installer.LaunchItem.LaunchItemType;
import com.codesourcery.installer.UninstallMode;
import com.codesourcery.installer.ui.InstallWizardPage;
import com.codesourcery.internal.installer.actions.InstallIUAction;
/**
* This class manages install operations.
* Call {@link #setInstallLocation(IPath)} to set the install location.
*/
public class InstallManager implements IInstallManager {
/** Cleanup progress work */
private static final int CLEANUP_PROGRESS = 10;
/** Uninstall setup progress work */
private static final int UNINSTALL_SETUP_PROGRESS = 10;
/** Product progress work */
private static final int PRODUCT_PROGRESS = 100;
/** Install registry filename */
private static final String INSTALL_REGISTRY_FILENAME = ".registry";
/** Mirror information filename */
private static final String MIRROR_INFO_FILENAME = "mirror.info";
/** Installed product to update with installation */
private IInstalledProduct installedProduct;
/** Cached wizard pages */
private IInstallWizardPage[] wizardPages;
/** Install verifiers*/
private ListenerList installVerifiers = new ListenerList();
/** Install data */
private IInstallData installData;
/** Start time */
private Date startTime;
/**
* Install description
*/
private IInstallDescription installDescription;
/**
* Install manifest
*/
private IInstallManifest installManifest;
/**
* Install modules
*/
IInstallModule[] modules;
/**
* Install location
*/
private IPath installLocation;
/**
* Install mode
*/
private InstallMode installMode;
/**
* Install registry
*/
private InstallRegistry installRegistry = new InstallRegistry();
/** Restart or re-login required or not. **/
private boolean needsResetOrRelogin = false;
/**
* Constructor
*/
public InstallManager() {
// Create default new install manifest
installManifest = new InstallManifest();
// Install registry
installRegistry = new InstallRegistry();
IPath path = Installer.getDefault().getDataFolder().append(INSTALL_REGISTRY_FILENAME);
if (path.toFile().exists()) {
try {
installRegistry.load(path);
} catch (CoreException e) {
Installer.log(e);
}
}
installData = new InstallData();
}
/**
* Disposes of the install manager.
*/
public void dispose() {
// Save install registry
try {
IPath path = Installer.getDefault().getDataFolder().append(INSTALL_REGISTRY_FILENAME);
getInstallRegistry().save(path);
}
catch (Exception e) {
Installer.log(e);
}
}
@Override
public void setInstallDescription(IInstallDescription installDescription) {
this.installDescription = installDescription;
// Load install modules
loadModules();
}
@Override
public IInstallDescription getInstallDescription() {
return installDescription;
}
@Override
public void setInstallManifest(IInstallManifest installManifest) {
this.installManifest = installManifest;
}
@Override
public IInstallManifest getInstallManifest() {
return installManifest;
}
/**
* Returns the install registry.
*
* @return Install registry
*/
private InstallRegistry getInstallRegistry() {
return installRegistry;
}
/**
* Verifies install components.
*
* @return Error message or <code>null</code>
* @throws CoreException on error
*/
protected void verifyInstallComponents() throws CoreException {
IInstallComponent[] components = RepositoryManager.getDefault().getInstallComponents(false);
IStatus[] status = verifyInstallComponents(components);
for (IStatus s : status) {
if (s.getSeverity() == IStatus.ERROR) {
throw new CoreException(new Status(IStatus.ERROR, Installer.ID, s.getMessage()));
}
}
}
@Override
public void setInstallLocation(IPath path, IProgressMonitor monitor) throws CoreException {
// Mirror has already been set
if (getInstallMode().isMirror())
return;
if (monitor == null)
monitor = new NullProgressMonitor();
getInstallDescription().setRootLocation(path);
// Load existing manifest if available
loadManifest(path);
// Location changed
if ((path == null) || !path.equals(installLocation)) {
if (installLocation != null) {
// Stop the P2 agent
RepositoryManager.getDefault().stopAgent();
// Remove the old install location. This will include any artifacts created by the P2 agent.
removeInstallLocation();
}
this.installLocation = path;
// Create new location
if (installLocation != null) {
if (getInstallMode().isInstall() && !getInstallMode().isUpdate() && !getInstallMode().isUpgrade()) {
createInstallLocation(installLocation);
}
// Create the P2 agent.
try {
createAgent(getInstallDescription().getInstallLocation(), monitor);
}
catch (Exception e) {
removeInstallLocation();
this.installLocation = null;
throw e;
}
}
}
if (installLocation != null) {
// Verify install
verifyInstall(RepositoryManager.getDefault().getAgent(), RepositoryManager.getDefault().getInstallProfile());
// Verify install components
verifyInstallComponents();
}
}
@Override
public void setMirrorLocation(IPath path, IProgressMonitor monitor)
throws CoreException {
// Install location has already been set
if (getInstallLocation() != null)
return;
if (monitor == null)
monitor = new NullProgressMonitor();
// Set mirror install mode
installMode.setMirror();
// Set repository manager to create mirror of install
RepositoryManager.getDefault().setCacheLocation(path);
RepositoryManager.getDefault().setUpdateCache(true);
RepositoryManager.getDefault().setCacheOnly(false);
// Create default agent
createAgent(null, monitor);
verifyInstallComponents();
}
@Override
public void setSourceLocation(IPath path) throws CoreException {
MirrorDescription desc = new MirrorDescription();
IPath mirrorInfo = path.append(MIRROR_INFO_FILENAME);
File mirrorInfoFile = mirrorInfo.toFile();
if (!mirrorInfoFile.exists()) {
Installer.fail(InstallMessages.Error_WrongMirror);
}
desc.load(mirrorInfoFile);
// Check that the mirror was made with this installer
if (!getInstallDescription().getProductId().equals(desc.getProductId()) ||
!getInstallDescription().getProductVersionString().equals(desc.getProductVersion())) {
Installer.fail(InstallMessages.Error_WrongMirror);
}
// Set repository manager to install from mirror only
RepositoryManager.getDefault().setCacheLocation(path);
RepositoryManager.getDefault().setUpdateCache(false);
RepositoryManager.getDefault().setCacheOnly(true);
}
/**
* Creates the directories for an install location and records the levels of directories created in the install
* manifest.
*
* @param path Path to install location
* @throws CoreException on failure to create install location
*/
public void createInstallLocation(IPath path) throws CoreException {
String[] segments = path.segments();
IPath location = new Path(path.getDevice(), "/");
ArrayList<String> createdDirectories = new ArrayList<String>();
for (String segment : segments) {
location = location.append(segment);
File directory = location.toFile();
// If directory does not exist then create it and increment the level
// of directories that should be removed on uninstall.
if (!directory.exists()) {
directory.mkdir();
if (!directory.exists()) {
Installer.fail(InstallMessages.NoWritePermissions);
}
else {
createdDirectories.add(directory.getName());
}
}
}
// Record the directories created
String[] directories = createdDirectories.toArray(new String[createdDirectories.size()]);
((InstallManifest)installManifest).setDirectories(directories);
}
/**
* Removes the directories for an install location.
*
* @throws CoreException on failure to remove install location
*/
public void removeInstallLocation() throws CoreException {
// Remove created install artifacts if not an update or upgrade of existing installation
boolean removeInstallLocation = !getInstallMode().isUpdate() && !getInstallMode().isUpgrade();
// Or if there are other products installed at location
if ((getInstallManifest() != null) && (getInstallManifest().getProducts().length != 0)) {
removeInstallLocation = false;
}
if (!removeInstallLocation) {
return;
}
// Get install location to remove
IPath path = getInstallLocation();
if (path == null) {
return;
}
String[] directories = (getInstallManifest() != null) ? ((InstallManifest)getInstallManifest()).getDirectories() : null;
try {
// Remove directories
if (directories != null) {
// Delete created directories if they are empty
for (int index = directories.length - 1; index >= 0; index --) {
// Make sure parent directory name matches
if (!path.lastSegment().equals(directories[index])) {
break;
}
File dir = path.toFile();
// Except for the first directory, delete only if it is empty
if ((index != directories.length - 1) && dir.listFiles().length != 0)
break;
FileUtils.deleteDirectory(dir.toPath());
path = path.removeLastSegments(1);
}
}
// Otherwise remove files in directory
else {
File[] files = path.toFile().listFiles();
for (File file : files) {
if (file.isDirectory())
FileUtils.deleteDirectory(file.toPath());
else
file.delete();
}
}
}
catch (Exception e) {
Installer.fail("Failed to remove install location.", e);
}
}
/**
* Creates and initializes the provisioning agent.
*
* @param installLocation Install location
* @param monitor Progress monitor
* @throws CoreException on failure
*/
private void createAgent(IPath installLocation, IProgressMonitor monitor) throws CoreException {
// Create new P2 agent
// Note, if this is not an existing installation, it will result
// in agent files being created in the location.
IProvisioningAgent agent = RepositoryManager.getDefault().createAgent(installLocation, monitor);
// Let install modules perform any agent initialization
if (agent != null) {
for (IInstallModule module : getModules()) {
try {
module.initAgent(agent);
}
catch (Exception e) {
Installer.log(e);
}
}
}
// Load repositories
try {
RepositoryManager.getDefault().loadInstallRepositories(monitor);
}
catch (Exception e) {
RepositoryManager.getDefault().stopAgent();
throw e;
}
}
@Override
public IPath getInstallLocation() {
return installLocation;
}
/**
* Sets the install mode.
*
* @param installMode Install mode
*/
public void setInstallMode(InstallMode installMode) {
this.installMode = installMode;
}
@Override
public IInstallMode getInstallMode() {
return installMode;
}
/**
* Logs a time stamp.
*
* @param message Message for time stamp.
* @param date Time stamp
*/
private void logTimeStamp(String message, Date date) {
try {
final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Installer.log(message + ": " + format.format(date));
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* Logs start time.
*
* @param message Message for time stamp.
*/
private void logStartTime(String message) {
try {
startTime = Calendar.getInstance().getTime();
logTimeStamp(message, startTime);
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* Logs end time.
*
* @param message Message for time stamp.
*/
private void logEndTime(String message) {
try {
Date endTime = Calendar.getInstance().getTime();
logTimeStamp(message, endTime);
long elapsed = endTime.getTime() - startTime.getTime();
long secondsInMilliseconds = 1000;
long minutesInMilliseconds = secondsInMilliseconds * 60;
long hoursInMilliseconds = minutesInMilliseconds * 60;
long daysInMilliseconds = hoursInMilliseconds * 24;
long elapsedDays = elapsed / daysInMilliseconds;
elapsed = elapsed % daysInMilliseconds;
long elapsedHours = elapsed / hoursInMilliseconds;
elapsed = elapsed % hoursInMilliseconds;
long elapsedMinutes = elapsed / minutesInMilliseconds;
elapsed = elapsed % minutesInMilliseconds;
long elapsedSeconds = elapsed / secondsInMilliseconds;
Installer.log("Total Time: " +
((elapsedDays > 0) ? Long.toString(elapsedDays) + " days " : "") +
((elapsedHours > 0) ? Long.toString(elapsedHours) + " hours " : "") +
((elapsedMinutes > 0) ? Long.toString(elapsedMinutes) + " minutes " : "") +
((elapsedSeconds > 0) ? Long.toString(elapsedSeconds) + " seconds " : "")
);
}
catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void install(IProgressMonitor monitor) throws CoreException {
logStartTime("Install Started");
if (Installer.getDefault().getInstallManager().getInstallMode().isMirror()) {
doMirror(monitor);
}
else {
doInstall(monitor);
}
logEndTime("Install Completed");
}
/**
* Performs a mirror operation.
*
* @param monitor Progress monitor
* @throws CoreException on failure
*/
protected void doMirror(IProgressMonitor monitor) throws CoreException {
if (monitor.isCanceled())
return;
// Units to add
ArrayList<IInstallableUnit> toAdd = new ArrayList<IInstallableUnit>();
// Get the install plan
RepositoryManager.getDefault().getAllInstallUnits(toAdd);
// Peform the provision
RepositoryManager.getDefault().provision(null, toAdd, null, false, monitor);
// Save mirror information
MirrorDescription desc = new MirrorDescription();
desc.setProductId(getInstallDescription().getProductId());
desc.setProductVersion(getInstallDescription().getProductVersionString());
IPath infoPath = RepositoryManager.getDefault().getCacheLocation().append(MIRROR_INFO_FILENAME);
desc.save(infoPath.toFile());
}
/**
* Performs an install operation.
*
* @param monitor Progress monitor
* @throws CoreException on failure
*/
protected void doInstall(IProgressMonitor monitor) throws CoreException {
// Installation mode
InstallMode mode = (InstallMode)Installer.getDefault().getInstallManager().getInstallMode();
// Check for existing version of product
IInstallProduct product = getExistingProduct(getInstallManifest());
// Get install actions
IInstallAction[] actions = getInstallActions(installData);
// Remove existing product if required
if (!mode.isUpdate()) {
if (product != null) {
// Uninstall actions of existing product that require it
for (IInstallAction action : product.getActions()) {
if (action.uninstallOnUpgrade()) {
if (isActionSupported(action)) {
action.run(RepositoryManager.getDefault().getAgent(),
product, new InstallMode(false), new NullProgressMonitor());
if (action.needsRestartOrRelogin())
needsResetOrRelogin = true;
}
}
if (monitor.isCanceled())
break;
}
// Remove existing product
getInstallManifest().removeProduct(product);
product = null;
}
}
// Create new product
if (product == null) {
product = new InstallProduct(
getInstallDescription().getProductId(),
getInstallDescription().getProductName(),
getInstallDescription().getProductVersionString(),
getInstallDescription().getProductUninstallName(),
getInstallDescription().getRootLocation(),
getInstallDescription().getInstallLocation());
// Save if installation directories should be removed for the product
UninstallMode uninstallMode = getInstallDescription().getUninstallMode();
product.setProperty(IInstallProduct.PROPERTY_REMOVE_DIRS,
uninstallMode != null ?
Boolean.toString(getInstallDescription().getUninstallMode().getRemoveDirectories()) :
Boolean.FALSE.toString());
// Save if product should be shown in uninstaller
product.setProperty(IInstallProduct.PROPERTY_SHOW_UNINSTALL,
uninstallMode != null ?
Boolean.toString(getInstallDescription().getUninstallMode().getShowUninstall()) :
Boolean.FALSE.toString());
// Save product additional uninstallation text (if any)
String productUninstallText = getInstallDescription().getText(IInstallDescription.TEXT_UNINSTALL_ADDENDUM, null);
if (productUninstallText != null) {
product.setProperty(IInstallProduct.PROPERTY_UNINSTALL_TEXT, productUninstallText);
}
}
// Compute action ticks
int totalActionWork = 0;
for (IInstallAction action : actions) {
if (isActionSupported(action)) {
totalActionWork += action.getProgressWeight();
}
}
monitor.beginTask("", totalActionWork + CLEANUP_PROGRESS + UNINSTALL_SETUP_PROGRESS);
// Install
int index;
for (index = 0; index < actions.length; index ++) {
IInstallAction action = actions[index];
if (isActionSupported(action)) {
// Run action
SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, action.getProgressWeight());
action.run(RepositoryManager.getDefault().getAgent(),
product, mode, subMonitor);
// Set reset or relogin if it is required for action.
if (action.needsRestartOrRelogin())
needsResetOrRelogin = true;
// Add the action to the product unless the installation mode
// is update or it is the install IU's action
if (!getInstallMode().isUpdate() || !(action instanceof InstallIUAction)) {
product.addAction(action);
}
}
if (monitor.isCanceled())
break;
}
// Installation cancelled - clean up
if (monitor.isCanceled()) {
monitor.setTaskName(InstallMessages.CleanupInstallation);
// If not update, roll back performed actions. For an update, the P2 provisioning operation would have been
// cancelled and IU's rolled back.
if (!getInstallMode().isUpdate()) {
InstallMode rollbackMode = new InstallMode(mode);
rollbackMode.setInstall(false);
// Uninstall performed actions
for (int rollbackIndex = 0; rollbackIndex <= index; rollbackIndex ++) {
if (isActionSupported(actions[rollbackIndex])) {
actions[rollbackIndex].run(RepositoryManager.getDefault().getAgent(),
product, rollbackMode, new NullProgressMonitor());
// Set reset or relogin if it is required for action.
if (actions[rollbackIndex].needsRestartOrRelogin())
needsResetOrRelogin = true;
}
}
}
// Remove install location
setInstallLocation(null, null);
}
// Installation completed
else {
monitor.worked(CLEANUP_PROGRESS);
// Update install manifest
getInstallManifest().addProduct(product);
// Update install registry
if (getInstallDescription().getUseInstallRegistry()) {
getInstallRegistry().addProduct(
new InstalledProduct(
product.getId(),
product.getName(),
product.getVersionString(),
product.getLocation(),
getInstallDescription().getProductCategory()
)
);
}
// Install manifest path
IPath uninstallLocation = getInstallDescription().getRootLocation().append(IInstallConstants.UNINSTALL_DIRECTORY);
IPath manifestPath = uninstallLocation.append(IInstallConstants.INSTALL_MANIFEST_FILENAME);
// Setup uninstaller
try {
if (!mode.isUpdate()) {
String[] uninstallFiles = getInstallDescription().getUninstallFiles();
if (uninstallFiles != null) {
// If there is an existing uninstaller, remove it to ensure
// the latest version is included.
if (uninstallLocation.toFile().exists()) {
try {
FileUtils.deleteDirectory(uninstallLocation.toFile().toPath());
} catch (IOException e) {
Installer.fail(InstallMessages.Error_CopyInstaller, e);
}
}
// Copy installer
if (!manifestPath.toFile().exists()) {
copyInstaller(uninstallLocation, new NullProgressMonitor());
}
}
}
}
catch (Exception e) {
Installer.log(e);
}
// Save manifest
if (getInstallDescription().getUninstallMode() != null) {
getInstallManifest().save(manifestPath.toFile());
}
}
monitor.worked(UNINSTALL_SETUP_PROGRESS);
monitor.done();
}
@Override
public void uninstall(IInstallProduct[] products, IProgressMonitor monitor)
throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor,
products.length * PRODUCT_PROGRESS + products.length * PRODUCT_PROGRESS);
InstallMode mode = (InstallMode)Installer.getDefault().getInstallManager().getInstallMode();
// Remove the products from the registry. It is important that the products be removed before the actions
// are run as InstallIUActions checks remaining products.
for (IInstallProduct product : products) {
// Remove product from manifest
getInstallManifest().removeProduct(product);
// Remove product from install registry
getInstallRegistry().removeProduct(product.getId());
}
// Remove products actions
for (IInstallProduct product : products) {
RepositoryManager.getDefault().createAgent(product.getInstallLocation(), monitor);
RepositoryManager.getDefault().loadInstallRepositories(monitor);
if (monitor.isCanceled())
break;
// Remove product actions
int work = PRODUCT_PROGRESS / product.getActions().length;
for (IInstallAction action : product.getActions()) {
if (isActionSupported(action)) {
action.run(RepositoryManager.getDefault().getAgent(), product, mode, progress.newChild(work));
// Set reset or re-login if it is required for any action.
if (action.needsRestartOrRelogin())
needsResetOrRelogin = true;
}
if (monitor.isCanceled())
break;
}
}
// Update manifest if there are still products installed
if (getInstallManifest().getProducts().length > 0) {
getInstallManifest().save();
monitor.worked(PRODUCT_PROGRESS);
}
// Else remove product directory if all products have been uninstalled
else {
removeProductLocation(products[0], progress.newChild(PRODUCT_PROGRESS));
}
}
@Override
public void launch(LaunchItem item) throws CoreException {
IPath installLocation = getInstallDescription().getRootLocation();
try {
String program;
// Executable item
if (item.getType() == LaunchItemType.EXECUTABLE) {
IPath toRun = installLocation.append(item.getPath());
if (!toRun.toFile().exists())
Installer.fail(InstallMessages.Error_FileNotFound + toRun.toOSString());
ProcessBuilder pb = new ProcessBuilder();
// Set up environment
Map<String, String> environment = pb.environment();
IInstallModule[] modules = getModules();
for (IInstallModule module : modules) {
try {
module.setEnvironmentVariables(environment);
}
catch (Exception e) {
Installer.log(e);
}
}
program = toRun.toOSString();
pb.command(program);
pb.start();
}
// File item
else if (item.getType() == LaunchItemType.FILE) {
IPath toRun = installLocation.append(item.getPath());
if (!toRun.toFile().exists())
Installer.fail(InstallMessages.Error_FileNotFound + toRun.toOSString());
program = "file://" + toRun.toOSString();
Program.launch(program);
}
// HTML item
else if (item.getType() == LaunchItemType.HTML){
program = item.getPath();
Program.launch(program);
}
//RESTART item
else if (item.getType() == LaunchItemType.RESTART) {
if (Installer.isWindows()) {
restart("shutdown -r");
}
else
Installer.log(NLS.bind(InstallMessages.Error_UnsupportedOS, "Restart", System.getProperty("os.name")));
}
//LOGOUT item
else if (item.getType() == LaunchItemType.LOGOUT) {
if (Installer.isWindows()) {
restart("shutdown -l");
}
else if (Installer.isLinux()) {
final String user = System.getProperty("user.name");
if (user == null) {
Installer.log("Unable to obtain user.name");
}
else {
restart("pkill -KILL -u " + user.toLowerCase());
}
}
}
else {
throw new NullPointerException(InstallMessages.Error_NoLaunchItemType);
}
}
catch (Exception e) {
Installer.fail(NLS.bind(InstallMessages.Error_LaunchFailed0, item.getPath()), e);
}
// SWT Program.launch() can throw an UnsatisfiedLinkError if it is
// unable to launch the file.
catch (UnsatisfiedLinkError e) {
Installer.fail(NLS.bind(InstallMessages.Error_LaunchFailed0, item.getPath()), e);
}
}
/**
* Runs a restart command at the end of the installation.
*
* @param command Command to run
*/
private void restart(final String command) {
ShutdownHandler.getDefault().addOperation(new Runnable() {
@Override
public void run() {
try {
Runtime.getRuntime().exec(command);
}
catch (Exception e) {
Installer.log(e);
}
}
});
}
/**
* Returns the wizard pages from all install modules. This method ensures
* that wizard pages with the same name are not returned.
*
* @return Wizard pages
*/
protected IInstallWizardPage[] getModulePages() {
// Filter duplicated named pages, maintain order
LinkedHashMap<String, IInstallWizardPage> pages = new LinkedHashMap<String, IInstallWizardPage>();
for (IInstallModule module : getModules()) {
IInstallWizardPage[] modulePages = module.getInstallPages(getInstallMode());
if (modulePages != null) {
for (IInstallWizardPage modulePage : modulePages) {
pages.put(modulePage.getName(), modulePage);
}
}
}
return pages.values().toArray(new IInstallWizardPage[pages.size()]);
}
/**
* Returns if a wizard page is excluded.
*
* @param wizardPage Wizard page
* @return <code>true</code> if wizard page is excluded
*/
private boolean isWizardPageExcluded(InstallWizardPage wizardPage) {
boolean excluded = false;
String[] excludedPages = getInstallDescription().getWizardPagesExcluded();
if (excludedPages != null) {
for (String excludedPage : excludedPages) {
if (wizardPage.getName().equals(excludedPage)) {
excluded = true;
break;
}
}
}
return excluded;
}
@Override
public IInstallWizardPage[] getWizardPages() {
if (getInstallDescription() == null)
return new IInstallWizardPage[0];
if (wizardPages == null) {
ArrayList<IInstallWizardPage> pages = new ArrayList<IInstallWizardPage>();
// Wizard page order
String[] wizardPagesOrder = getInstallDescription().getWizardPagesOrder();
// First pages to insert
IInstallWizardPage[] firstPages = wizardPagesOrder != null ?
new IInstallWizardPage[wizardPagesOrder.length] : new IInstallWizardPage[0];
// Remaining pages to insert
ArrayList<IInstallWizardPage> remainingPages = new ArrayList<IInstallWizardPage>();
// Page titles
InstallPageTitle[] pageTitles = getInstallDescription().getPageTitles();
IInstallWizardPage[] modulePages = getModulePages();
// Loop through pages from all modules
for (IInstallWizardPage modulePage : modulePages) {
// Verify page base class
if (modulePage instanceof InstallWizardPage) {
InstallWizardPage page = (InstallWizardPage)modulePage;
// Excluded page
if (isWizardPageExcluded(page))
continue;
// Set page title if available
if (pageTitles != null) {
for (InstallPageTitle pageTitle : pageTitles) {
if (pageTitle.getPageName().equals(modulePage.getName())) {
page.setPageLabel(pageTitle.getPageTitle());
break;
}
}
}
// Check if the page is found in the order
int pos = -1;
if (wizardPagesOrder != null) {
for (int index = 0; index < wizardPagesOrder.length; index ++) {
String modulePageName = modulePage.getName();
if ((modulePageName != null) && modulePageName.equals(wizardPagesOrder[index])) {
pos = index;
break;
}
}
}
// First page
if (pos != -1) {
firstPages[pos] = modulePage;
}
// Remaining page
else {
remainingPages.add(modulePage);
}
}
else {
Installer.log(modulePage.getName() + " does not extend InstallWizardPage.");
}
}
// Add first pages
for (IInstallWizardPage page : firstPages) {
if (page != null) {
pages.add(page);
}
}
// Add remaining pages
for (IInstallWizardPage page : remainingPages) {
pages.add(page);
}
wizardPages = pages.toArray(new IInstallWizardPage[pages.size()]);
}
return wizardPages;
}
/**
* Returns all wizard pages that are currently supported.
*
* @return Supported wizard pages
*/
public IInstallWizardPage[] getSupportedWizardPages() {
ArrayList<IInstallWizardPage> supportedPages = new ArrayList<IInstallWizardPage>();
IWizardPage[] pages = getWizardPages();
for (IWizardPage page : pages) {
if (page instanceof IInstallWizardPage) {
IInstallWizardPage wizardPage = (IInstallWizardPage)page;
if (wizardPage.isSupported()) {
supportedPages.add(wizardPage);
}
}
}
return supportedPages.toArray(new IInstallWizardPage[supportedPages.size()]);
}
/**
* Loads the install manifest from the
* install location if available.
*
* @param installLocation Install location
*/
private void loadManifest(IPath installLocation) {
try {
if (getInstallDescription() != null) {
InstallManifest existingManifest = InstallManifest.loadManifest(installLocation);
if (existingManifest != null) {
setInstallManifest(existingManifest);
if (installMode != null) {
// If patch then setup update mode
if (installMode.isPatch()) {
installMode.setUpdate();
}
// Else if install then set update or upgrade based
// on the existing version
else {
// Check for existing version of product
IInstallProduct existingProduct = existingManifest.getProduct(getInstallDescription().getProductId());
if (existingProduct != null) {
// Update same version
if (existingProduct.getVersionString().equals(getInstallDescription().getProductVersionString())) {
installMode.setUpdate();
}
// Upgrade different version
else {
installMode.setUpgrade();
}
}
}
}
}
}
}
catch (Exception e) {
Installer.log(e);
}
}
/**
* Returns if an action is supported on the platform.
*
* @param action Action
* @return <code>true</code> if the action is supported
*/
private boolean isActionSupported(IInstallAction action) {
return action.isSupported(Platform.getOS(), Platform.getOSArch());
}
/**
* This method removes the created directories for a product installation. Files in the product directory will be
* removed and the product directory will be scheduled for removal after the uninstaller exits. Any parent
* directories created during the installation will be scheduled for removal if they are empty.
* Before a directory is scheduled for removal, it is scanned for existing installed products. If any products are
* found, those products will be adjusted so that they remove the directories instead when they are uninstalled
* (regardless if that product created the directory during its installation).
*
* Example:
* Product 1 is installed to /parent/product1 and creates the 'parent' and 'product1' directories.
* Product 2 is then installed to /parent/product2 and only creates the 'product2' directory.
*
* Product 1 records that it should remove two parent directories. Product 2 records that it should only remove
* one parent directory.
* Uninstalling Product 1 will remove the 'product1' directory then adjust the Product 2 directories to remove
* two parent directories when it is uninstalled.
*
* @param product Product
* @param monitor Progress monitor
* @throws CoreException on failure to remove product directory
*/
public void removeProductLocation(IInstallProduct product, IProgressMonitor monitor) throws CoreException {
if (getInstallManifest().getProducts().length == 0) {
// If the product installation directories should be removed on uninstall
String propRemoveDirs = product.getProperty(IInstallProduct.PROPERTY_REMOVE_DIRS);
boolean removeDirs = ((propRemoveDirs == null) || Boolean.parseBoolean(propRemoveDirs));
// Products directory
IPath productPath = getInstallManifest().getInstallLocation();
// Remove installation directories
boolean removed = false;
if (removeDirs) {
// Created directories to remove
String[] directories = (installManifest != null) ? ((InstallManifest)installManifest).getDirectories() : new String[0];
IStatus removeStatus = Status.OK_STATUS;
// Remove files in the product directory (except for uninstaller)
removeStatus = deleteProductFiles(productPath, monitor);
if (removeStatus.isOK()) {
// Schedule the directory to be removed after the uninstaller has exited
ShutdownHandler.getDefault().addDirectoryToRemove(productPath.toOSString(), false);
removed = true;
// Schedule created parent directories to be removed if they are empty
IPath path = productPath.removeLastSegments(1);
for (int index = directories.length - 2; index >= 0; index--) {
String pathName = directories[index];
// Verify parent directory is correct (installation was not moved)
if (!path.lastSegment().equals(pathName)) {
break;
}
// Find any nested products (skipping this product directory)
InstallManifest[] nestedProducts = findProducts(path, productPath);
// If nested products were found, adjust them so that the directories will be removed when
// they are uninstalled instead and stop removing directories.
if (nestedProducts.length != 0) {
try {
for (InstallManifest nestedProduct : nestedProducts) {
ArrayList<String> nestedDirectories = new ArrayList<String>();
// Added remaining parent directories that need to be removed
for (int i = 0; i <= index; i++) {
nestedDirectories.add(directories[i]);
}
// Get product directory (parent of uninstall directory containing manifest)
IPath nestedProductDirectory = nestedProduct.getInstallLocation();
String[] nestedSegments = nestedProductDirectory.removeFirstSegments(path.segmentCount()).segments();
// Add the nested product directories that need to be removed
for (String nestedSegment : nestedSegments) {
nestedDirectories.add(nestedSegment);
}
// Save the nested product manifest
nestedProduct.setDirectories(nestedDirectories.toArray(new String[nestedDirectories.size()]));
nestedProduct.save();
}
}
catch (Exception e) {
Installer.log(e);
}
// Stop removing created parent directories
break;
}
// Schedule the directory to be removed if empty
ShutdownHandler.getDefault().addDirectoryToRemove(path.toOSString(), true);
path = path.removeLastSegments(1);
}
}
if (!removeStatus.isOK()) {
Installer.fail(removeStatus.getMessage());
}
}
// If product directory was not removed then just schedule the uninstall directory to be removed
if (!removed) {
IPath uninstallPath = productPath.append(IInstallConstants.UNINSTALL_DIRECTORY);
if (uninstallPath.toFile().exists()) {
// Make any read-only files writable so they can be removed
try {
FileUtils.setWritable(uninstallPath.toFile().toPath());
} catch (IOException e) {
Installer.log(e);
}
// Add directory for removal on shutdown
ShutdownHandler.getDefault().addDirectoryToRemove(uninstallPath.toOSString(), false);
}
}
}
}
/**
* Finds installed products in a directory.
*
* @param directory Directory to search
* @param skipDirectory Directory to skip
* @return Installed product manifests or empty if no products were found.
*/
private InstallManifest[] findProducts(final IPath directory, final IPath skipDirectory) {
final ArrayList<InstallManifest> products = new ArrayList<InstallManifest>();
final boolean[] removed = new boolean[] { true };
final java.nio.file.Path startPath = directory.toFile().toPath();
final java.nio.file.Path skipPath = (skipDirectory != null) ? skipDirectory.toFile().toPath() : null;
try {
Files.walkFileTree(startPath, new SimpleFileVisitor<java.nio.file.Path>() {
@Override
public FileVisitResult preVisitDirectory(
java.nio.file.Path dir, BasicFileAttributes attrs)
throws IOException {
// Skip product directory files
if (skipPath != null) {
return dir.equals(skipPath) ? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE;
}
else {
return FileVisitResult.CONTINUE;
}
}
@Override
public FileVisitResult postVisitDirectory(
java.nio.file.Path dir, IOException exc)
throws IOException {
FileVisitResult result = FileVisitResult.CONTINUE;
try {
// Load the other products manifest
IPath productPath = new Path(dir.toFile().getAbsolutePath());
InstallManifest manifest = InstallManifest.loadManifest(productPath);
if (manifest != null) {
products.add(manifest);
}
}
catch (Exception e) {
Installer.log(e);
result = FileVisitResult.TERMINATE;
}
return result;
}
});
}
catch (Exception e) {
Installer.log(e);
}
// If no nested products were found, schedule the directory to be removed if it is empty
if (removed[0]) {
ShutdownHandler.getDefault().addDirectoryToRemove(directory.toOSString(), true);
}
return products.toArray(new InstallManifest[products.size()]);
}
/**
* Deletes files in a product directory. The uninstall directory and the
* product directory itself will not be removed.
*
* @param path Product directory
* @param monitor Progress monitor
* @return <code>IStatus.OK</code> on success, <code>IStatus.ERROR</code>
* on failure and the message will contain files that could not be removed.
*/
private IStatus deleteProductFiles(IPath path, IProgressMonitor monitor) {
// Collect files to be removed
final File uninstallDirectory = new File(path.append(IInstallConstants.UNINSTALL_DIRECTORY).toOSString());
// Remove the files except for the uninstall directory (as it can't be removed on Windows while
// the uninstaller is running).
File[] filesNotRemoved = FileUtils.deleteFiles(path.toFile().toPath(), new java.nio.file.Path[] { uninstallDirectory.toPath() }, monitor);
// Some files could not be removed
if ((filesNotRemoved != null) && (filesNotRemoved.length > 0)) {
// Report files that could not be removed
StringBuffer message = new StringBuffer(InstallMessages.Error_FilesNotRemoved);
int count = 0;
for (File fileNotRemoved : filesNotRemoved) {
// Only report up to ten files
if (++count > 10) {
message.append('\n');
message.append(NLS.bind(InstallMessages.More0, filesNotRemoved.length - 10));
break;
}
message.append('\n');
message.append(" ");
message.append(fileNotRemoved.getAbsolutePath());
}
return new Status(IStatus.ERROR, Installer.ID, 0, message.toString(), null);
}
// All files were removed
else {
return Status.OK_STATUS;
}
}
/**
* Loads registered install modules that are specified in the install
* description.
*/
private void loadModules() {
if (modules == null) {
final String[] ids;
String[] moduleIds = installDescription.getModuleIDs();
// If no modules specified, use default module
if (moduleIds == null) {
ids = new String[] { GeneralInstallModule.ID };
}
else {
ids = moduleIds;
}
IInstallData installData = getInstallData();
List<String> idList = (ids != null && ids.length > 0) ? Arrays.asList(ids) : null;
modules = ContributorRegistry.getDefault().getModules(idList);
// Initialize modules
for (IInstallModule module : modules) {
module.init(getInstallDescription());
module.setDataDefaults(installData);
}
// Set data defaults from install description
IInstallDescription description = Installer.getDefault().getInstallManager().getInstallDescription();
if (description != null) {
Map<String, String> defaultData = description.getInstallDataDefaults();
if (defaultData != null) {
for (Entry<String, String> entry : defaultData.entrySet()) {
installData.setProperty(entry.getKey(), entry.getValue());
}
}
}
// Sort modules according to order in install description
Arrays.sort(modules, new Comparator<IInstallModule>() {
@Override
public int compare(IInstallModule arg0, IInstallModule arg1) {
int arg0i = -1;
int arg1i = -1;
for (int index = 0; index < ids.length; index ++) {
if (arg0.getId().equals(ids[index]))
arg0i = index;
if (arg1.getId().equals(ids[index]))
arg1i = index;
}
if (arg0i < arg1i)
return -1;
else if (arg0i > arg1i)
return 1;
else
return 0;
}
});
}
}
/**
* Returns install modules.
*
* @return Install modules
*/
private IInstallModule[] getModules() {
return modules;
}
/**
* Returns the collection of install actions sorted according to their
* install phase, pre-install actions first, followed by install actions,
* followed by post-install actions.
*
* @param installData Install data
* @return Sorted install actions
*/
private IInstallAction[] getInstallActions(IInstallData installData) {
List <IInstallAction> actions = new ArrayList<IInstallAction>();
for (IInstallModule module : getModules()) {
// Get module actions
IInstallAction[] moduleActions = module.getInstallActions(RepositoryManager.getDefault().getAgent(), installData, getInstallMode());
if (moduleActions != null) {
// Add actions that are not excluded
for (IInstallAction moduleAction : moduleActions) {
boolean addAction = true;
String[] excludedActions = getInstallDescription().getExcludedActions();
if (excludedActions != null) {
for (String excludedAction : excludedActions) {
if (moduleAction.getId().equals(excludedAction)) {
addAction = false;
break;
}
}
}
if (addAction) {
actions.add(moduleAction);
}
}
}
}
// Sort the actions according to their install phase attributes.
Collections.sort(actions, new Comparator<IInstallAction>() {
@Override
public int compare(IInstallAction o1, IInstallAction o2) {
return o1.getInstallPhase().ordinal() - o2.getInstallPhase().ordinal();
}
});
return actions.toArray(new IInstallAction[actions.size()]);
}
/**
* Copies the installer to a location.
*
* @param location Destination location
* @param monitor Progress monitor
* @throws CoreException on failure
*/
private void copyInstaller(IPath destinationLocation, IProgressMonitor monitor) throws CoreException {
try {
File uninstallDirectory = destinationLocation.toFile();
if (!uninstallDirectory.exists()) {
uninstallDirectory.mkdirs();
}
String[] uninstallFiles = getInstallDescription().getUninstallFiles();
if (uninstallFiles != null) {
for (String uninstallFile : uninstallFiles) {
String destinationFileName = uninstallFile;
String srcFileName = uninstallFile;
// Parse file name for ":" if renaming of destination file is desired.
if (uninstallFile.contains(":")) {
srcFileName = uninstallFile.substring(0, uninstallFile.indexOf(":"));
destinationFileName = uninstallFile.substring(uninstallFile.indexOf(":") + 1);
}
IPath destPath = destinationLocation.append(destinationFileName);
File srcFile = Installer.getDefault().getInstallFile(srcFileName);
if (srcFile.exists()) {
File destFile = destPath.toFile();
if (srcFile.isDirectory()) {
FileUtils.copyDirectory(srcFile.toPath(), destFile.toPath(), true);
}
else {
FileUtils.copyFile(srcFile.toPath(), destFile.toPath(),true);
}
}
}
}
}
catch (Exception e) {
Installer.log("Failed to copy installer. This could be because you are running from the Eclipse workbench and the exported RCP binary files are not available.");
Installer.log(e);
}
}
@Override
public void setInstalledProduct(IInstalledProduct product, IProgressMonitor monitor) throws CoreException {
this.installedProduct = product;
if (product != null) {
setInstallLocation(product.getInstallLocation(), monitor);
}
}
@Override
public IInstalledProduct getInstalledProduct() {
return installedProduct;
}
@Override
public IInstalledProduct getInstalledProduct(String id) {
return getInstallRegistry().getProduct(id);
}
@Override
public IInstalledProduct[] getInstalledProducts() {
return getInstallRegistry().getProducts();
}
@Override
public IInstalledProduct[] getInstalledProductsByRange(IProductRange[] ranges, boolean uniqueLocations) {
ArrayList<IInstalledProduct> products = new ArrayList<IInstalledProduct>();
HashMap<IPath, IInstalledProduct> locations = new HashMap<IPath, IInstalledProduct>();
for (IProductRange range : ranges) {
IInstalledProduct product = getInstallRegistry().getProduct(range.getId());
if (product != null) {
// Any product version or product version is in range
if ((range.getVersionRange() == null) || range.getVersionRange().isIncluded(product.getVersion())) {
if (uniqueLocations)
locations.put(product.getInstallLocation(), product);
else
products.add(product);
}
}
}
if (uniqueLocations) {
Collection<IInstalledProduct> values = locations.values();
return values.toArray(new IInstalledProduct[values.size()]);
}
else {
return products.toArray(new IInstalledProduct[products.size()]);
}
}
@Override
public IInstalledProduct[] getInstalledProductsByCategory(String category,
boolean uniqueLocations) {
ArrayList<IInstalledProduct> products = new ArrayList<IInstalledProduct>();
HashMap<IPath, IInstalledProduct> locations = new HashMap<IPath, IInstalledProduct>();
IInstalledProduct[] installedProducts = getInstallRegistry().getProducts();
for (IInstalledProduct installedProduct : installedProducts) {
if (category.equals(installedProduct.getCategory())) {
if (uniqueLocations) {
if (locations.get(installedProduct.getInstallLocation()) == null) {
locations.put(installedProduct.getInstallLocation(), installedProduct);
products.add(installedProduct);
}
else {
products.add(installedProduct);
}
}
}
}
return products.toArray(new IInstalledProduct[products.size()]);
}
@Override
public IInstallProduct getExistingProduct(IInstallManifest manifest) {
IInstallProduct product = null;
if (manifest != null) {
// If patch then find existing product that matches
if (getInstallMode().isPatch()) {
// If an installed product has been set, look up its product
// in the manifest
if (getInstalledProduct() != null) {
product = getInstallManifest().getProduct(getInstalledProduct().getId());
}
// Else find a product match in the manifest
else {
IProductRange[] ranges = getInstallDescription().getRequires();
IInstallProduct[] existingProducts = null;
// If any product is applicable
if (ranges == null) {
existingProducts = getInstallManifest().getProducts();
}
// Find products in range
else {
existingProducts = getInstallManifest().getProducts(ranges);
}
// Use first product that matches
if ((existingProducts != null) && (existingProducts.length > 0)) {
product = existingProducts[0];
}
}
}
// Else get existing product in manifest for product being installed
else {
product = manifest.getProduct(getInstallDescription().getProductId());
}
}
return product;
}
/**
* Returns whether restart or re-login required at the end of installation.
*
* @return <code>true</code> if restart or re-login is required, Otherwise returns
* <code>false</code>
*/
public boolean needsRestartOrRelogin() {
return needsResetOrRelogin;
}
@Override
public void addInstallVerifier(IInstallVerifier verifier) {
installVerifiers.add(verifier);
}
@Override
public void removeInstallVerifier(IInstallVerifier verifier) {
installVerifiers.remove(verifier);
}
/**
* Verifies an installation folder.
*
* @param installLocation Install location
* @return Status for the folder
*/
public IStatus[] verifyInstallLocation(IPath installLocation) {
ArrayList<IStatus> status = new ArrayList<IStatus>();
for (Object listener : installVerifiers.getListeners()) {
try {
IStatus verifyStatus = ((IInstallVerifier)listener).verifyInstallLocation(installLocation);
if ((verifyStatus != null) && !verifyStatus.isOK()) {
status.add(verifyStatus);
}
}
catch (Exception e) {
Installer.log(e);
}
}
return status.toArray(new IStatus[status.size()]);
}
/**
* Verifies an install.
*
* @param agent Provisioning agent
* @param profile Install profile
* @throws CoreException if install is not valid
*/
public void verifyInstall(IProvisioningAgent agent, IProfile profile) throws CoreException {
for (Object listener : installVerifiers.getListeners()) {
IStatus status = ((IInstallVerifier)listener).verifyInstall(agent, profile);
if (status.getSeverity() == IStatus.ERROR) {
throw new CoreException(new Status(IStatus.ERROR, Installer.ID, status.getMessage()));
}
}
}
/**
* Verify the user supplied credentials to insure they are valid
*
* @param username
* @param password
* @return
*/
public IStatus[] verifyCredentials(String username, String password) {
ArrayList<IStatus> status = new ArrayList<IStatus>();
for (Object listener : installVerifiers.getListeners()) {
try {
IStatus verifyStatus = ((IInstallVerifier)listener).verifyCredentials(username, password);
if ((verifyStatus != null) && !verifyStatus.isOK()) {
status.add(verifyStatus);
}
}
catch (Exception e) {
Installer.log(e);
}
}
return status.toArray(new IStatus[status.size()]);
}
/**
* Verifies loaded components.
*
* @param components Components
* @return Status for components
*/
public IStatus[] verifyInstallComponents(IInstallComponent[] components) {
ArrayList<IStatus> status = new ArrayList<IStatus>();
for (Object listener : installVerifiers.getListeners()) {
try {
IStatus verifyStatus = ((IInstallVerifier)listener).verifyInstallComponents(components);
if ((verifyStatus != null) && !verifyStatus.isOK()) {
status.add(verifyStatus);
}
}
catch (Exception e) {
Installer.log(e);
}
}
return status.toArray(new IStatus[status.size()]);
}
/**
* Verifies component selection.
*
* @param components Selected components
* @return Status for components selection
*/
public IStatus[] verifyInstallComponentSelection(IInstallComponent[] components) {
ArrayList<IStatus> status = new ArrayList<IStatus>();
for (Object listener : installVerifiers.getListeners()) {
try {
IStatus verifyStatus = ((IInstallVerifier)listener).verifyInstallComponentSelection(components);
if ((verifyStatus != null) && !verifyStatus.isOK()) {
status.add(verifyStatus);
}
}
catch (Exception e) {
Installer.log(e);
}
}
return status.toArray(new IStatus[status.size()]);
}
@Override
public IInstallData getInstallData() {
return installData;
}
@Override
public boolean isLaunchItemAvailable(LaunchItem item) {
boolean available = false;
IPath installLocation = getInstallLocation();
if (item.getType() == LaunchItemType.EXECUTABLE) {
if (installLocation != null) {
IPath path = installLocation.append(item.getPath());
available = (path.toFile().exists());
}
}
// File item
else if (item.getType() == LaunchItemType.FILE) {
if (installLocation != null) {
IPath path = installLocation.append(item.getPath());
available = path.toFile().exists();
}
}
// HTML item
else if (item.getType() == LaunchItemType.HTML){
URI uri = null;
try {
uri = new URI(item.getPath());
} catch (URISyntaxException e) {
Installer.log(e);
}
if (uri != null && uri.getScheme().toLowerCase().equals("file")) {
File file = new File(uri.toString());
available = file.exists();
}
else {
available = true;
}
}
//RESTART and LOGOUT items
else if (item.getType() == LaunchItemType.RESTART || item.getType() == LaunchItemType.LOGOUT) {
available = true;
}
return available;
}
}