/*******************************************************************************
* Copyright (c) 2007, 2010 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Code 9 - ongoing development
* Mentor Graphics - Modified from original P2 stand-alone installer
*******************************************************************************/
package com.codesourcery.internal.installer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
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.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.equinox.internal.p2.core.helpers.CollectionUtils;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.transport.ecf.RepositoryTransport;
import org.eclipse.equinox.p2.metadata.IVersionedId;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.metadata.VersionedId;
import com.codesourcery.installer.IInstallConstraint;
import com.codesourcery.installer.IInstallDescription;
import com.codesourcery.installer.IInstallPlatform.ShortcutFolder;
import com.codesourcery.installer.IProductRange;
import com.codesourcery.installer.IRepositoryLocation;
import com.codesourcery.installer.InstallPageTitle;
import com.codesourcery.installer.Installer;
import com.codesourcery.installer.LaunchItem;
import com.codesourcery.installer.LaunchItem.LaunchItemPresentation;
import com.codesourcery.installer.LaunchItem.LaunchItemType;
import com.codesourcery.installer.LicenseDescriptor;
import com.codesourcery.installer.LinkDescription;
import com.codesourcery.installer.UninstallMode;
import com.codesourcery.installer.UpdateSite;
@SuppressWarnings("restriction") // Accesses internal P2 API's
public class InstallDescription implements IInstallDescription {
/** P2 profile properties prefix */
public static final String PROP_P2_PROFILE_PREFIX = "p2."; //$NON-NLS-1$
/** Install data defaults propert */
public static final String PROP_DATA_PREFIX = "eclipse.p2.default.";//$NON-NLS-1$
/** Artifact repositories property */
public static final String PROP_ARTIFACT_REPOSITORY = "eclipse.p2.repos.artifacts";//$NON-NLS-1$
/** Install location property */
public static final String PROP_INSTALL_LOCATION = "eclipse.p2.location.install";//$NON-NLS-1$
/** Meta-data repositories property */
public static final String PROP_METADATA_REPOSITORY = "eclipse.p2.repos.metadata";//$NON-NLS-1$
/** Profile name property */
public static final String PROP_PROFILE_NAME = "eclipse.p2.profile.name";//$NON-NLS-1$
/** <code>true</code> to remove profile on uninstall property */
public static final String PROP_REMOVE_PROFILE = "eclipse.p2.profile.remove";//$NON-NLS-1$
/** Required roots property */
public static final String PROP_REQUIRED_ROOTS = "eclipse.p2.roots.required";//$NON-NLS-1$
/** Optional roots property */
public static final String PROP_OPTIONAL_ROOTS = "eclipse.p2.roots.optional";//$NON-NLS-1$
/** Relationships property */
public static final String PROP_ROOTS_CONSTRAINTS = "eclipse.p2.roots.constraints";//$NON-NLS-1$
/** License property */
public static final String PROP_LICENSE = "eclipse.p2.license";//$NON-NLS-1$
/** License installable units property */
public static final String PROP_LICENSE_IU = "eclipse.p2.license.iu";//$NON-NLS-1$
/** Install information property */
public static final String PROP_INFORMATION = "eclipse.p2.wizard.text.information";//$NON-NLS-1$
/** Optional roots default property */
public static final String PROP_OPTIONAL_ROOTS_DEFAULT = "eclipse.p2.roots.optional.default";//$NON-NLS-1$
/** Product identifier property */
public static final String PROP_PRODUCT_ID = "eclipse.p2.product.id";//$NON-NLS-1$
/** Product name property */
public static final String PROP_PRODUCT_NAME = "eclipse.p2.product.name";//$NON-NLS-1$
/** Product category property */
public static final String PROP_PRODUCT_CATEGORY = "eclipse.p2.product.category";//$NON-NLS-1$
/** Vendor name property */
public static final String PROP_PRODUCT_VENDOR = "eclipse.p2.product.vendor";//$NON-NLS-1$
/** Product version property */
public static final String PROP_PRODUCT_VERSION = "eclipse.p2.product.version";//$NON-NLS-1$
/** Product help link property */
public static final String PROP_PRODUCT_HELP = "eclipse.p2.product.help";//$NON-NLS-1$
/** Product root property */
public static final String PROP_PRODUCT_ROOT = "eclipse.p2.product.root";//$NON-NLS-1$
/** Product uninstall name */
public static final String PROP_PRODUCT_UNINSTALL_NAME = "eclipse.p2.product.uninstall.name";//$NON-NLS-1$
/** Root install location property */
public static final String PROP_ROOT_LOCATION_PREFIX = "eclipse.p2.location.root";//$NON-NLS-1$
/** Wizard text prefix property */
public static final String PROP_WIZARD_TEXT_PREFIX = "eclipse.p2.wizard.text";//$NON-NLS-1$
/** Uninstall files property */
public static final String PROP_UNINSTALL_FILES = "eclipse.p2.uninstall.files";//$NON-NLS-1$
/** Links property */
public static final String PROP_LINKS = "eclipse.p2.links";//$NON-NLS-1$
/** Links location property */
public static final String PROP_LINKS_LOCATION = "eclipse.p2.location.links";//$NON-NLS-1$
/** Links default property */
public static final String PROP_LINKS_DEFAULT = "eclipse.p2.links.default";//$NON-NLS-1$
/** Environment paths property */
public static final String PROP_ENV_PATHS = "eclipse.p2.location.paths";//$NON-NLS-1$
/** Launch items property */
public static final String PROP_LAUNCH = "eclipse.p2.wizard.launch";//$NON-NLS-1$
/** Launch presentation property */
public static final String PROP_LAUNCH_PRESENTATION = "eclipse.p2.wizard.launch.presentation";//$NON-NLS-1$
/** Installer window title property */
public static final String PROP_WINDOW_TITLE = "eclipse.p2.window.title";//$NON-NLS-1$
/** Installer title property */
public static final String PROP_TITLE = "eclipse.p2.wizard.title";//$NON-NLS-1$
/** Installer title image property */
public static final String PROP_TITLE_IMAGE = "eclipse.p2.wizard.image";//$NON-NLS-1$
/** Installer wizard pages property */
public static final String PROP_WIZARD_PAGES_ORDER = "eclipse.p2.wizard.pages.order";//$NON-NLS-1$
/** Installer wizard pages excluded property */
public static final String PROP_WIZARD_PAGES_EXCLUDE = "eclipse.p2.wizard.pages.exclude";//$NON-NLS-1$
/** Progress regular expression prefix */
public static final String PROP_PROGRESS_PREFIX = "eclipse.p2.progress";//$NON-NLS-1$
/** Installer modules property */
public static final String PROP_MODULES = "eclipse.p2.modules";//$NON-NLS-1$
/** Update sites property */
private static final String PROP_UPDATE = "eclipse.p2.update";//$NON-NLS-1$
/** Show Components version property */
public static final String PROP_SHOW_COMPONENT_VERSIONS = "eclipse.p2.wizard.components.showVersion";//$NON-NLS-1$
/** Show optional components first property */
public static final String PROP_SHOW_OPTIONAL_FIRST = "eclipse.p2.wizard.components.showOptionalFirst";//$NON-NLS-1$
/** Default expanded roots property */
public static final String PROP_EXPAND_ROOTS = "eclipse.p2.wizard.components.expand";//$NON-NLS-1$
/** Install wizard page navigation property */
public static final String PROP_WIZARD_NAVIGATION = "org.eclipse.p2.wizard.navigation";//$NON-NLS-1$
/** Install wizard page titles property */
public static final String PROP_WIZARD_PAGE_TITLES = "eclipse.p2.wizard.pages.titles";//$NON-NLS-1$
/** Excluded actions property */
public static final String PROP_EXCLUDED_ACTIONS = "eclipse.p2.actions.exclude";//$NON-NLS-1$
/** Patch property */
public static final String PROP_PATCH = "eclipse.p2.patch";//$NON-NLS-1$
/** Requires property */
public static final String PROP_REQUIRES = "eclipse.p2.requires";//$NON-NLS-1$
/** Missing requirement expression property prefix */
public static final String PROP_MISSING_REQUIREMENT_PREFIX = "eclipse.p2.missingRequirement";//$NON-NLS-1$
/** Expression property find suffix */
public static final String PROP_FIND_SUFFIX = ".find";//$NON-NLS-1$
/** Expression property replace suffix */
public static final String PROP_REPLACE_SUFFIX = ".replace";//$NON-NLS-1$
/** Include all repositories property */
public static final String PROP_INCLUDE_ALL_REPOSITORIES = "eclipse.p2.includeAllRepositories";//$NON-NLS-1$
/** Use install registry property */
public static final String PROP_USE_INSTALL_REGISTRY = "eclipse.p2.useInstallRegistry";//$NON-NLS-1$
/** Installer data location property */
public static final String PROP_DATA_LOCATION = "eclipse.p2.location.data";//$NON-NLS-1$
/** Order planner property */
public static final String PROP_ORDER_PLANNER = "eclipse.p2.orderPlanner";//$NON-NLS-1$
/** Install mode */
public static final String PROP_INSTALL = "eclipse.p2.install";//$NON-NLS-1$
/** Install size format */
public static final String PROP_INSTALL_SIZE_FORMAT = "eclipse.p2.install.size.format";//$NON-NLS-1$
/** Uninstall mode */
public static final String PROP_UNINSTALL = "eclipse.p2.uninstall";//$NON-NLS-1$
/** Show product in uninstaller property */
public static final String UNINSTALL_SHOW_UNINSTALL = "SHOW_UNINSTALL";//$NON-NLS-1$
/** Create add/remove entry property */
public static final String UNINSTALL_ADDREMOVE = "CREATE_ADD_REMOVE";//$NON-NLS-1$
/** Remove installation directories on uninstall property */
public static final String UNINSTALL_REMOVE_DIRS = "REMOVE_DIRS";//$NON-NLS-1$
/** Minimum version that can be upgraded property **/
public static final String PROP_MINIMUM_UPGRADE_VERSION = "eclipse.p2.install.upgrade.minVersion";//$NON-NLS-1$
/** Network time-out property **/
public static final String PROP_NETWORK_TIMEOUT = "eclipse.p2.network.timeout";//$NON-NLS-1$
/** Network retry property **/
public static final String PROP_NETWORK_RETRY = "eclipse.p2.network.retry";//$NON-NLS-1$
/** Base location for installer */
private URI base;
/** Installer properties */
private Map<String, String> properties = new HashMap<String, String>();
/** P2 profile properties */
private Map<String, String> profileProperties = new HashMap<String, String>();
/** Root install location */
private IPath rootLocation;
/** P2 install location */
private IPath p2Location;
/** Items to launch after installation */
private LaunchItem[] launchItems;
/** Update sites to add */
private UpdateSite[] updateSites;
/** Product identifier */
private String productId;
/** Product name */
private String productName;
/** Product category */
private String productCategory;
/** Product vendor */
private String productVendor;
/** Product original version text */
private String productVersionText;
/** Product version */
private Version productVersion;
/** Product help URL */
private String productHelp;
/** Product name used during uninstall*/
private String uninstallproductName;
/** Required root installable units */
private IVersionedId[] requiredRoots;
/** Optional root installable units */
private IVersionedId[] optionalRoots;
/** Default optional root installable units */
private IVersionedId[] optionalRootsDefault;
/** Roots that should be expanded in the wizard by default */
private IVersionedId[] expandedRoots;
/** Product licenses */
private LicenseDescriptor[] licenses;
/** P2 profile identifier */
private String profileName;
/** <code>true</code> to remove entire profile on uninstall */
private boolean removeProfile = false;
/** Files to copy for uninstaller */
private String[] uninstallFiles;
/** Uninstaller name */
private String uninstallerName;
/** Short-cuts to create */
private LinkDescription[] links;
/** Short-cuts location */
private IPath linksLocation;
/** Environment pats to add */
private String[] environmentPaths;
/** Installer window title */
private String windowTitle;
/** Installer title */
private String title;
/** Path to title image file */
private IPath titleImage;
/** Install wizard pages */
private String[] wizardPages;
/** Install wizard pages order */
private String[] wizardPagesOrder;
/** Progress regular expression find patterns */
private String[] progressFindPatterns;
/** Progress regular expression replace patterns */
private String[] progressReplacePatterns;
/** Active module identifiers */
private String[] moduleIDs;
/** <code>true</code> to show components version */
private boolean showComponentVersions = false;
/** <code>true</code> to show optional components first */
private boolean showOptionalComponentsFirst = false;
/** Install wizard page navigation */
private WizardNavigation pageNavigation;
/** Wizard page titles */
private InstallPageTitle[] pageTitles;
/** Missing requirement find/replace regular expressions */
private String[][] missingRequirementExpressions;
/** <code>true</code> to include remote repositories during installation */
private boolean includeRemoteRepositories = false;
/** <code>true</code> if install is a patch */
private boolean patch;
/** Product ranges */
private IProductRange[] productRanges;
/** <code>true</code> to use install registry */
private boolean useInstallRegistry = true;
/** Installer data location */
private IPath dataLocation;
/** Uninstall mode or <code>null</code> if no uninstaller */
private UninstallMode uninstallMode;
/** <code>true</code> to use ordered planner */
private boolean orderPlanner=true;
/** Install relationships */
private IInstallConstraint[] relationships;
/** <code>true</code> if product upgrades are supported */
private boolean supportsUpgrade = true;
/** <code>true</code> if product upgrades are supported */
private boolean supportsUpdate = true;
/** Excluded actions */
private String[] excludedActions;
/** Install data defaults */
private Map<String, String> installDataDefaults;
/** Check installer directory **/
private boolean checkEmtptyInstallDirectory=false;
/** Minimum version of product that can be upgraded */
private Version minimumUpgradeVersion;
/** Size format specification */
private String sizeFormat;
/** Installer text */
private HashMap<String, String> installerText = new HashMap<String, String>();
/** Mirror mode */
private MirrorMode mirrorMode = MirrorMode.NONE;
/** Network time-out */
private int networkTimeout = -1;
/** Network retry */
private int networkRetry = -1;
/** <code>true</code> to create product root IU */
private boolean productRoot = true;
/**
* Loads an install description.
*
* @param site Site for description
* @param props Install property values to set or <code>null</code>
* description file or <code>null</code> to use default
* @param monitor Progress monitor
* @throws CoreException on failure
*/
public void load(URI site, Map<String, String> props, IProgressMonitor monitor)
throws CoreException {
try {
InputStream in = null;
try {
in = new RepositoryTransport().stream(site, monitor);
properties = CollectionUtils.loadProperties(in);
} finally {
if (in != null) {
try {
in.close();
}
catch (IOException e) {
// Ignore
}
}
}
// Replace properties
if (props != null) {
Iterator<Entry<String, String>> iter = props.entrySet().iterator();
while (iter.hasNext()) {
Entry<String, String> prop = iter.next();
String name = prop.getKey();
String value = prop.getValue();
properties.put(name, value);
}
}
// Resolve variables
resolveVariables(properties);
base = getBase(site);
// Load properties
initialize();
// Load profile properties
initializeProfileProperties();
// Load install data defaults
initializeDataDefaults();
}
catch (Exception e) {
Installer.fail("Failed to load install description.", e);
}
}
/**
* Reads a property value and performs any special processing specified in a prefix. The property name can specify
* the following prefixes:
* <ul>
* <li>filename: - Converts the property value to a file system safe format.</li>
* <li>nospace: - Replaces any spaces in the property value with underscores.</li>
* <li>nonum: - Removes any numbers or periods from the property value.</li>
* <li>upper: - Converts the property value to uppercase.</li>
* <li>lower: - Converts the property value to lowercase.</li>
* </ul>
*
* If the property name contains no prefix, the property value will be returned as is.
*
* @param variable Property name optionally containing a prefix
* @return Property value
*/
private String resolvePrefixedProperty(String variable) {
String prefix = null;
// Check if special prefix is present
int prefixIndex = variable.indexOf(':');
if (prefixIndex != -1) {
prefix = variable.substring(0, prefixIndex);
variable = variable.substring(prefixIndex + 1);
}
// Read the property value
String propertyValue = readProperty(variable);
// If property is not available, try system
// environment variable
if (propertyValue == null) {
propertyValue = System.getenv(variable);
}
// Handle any prefix processing
if ((prefix != null) && (propertyValue != null)) {
switch (prefix) {
// Replace characters that are no a-z, A-Z, 0-9, or a space
// with dashes.
case "filename":
propertyValue = propertyValue.replaceAll("[^a-zA-Z0-9 ]", "-");
break;
// Replace any spaces with underscores
case "nospace":
propertyValue = propertyValue.replaceAll("[ ]", "_");
break;
// Remove any number characters
case "nonum":
propertyValue = propertyValue.replaceAll("[^a-zA-Z ]", "");
break;
// Convert all characters to upper case
case "upper":
propertyValue = propertyValue.toUpperCase();
break;
// Convert all characters to lower case
case "lower":
propertyValue = propertyValue.toLowerCase();
break;
}
}
return propertyValue;
}
/**
* Resolves property variables, replacing any ${property} with the value
* of the 'property'.
*
* @param properties Properties to replace
*/
private void resolveVariables(Map<String, String> properties) {
try {
Iterator<Entry<String, String>> iter = properties.entrySet().iterator();
while (iter.hasNext()) {
Entry<String, String> entry = iter.next();
String value = entry.getValue();
int start = 0;
int index, index2;
// Start of variable
while ((index = value.indexOf('$', start)) != -1) {
if (index + 1 < value.length()) {
if (value.charAt(index + 1) == '{') {
index2 = value.indexOf('}', index);
if (index2 != -1) {
// Property to replace
String property = value.substring(index + 2, index2);
// Defer resolving late binding properties
if (property.equals(PROP_REPOS_MIRROR) || property.equals(PROP_EXISTING_VERSION)) {
start ++;
}
// Resolve property references
else {
// Property value
String sub = resolvePrefixedProperty(property);
// Replace variable
value = value.substring(0, index) +
(sub != null ? sub : "") +
value.substring(index2 + 1);
entry.setValue(value);
}
}
else {
Installer.log("Error in resolving macros: No matching \"}\" for \"${\".");
break;
}
}
else if (index + 1 < value.length()){
start = index + 1;
}
}
else {
break;
}
}
}
}
catch (Exception e) {
Installer.log(e);
}
}
/**
* Returns the base URI.
*
* @return Base URI
*/
protected URI getBase() {
return base;
}
/**
* Initializes the install description.
*/
protected void initialize() {
String property;
// Update sites
property = readProperty(PROP_UPDATE);
if (property != null) {
ArrayList<UpdateSite> updateSites = new ArrayList<UpdateSite>();
String[] sites = getArrayFromString(property, ",");
for (String site : sites) {
String[] parts = getArrayFromString(site, ";");
UpdateSite updateSite = new UpdateSite(parts[0], parts.length == 2 ? parts[1] : null);
updateSites.add(updateSite);
}
setUpdateSites(updateSites.toArray(new UpdateSite[updateSites.size()]));
}
// Presentation property (used by launch property below)
String presentationProperty = readProperty(PROP_LAUNCH_PRESENTATION);
HashMap<String, LaunchItemPresentation>presentationMap = null;
if (presentationProperty != null) {
presentationMap = new HashMap<String, LaunchItemPresentation>();
String [] presentationPairs = getArrayFromString(presentationProperty, ",");
for (String presentationPair: presentationPairs) {
String [] presentationPairParts = getArrayFromString(presentationPair, ":");
if (presentationPairParts.length == 2) {
presentationMap.put(presentationPairParts[0], LaunchItemPresentation.fromString(presentationPairParts[1]));
}
}
}
// Items to launch
property = readProperty(PROP_LAUNCH);
if (property != null) {
ArrayList<LaunchItem> launchItems = new ArrayList<LaunchItem>();
boolean restartOrLogoutPresent = false;
String[] programs = getArrayFromString(property, ",");
for (String program : programs) {
String[] parts = getArrayFromString(program, ";");
// Launch type
LaunchItemType type = null;
// Executable
if (parts[2].equals(LaunchItemType.EXECUTABLE.getName()))
type = LaunchItemType.EXECUTABLE;
// File
else if (parts[2].equals(LaunchItemType.FILE.getName()))
type = LaunchItemType.FILE;
// URL
else if (parts[2].equals(LaunchItemType.HTML.getName()))
type = LaunchItemType.HTML;
//RESTART and LOGOUT
else if (parts[2].equals(LaunchItemType.RESTART.getName()) ||
parts[2].equals(LaunchItemType.LOGOUT.getName()))
{
/* If multiple restart and logout items are specified, skip
* them.
*/
if (restartOrLogoutPresent)
continue;
type = parts[2].equals(LaunchItemType.RESTART.getName()) ? LaunchItemType.RESTART: LaunchItemType.LOGOUT;
restartOrLogoutPresent = true;
}
parts[1] = parts[1].replace("{exe}", Installer.isWindows() ? ".exe" : "");
// Presentation
LaunchItemPresentation presentation = null;
if (presentationMap != null) {
LaunchItemPresentation overrideType = presentationMap.get(type.getName());
if (overrideType != null) {
presentation = overrideType;
}
}
if (presentation == null) {
if (parts.length > 3) {
/* Older installer.properties use false and true flags */
if (parts[3].equals(LaunchItemPresentation.UNCHECKED.getName()) |
parts[3].equals(Boolean.FALSE.toString())) {
presentation = LaunchItemPresentation.UNCHECKED;
}
else if (parts[3].equals(LaunchItemPresentation.LINK.getName())) {
presentation = LaunchItemPresentation.LINK;
}
}
}
if (presentation == null) {
presentation = LaunchItemPresentation.CHECKED;
}
LaunchItem item = new LaunchItem(type, parts[0], parts[1], presentation);
launchItems.add(item);
}
setLaunchItems(launchItems.toArray(new LaunchItem[launchItems.size()]));
}
// Default install location
property = readProperty(PROP_INSTALL_LOCATION);
if (property != null) {
setInstallLocation(InstallUtils.resolvePath(property));
}
// Profile name
property = readProperty(PROP_PROFILE_NAME);
if (property != null)
setProfileName(property);
// Remove profile
property = readProperty(PROP_REMOVE_PROFILE);
if (property != null)
setRemoveProfile(property.trim().toLowerCase().equals("true"));
// Product identifier
property = readProperty(PROP_PRODUCT_ID);
if (property != null)
setProductId(property);
// Product name
property = readProperty(PROP_PRODUCT_NAME);
if (property != null)
setProductName(property);
// Product category
property = readProperty(PROP_PRODUCT_CATEGORY);
if (property != null)
setProductCategory(property);
// Product vendor
property = readProperty(PROP_PRODUCT_VENDOR);
if (property != null)
setProductVendor(property);
// Product version
property = readProperty(PROP_PRODUCT_VERSION);
if (property != null)
setProductVersionString(property);
// Product help
property = readProperty(PROP_PRODUCT_HELP);
if (property != null)
setProductHelp(property);
// Product root IU property
property = readProperty(PROP_PRODUCT_ROOT);
if (property != null) {
setProductRoot(Boolean.parseBoolean(property));
}
// Product Uninstall Name
property = readProperty(PROP_PRODUCT_UNINSTALL_NAME);
if (property != null)
setProductUninstallName(property);
// Required roots
setRequiredRoots(readRootsProperty(PROP_REQUIRED_ROOTS));
// Optional roots
setOptionalRoots(readRootsProperty(PROP_OPTIONAL_ROOTS));
// Default optional roots
setDefaultOptionalRoots(readRootsProperty(PROP_OPTIONAL_ROOTS_DEFAULT));
// Expanded roots
setWizardExpandedRoots(readRootsProperty(PROP_EXPAND_ROOTS));
// Root constraints
property = readProperty(PROP_ROOTS_CONSTRAINTS);
if (property != null) {
ArrayList<IInstallConstraint> relations = new ArrayList<IInstallConstraint>();
// Get relation specs
String[] relationSpecs = InstallUtils.getArrayFromString(property, ";");
for (String relationSpec : relationSpecs) {
int start = relationSpec.indexOf('(');
if (start != -1) {
String typeSpec = relationSpec.substring(0, start);
IInstallConstraint.Constraint type = IInstallConstraint.Constraint.valueOf(typeSpec);
if (type != null) {
int end = relationSpec.indexOf(')');
if (end != -1) {
String rootsSpec = relationSpec.substring(start + 1, end);
ArrayList<IVersionedId> roots = new ArrayList<IVersionedId>();
String[] parts = InstallUtils.getArrayFromString(rootsSpec, ",");
for (String part : parts) {
VersionedId id = new VersionedId(part, Version.emptyVersion);
roots.add(id);
}
// Add relation
IInstallConstraint relation = new InstallConstraint(roots.toArray(new IVersionedId[roots.size()]), type);
relations.add(relation);
}
}
}
}
// Set relations
setInstallConstraints(relations.toArray(new IInstallConstraint[relations.size()]));
}
// Licenses
ArrayList<LicenseDescriptor> licenses = new ArrayList<LicenseDescriptor>();
// Licenses from files
readLicenses(licenses, PROP_LICENSE, true);
// Install units for licenses
readLicenses(licenses, PROP_LICENSE_IU, false);
if (licenses.size() > 0) {
setLicenses(licenses.toArray(new LicenseDescriptor[licenses.size()]));
}
// Installer text
Map<String, String> wizardText = getPrefixedProperties(PROP_WIZARD_TEXT_PREFIX);
for (Entry<String, String> entry : wizardText.entrySet()) {
String prop = entry.getKey();
String value = entry.getValue();
// Information
if (PROP_INFORMATION.equals(prop)) {
URI[] informationLocations = getURIs(value, getBase());
if (informationLocations.length > 0) {
try {
setText(stripIdentifierPrefix(PROP_INFORMATION, PROP_WIZARD_TEXT_PREFIX),
readFile(informationLocations[0]));
} catch (IOException e) {
LogHelper.log(new Status(IStatus.ERROR, Installer.ID,
"Failed to read information file: " + informationLocations[0], e)); //$NON-NLS-1$
}
}
}
else {
this.setText(stripIdentifierPrefix(prop, PROP_WIZARD_TEXT_PREFIX), value);
}
}
// Install mode
property = readProperty(PROP_INSTALL);
if (property != null) {
String[] flags = getArrayFromString(property, "|");
for (String flag : flags) {
if (flag.equals("NO_UPGRADE")) {
setSupportsUpgrade(false);
}
else if (flag.equals("NO_UPDATE")) {
setSupportsUpdate(false);
}
else if (flag.equals("EMPTY_DIRECTORY")) {
setRequireEmptyInstallDirectory(true);
}
else if (flag.equals("MIRROR")) {
setMirrorMode(MirrorMode.ALL);
}
else if (flag.equals("MIRROR_REMOTE")) {
setMirrorMode(MirrorMode.REMOTE_ONLY);
}
}
}
// Uninstall mode
property = readProperty(PROP_UNINSTALL);
if (property != null) {
boolean showUninstall = false;
boolean createAddRemove = false;
boolean removeDirectories = false;
String[] flags = getArrayFromString(property, "|");
for (String flag : flags) {
if (flag.equals(UNINSTALL_ADDREMOVE))
createAddRemove = true;
else if (flag.equals(UNINSTALL_REMOVE_DIRS))
removeDirectories = true;
else if (flag.equals(UNINSTALL_SHOW_UNINSTALL))
showUninstall = true;
}
UninstallMode mode = new UninstallMode(showUninstall, createAddRemove, removeDirectories);
setUninstallMode(mode);
}
// Uninstall files
property = readProperty(PROP_UNINSTALL_FILES);
// Include uninstaller
if (property != null) {
String[] uninstallFiles = getArrayFromString(property, ","); //$NON-NLS-1$
String uninstallFile;
String uninstallerFileName = IInstallConstants.INSTALLER_NAME;
// Replace executable extensions
for (int index = 0; index < uninstallFiles.length; index++) {
uninstallFile = uninstallFiles[index];
if (uninstallFile.contains(":") && uninstallFile.startsWith("setup{exe}")) {
uninstallerFileName = uninstallFile.substring(uninstallFile.indexOf(":") + 1);
uninstallerFileName = uninstallerFileName.substring(0,uninstallerFileName.indexOf("{exe}"));
}
uninstallFiles[index] = uninstallFiles[index].replace("{exe}",
Installer.isWindows() ? "." + IInstallConstants.EXTENSION_EXE : "");
}
setUninstallFiles(uninstallFiles);
setUninstallerName(uninstallerFileName);
// If the description did not set an uninstall mode, but is including
// uninstaller files, set a default uninstall mode.
if (getUninstallMode() == null) {
setUninstallMode(new UninstallMode(false, true, true));
}
}
// Root location
property = readProperty(PROP_ROOT_LOCATION_PREFIX);
if (property != null) {
setRootLocation(InstallUtils.resolvePath(property));
}
// Data location
property = readProperty(PROP_DATA_LOCATION);
if (property != null) {
setDataLocation(InstallUtils.resolvePath(property));
}
// Network timeout
property = readProperty(PROP_NETWORK_TIMEOUT);
if (property != null) {
try {
setNetworkTimeout(Integer.parseInt(property));
}
catch (Exception e) {
Installer.log(e);
}
}
// Network retry
property = readProperty(PROP_NETWORK_RETRY);
if (property != null) {
try {
setNetworkRetry(Integer.parseInt(property));
}
catch (Exception e) {
Installer.log(e);
}
}
// Short-cuts links location
property = readProperty(PROP_LINKS_LOCATION);
if (property != null) {
setLinksLocation(new Path(property));
}
// Default short-cut link folders
ArrayList<ShortcutFolder> defaultShortcutFolders = new ArrayList<ShortcutFolder>();
property = readProperty(PROP_LINKS_DEFAULT);
if (property != null) {
String[] folders = getArrayFromString(property, ",");
for (String folder : folders) {
if (folder.equals("programs"))
defaultShortcutFolders.add(ShortcutFolder.PROGRAMS);
else if (folder.equals("desktop"))
defaultShortcutFolders.add(ShortcutFolder.DESKTOP);
else if (folder.equals("launcher"))
defaultShortcutFolders.add(ShortcutFolder.UNITY_DASH);
}
}
// Short-cut links
property = readProperty(PROP_LINKS);
if (property != null) {
ArrayList<LinkDescription> linkDescriptions = new ArrayList<LinkDescription>();
String[] links = getArrayFromString(property, ",");
for (String link : links) {
String[] parts = getArrayFromString(link, ";");
// Replace executable extension (if specified)
parts[3] = parts[3].replace("{exe}", Installer.isWindows() ? ".exe" : "");
// Replace icon extension (if specified)
parts[4] = parts[4].replace("{exe}", Installer.isWindows() ? ".exe" : "");
parts[4] = parts[4].replace("{icon}", Installer.isWindows() ? ".ico" : ".png");
String folderSpec = parts[0].trim();
ShortcutFolder folder = null;
if (folderSpec.equals("programs"))
folder = ShortcutFolder.PROGRAMS;
else if (folderSpec.equals("desktop"))
folder = ShortcutFolder.DESKTOP;
else if (folderSpec.equals("launcher"))
folder = ShortcutFolder.UNITY_DASH;
// Default to selected if optional defaults not specified
boolean selected = defaultShortcutFolders.size() == 0;
// Else, check if folder is selected by default
for (ShortcutFolder defaultFolder : defaultShortcutFolders) {
if (folder == defaultFolder) {
selected = true;
break;
}
}
String[] args;
if (parts.length > 5) {
args = getArrayFromString(parts[5], " ");
}
else {
args = new String[0];
}
// Add link description
LinkDescription linkDescription = new LinkDescription(
folder, // Folder
parts[1].trim(), // Link path
parts[2].trim(), // Link name
parts[3].trim(), // Link target
parts[4].trim(), // Icon path
args, // Launcher arguments
selected // Default selection
);
linkDescriptions.add(linkDescription);
}
setLinks(linkDescriptions.toArray(new LinkDescription[linkDescriptions.size()]));
}
// Environment path variables
property = readProperty(PROP_ENV_PATHS);
if (property != null) {
String[] paths = getArrayFromString(property, ",");
setEnvironmnetPaths(paths);
}
// Title
property = readProperty(PROP_TITLE);
if (property != null) {
setTitle(property);
}
// Title image
try {
property = readProperty(PROP_TITLE_IMAGE);
if (property != null) {
URI titleImageLocation = getURI(property, getBase());
File imageFile = URIUtil.toFile(titleImageLocation);
if ((imageFile != null) && imageFile.exists()) {
setTitleImage(new Path(imageFile.getAbsolutePath()));
}
}
}
catch (Exception e) {
Installer.log(e);
}
// Window title
property = readProperty(PROP_WINDOW_TITLE);
if (property != null) {
setWindowTitle(property);
}
// Excluded actions
property = readProperty(PROP_EXCLUDED_ACTIONS);
if (property != null) {
String[] actions = getArrayFromString(property, ",");
setExcludedActions(actions);
}
// Wizard pages excluded
property = readProperty(PROP_WIZARD_PAGES_EXCLUDE);
if (property != null) {
String[] pages = getArrayFromString(property, ",");
setWizardPagesExcluded(pages);
}
// Wizard pages order
property = readProperty(PROP_WIZARD_PAGES_ORDER);
if (property != null) {
String[] pages = getArrayFromString(property, ",");
setWizardPagesOrder(pages);
}
// Wizard page titles
property = readProperty(PROP_WIZARD_PAGE_TITLES);
if (property != null) {
ArrayList<InstallPageTitle> titles = new ArrayList<InstallPageTitle>();
String[] pages = getArrayFromString(property, ",");
for (String page : pages) {
int index = page.indexOf(':');
if (index != -1) {
String pageName = page.substring(0, index);
String pageTitle = page.substring(index + 1);
titles.add(new InstallPageTitle(pageName, pageTitle));
}
}
setPageTitles(titles.toArray(new InstallPageTitle[titles.size()]));
}
// P2 progress find/replace
String[] find = getIndexedProperties(PROP_PROGRESS_PREFIX + PROP_FIND_SUFFIX);
if (find != null) {
String[] replace = getIndexedProperties(PROP_PROGRESS_PREFIX + PROP_REPLACE_SUFFIX);
if ((replace != null) && (replace.length == find.length)) {
setProgressPatterns(find, replace);
}
}
// P2 missing requirement message find/replace expressions
find = getIndexedProperties(PROP_MISSING_REQUIREMENT_PREFIX + PROP_FIND_SUFFIX);
if (find != null) {
String[] replace = getIndexedProperties(PROP_MISSING_REQUIREMENT_PREFIX + PROP_REPLACE_SUFFIX);
if ((replace != null) && (replace.length == find.length)) {
setMissingRequirementExpressions(find, replace);
}
}
// Installer modules
property = readProperty(PROP_MODULES);
if (property != null) {
String[] moduleList = getArrayFromString(property, ","); //$NON-NLS-1$
setModuleIDs(moduleList);
}
// Show/Hide components version on components page
property = readProperty(PROP_SHOW_COMPONENT_VERSIONS);
if (property != null) {
setShowComponentVersions(property.trim().toLowerCase().equals("true"));
}
// Show optional components first on components page
property = readProperty(PROP_SHOW_OPTIONAL_FIRST);
if (property != null) {
setShowOptionalComponentsFirst(property.trim().toLowerCase().equals("true"));
}
// Wizard page navigation
property = readProperty(PROP_WIZARD_NAVIGATION);
if (property != null) {
WizardNavigation navigation = WizardNavigation.fromString(property);
setPageNavigation(navigation);
}
// Patch
property = readProperty(PROP_PATCH);
if (property != null) {
setPatch(property.trim().equals(Boolean.TRUE.toString()));
}
// Requires
property = readProperty(PROP_REQUIRES);
if (property != null) {
try {
ArrayList<IProductRange> productRanges = new ArrayList<IProductRange>();
String[] products = InstallUtils.getArrayFromString(property, ";");
for (String product : products) {
String[] parts = InstallUtils.getArrayFromString(product, ":");
if (parts.length > 0) {
String productId = parts[0];
VersionRange productRange = null;
if (parts.length > 1) {
productRange = InstallUtils.createVersionRange(parts[1]);
}
productRanges.add(new ProductRange(productId, productRange));
}
}
setRequires(productRanges.toArray(new IProductRange[productRanges.size()]));
}
catch (Exception e) {
Installer.log(e);
}
}
// Include remote repositories
property = readProperty(PROP_INCLUDE_ALL_REPOSITORIES);
if (property != null)
setIncludeAllRepositories(property.trim().toLowerCase().equals(Boolean.TRUE.toString()));
// Use install registry
property = readProperty(PROP_USE_INSTALL_REGISTRY);
if (property != null)
setUseInstallRegistry(property.trim().toLowerCase().equals(Boolean.TRUE.toString()));
// Order planner
setOrderPlanner(true);
property = readProperty(PROP_ORDER_PLANNER);
if (property != null)
setOrderPlanner(property.trim().toLowerCase().equals(Boolean.TRUE.toString()));
// Minimum version that can be upgraded
property = readProperty(PROP_MINIMUM_UPGRADE_VERSION);
if (property != null) {
Version minVersion = InstallUtils.createVersion(property);
setMinimumUpgradeVersion(minVersion);
}
// Size format
property = readProperty(PROP_INSTALL_SIZE_FORMAT);
// Default formatting
if (property == null) {
setInstallSizeFormat(InstallMessages.InstallSizeFormat);
}
// Format specified
else if (!property.trim().isEmpty()) {
setInstallSizeFormat(property);
}
}
/**
* Reads license descriptions from an installer property.
*
* @param licenses Collection for license descriptions
* @param propertyName Installer property name
* @param files <code>true</code> if the property is for file based licenses, <code>false</code> if property is
* for install unit based licenses.
*/
private void readLicenses(List<LicenseDescriptor> licenses, String propertyName, boolean files) {
String property = readProperty(propertyName);
if (property != null) {
String[] licenseInfos = getArrayFromString(property, ","); //$NON-NLS-1$
for (String licenseInfo : licenseInfos) {
String licenseName = null;
// License name specified
int index = licenseInfo.lastIndexOf(':');
if (index != -1) {
licenseName = licenseInfo.substring(index + 1);
licenseInfo = licenseInfo.substring(0, index);
}
// License from file
if (files) {
URI[] licenseLocations = getURIs(licenseInfo, getBase());
if (licenseLocations.length > 0) {
try {
String contents = readFile(licenseLocations[0]);
if (contents != null) {
LicenseDescriptor license = new LicenseDescriptor(readFile(licenseLocations[0]), licenseName);
licenses.add(license);
}
else {
Installer.log("Failed to read license file: " + licenseLocations[0]);
}
} catch (IOException e) {
LogHelper.log(new Status(IStatus.ERROR, Installer.ID, "Failed to read license file: " + licenseLocations[0], e)); //$NON-NLS-1$
}
}
}
// License for installable unit
else {
VersionedId id = new VersionedId(licenseInfo, Version.emptyVersion);
LicenseDescriptor license = new LicenseDescriptor(id, licenseName);
licenses.add(license);
}
}
}
}
/**
* Reads versioned roots specified in a property.
*
* @param property Property
* @return Roots or <code>null</code>
*/
private IVersionedId[] readRootsProperty(String property) {
IVersionedId[] readRoots = null;
String rootSpec = readProperty(property);
if (rootSpec != null) {
String[] rootList = getArrayFromString(rootSpec, ","); //$NON-NLS-1$
ArrayList<IVersionedId> roots = new ArrayList<IVersionedId>(rootList.length);
for (int i = 0; i < rootList.length; i++) {
try {
roots.add(VersionedId.parse(rootList[i]));
} catch (IllegalArgumentException e) {
LogHelper.log(new Status(IStatus.ERROR, Installer.ID, InstallMessages.Error_InvalidInstallDescriptionVersion + rootList[i], e)); //$NON-NLS-1$
}
}
if (!roots.isEmpty()) {
readRoots = roots.toArray(new IVersionedId[roots.size()]);
}
}
return readRoots;
}
@Override
public String[] getIndexedProperties(String prefix) {
String[] values = null;
if (readProperty(prefix + ".0") != null) {
int index = 0;
ArrayList<String> patterns = new ArrayList<String>();
for (;;) {
String indexPostfix = Integer.toString(index);
String value = readProperty(prefix + "." + indexPostfix);
if (value == null)
break;
patterns.add(value);
index ++;
}
values = patterns.toArray(new String[patterns.size()]);
}
return values;
}
@Override
public Map<String, String> getPrefixedProperties(String prefix) {
LinkedHashMap<String, String> prefixedProperties = new LinkedHashMap<String, String>();
// Put the default property first
String defaultPropertyValue = readProperty(prefix);
if (defaultPropertyValue != null) {
prefixedProperties.put(prefix, defaultPropertyValue);
}
// Put the remaining properties
for (Entry<String, String> property : properties.entrySet()) {
String propertyName = property.getKey();
// If property is prefixed but not the default value
if (propertyName.startsWith(prefix) && !propertyName.equals(prefix)) {
String propertyValue = readProperty(propertyName);
prefixedProperties.put(propertyName, propertyValue);
}
}
return prefixedProperties;
}
/**
* Reads a property set in the install description. This method will first
* attempt to read the value for an operating specific and/or architecture
* specific property. If those are not found, it will attempt to read the
* default property value. The properties will be read in the following
* order:
*
* <ul>
* <li>prefix.os.arch</li>
* <li>prefix.os</li>
* <li>prefix<li>
* </ul>
*
* @param prefix Prefix for the property name
* @return Property value or <code>null</code>
*/
private String readProperty(String prefix) {
final String[] PROPS_OLD = new String[] {
"eclipse.p2.metadata", "eclipse.p2.artifacts", "eclipse.p2.welcomeText",
"eclipse.p2.installFolderText", "eclipse.p2.windowTitle", "eclipse.p2.title",
"eclipse.p2.information", "eclipse.p2.rootLocation", "eclipse.p2.installLocation",
"eclipse.p2.productId", "eclipse.p2.productName", "eclipse.p2.productCategory",
"eclipse.p2.productVendor", "eclipse.p2.productVersion", "eclipse.p2.productHelp",
"eclipse.p2.profileName", "eclipse.p2.removeProfile", "eclipse.p2.launch",
"eclipse.p2.linksLocation", "eclipse.p2.linksDefault", "eclipse.p2.requiredRoots",
"eclipse.p2.optionalRoots", "eclipse.p2.optionalRootsDefault", "eclipse.p2.licenseIU",
"org.eclipse.p2.wizardNavigation", "eclipse.p2.wizardPages", "eclipse.p2.wizardPageTitles",
"eclipse.p2.hideComponentsVersion", "eclipse.p2.titleImage", "eclipse.p2.dataLocation",
"eclipse.p2.env.paths"
};
final String[] PROPS_NEW = new String[] {
PROP_METADATA_REPOSITORY, PROP_ARTIFACT_REPOSITORY, PROP_WIZARD_TEXT_PREFIX + ".welcome",
PROP_WIZARD_TEXT_PREFIX + ".installFolder", PROP_WINDOW_TITLE, PROP_TITLE,
PROP_INFORMATION, PROP_ROOT_LOCATION_PREFIX, PROP_INSTALL_LOCATION,
PROP_PRODUCT_ID, PROP_PRODUCT_NAME, PROP_PRODUCT_CATEGORY,
PROP_PRODUCT_VENDOR, PROP_PRODUCT_VERSION, PROP_PRODUCT_HELP,
PROP_PROFILE_NAME, PROP_REMOVE_PROFILE, PROP_LAUNCH,
PROP_LINKS_LOCATION, PROP_LINKS_DEFAULT, PROP_REQUIRED_ROOTS,
PROP_OPTIONAL_ROOTS, PROP_OPTIONAL_ROOTS_DEFAULT, PROP_LICENSE_IU,
PROP_WIZARD_NAVIGATION, PROP_WIZARD_PAGES_ORDER, PROP_WIZARD_PAGE_TITLES,
PROP_SHOW_COMPONENT_VERSIONS, PROP_TITLE_IMAGE, PROP_DATA_LOCATION,
PROP_ENV_PATHS
};
String value = null;
if (prefix != null) {
String os = Platform.getOS();
if (!os.equals(Platform.OS_UNKNOWN)) {
String osProperty = prefix + "." + os;
String archProperty = osProperty + "." + Platform.getOSArch();
// Attempt to get value for property that includes operating system
// and architecture in the name
value = properties.get(archProperty);
// If no property is defined, attempt to get value for property with
// only operating system in the name
if (value == null) {
value = properties.get(osProperty);
}
}
// If OS or OS & ARCH property was not found, get the default property
// value
if (value == null) {
value = properties.get(prefix);
}
// Attempt to read older changed property names
if (value == null) {
for (int index = 0; index < PROPS_NEW.length; index ++) {
if (PROPS_NEW[index].equals(prefix)) {
value = properties.get(PROPS_OLD[index]);
break;
}
}
}
}
return value;
}
/**
* Add all of the given properties to profile properties of the given description
* after removing the keys known to be for the installer. This allows install descriptions
* to also set random profile properties.
*/
private void initializeProfileProperties() {
// Load profile properties
Map<String, String> profileProperties = new HashMap<String, String>();
Set<Entry<String, String>> entries = properties.entrySet();
int prefixLength = PROP_P2_PROFILE_PREFIX.length();
for (Entry<String, String> entry : entries) {
String key = entry.getKey();
if (key.startsWith(PROP_P2_PROFILE_PREFIX)) {
String property = key.substring(prefixLength);
profileProperties.put(property, entry.getValue());
}
}
setProfileProperties(profileProperties);
}
/**
* Sets all install data defaults specified in install description.
*/
private void initializeDataDefaults() {
Map<String, String> dataDefaults = new HashMap<String, String>();
Set<Entry<String, String>> entries = properties.entrySet();
int prefixLength = PROP_DATA_PREFIX.length();
for (Entry<String, String> entry : entries) {
String key = entry.getKey();
if (key.startsWith(PROP_DATA_PREFIX)) {
String property = key.substring(prefixLength);
dataDefaults.put(property, entry.getValue());
}
}
setInstallDataDefaults(dataDefaults);
}
/**
* Returns the base URI for a given
* URI.
*
* @param uri URI
* @return Base URI or <code>null</code>.
*/
protected static URI getBase(URI uri) {
if (uri == null)
return null;
String uriString = uri.toString();
int slashIndex = uriString.lastIndexOf('/');
if (slashIndex == -1 || slashIndex == (uriString.length() - 1))
return uri;
return URI.create(uriString.substring(0, slashIndex + 1));
}
/**
* Reads the contents of a file.
*
* @param location File location
* @return File contents
* @throws IOException on failure to read the file.
*/
protected String readFile(URI location) throws IOException {
String contents = null;
File file = new File(location);
if (file.exists()) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
StringBuilder buffer = new StringBuilder();
String line;
String separator = System.getProperty("line.separator"); //$NON-NLS-1$
while ((line = reader.readLine()) != null) {
buffer.append(line);
buffer.append(separator);
}
contents = buffer.toString();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// Ignore
}
}
}
}
return contents;
}
/**
* Returns a URI for a specification.
*
* @param spec Specification
* @param base Base location
* @return URI or <code>null</code>
*/
protected URI getURI(String spec, URI base) {
// Bad specification
if (spec.startsWith("@"))
return null;
URI uri = null;
try {
uri = URIUtil.fromString(spec);
String uriScheme = uri.getScheme();
// Handle jar scheme special to support relative paths
if ((uriScheme != null) && uriScheme.equals("jar")) { //$NON-NLS-1$
String path = uri.getSchemeSpecificPart().substring("file:".length()); //$NON-NLS-1$
URI relPath = URIUtil.append(base, path);
uri = new URI("jar:" + relPath.toString()); //$NON-NLS-1$
}
else {
uri = URIUtil.makeAbsolute(uri, base);
}
} catch (URISyntaxException e) {
LogHelper.log(new Status(IStatus.ERROR, Installer.ID, "Invalid URL in install description: " + spec, e)); //$NON-NLS-1$
}
return uri;
}
/**
* Returns an array of URIs from the given comma-separated list
* of URLs. Returns <code>null</code> if the given spec does not contain any URLs.
* @param specs Repository specifications
* @param base Base location
* @return An array of URIs in the given spec, or <code>null</code>
*/
protected URI[] getURIs(String specs, URI base) {
if (specs.trim().isEmpty())
return new URI[0];
String[] urlSpecs = getArrayFromString(specs, ","); //$NON-NLS-1$
ArrayList<URI> result = new ArrayList<URI>(urlSpecs.length);
for (int i = 0; i < urlSpecs.length; i++) {
String spec = urlSpecs[i].trim();
if (!spec.isEmpty()) {
URI uri = getURI(spec, base);
if (uri != null) {
result.add(uri);
}
}
}
if (result.isEmpty())
return null;
return result.toArray(new URI[result.size()]);
}
/**
* Returns an array of strings from a single string of tokens delimited
* by a separator.
*
* @param list List of tokens
* @param separator Separator
* @return Array of separated strings
*/
protected String[] getArrayFromString(String list, String separator) {
ArrayList<String> parts = new ArrayList<String>();
int start = 0;
int end = list.indexOf(separator);
if (end == -1) {
if (list.trim().isEmpty()) {
return new String[] {};
}
return new String[] { list };
}
else {
String part;
while (end != -1) {
part = list.substring(start, end).trim();
parts.add(part);
start = end + 1;
end = list.indexOf(separator, start);
}
if (start < list.length()) {
part = list.substring(start).trim();
parts.add(part);
}
}
return parts.toArray(new String[parts.size()]);
}
@Override
public String getProperty(String propertyName) {
return readProperty(propertyName);
}
@Override
public void setProperty(String name, String value) {
properties.put(name, value);
}
@Override
public Map<String, String> getProperties(String prefix) {
int prefixLength = prefix.length();
HashMap<String, String> properties = new HashMap<String, String>();
Iterator<Entry<String, String>> iter = getProperties().entrySet().iterator();
while (iter.hasNext()) {
Entry<String, String> entry = iter.next();
String propertyName = entry.getKey();
if (propertyName.startsWith(prefix)) {
propertyName = propertyName.substring(prefixLength);
if (!propertyName.isEmpty()) {
properties.put(propertyName, entry.getValue());
}
}
}
return properties;
}
/**
* Returns all installer properties.
*
* @return Properties
*/
public Map<String, String> getProperties() {
return properties;
}
@Override
public void setWindowTitle(String value) {
windowTitle = value;
}
@Override
public String getWindowTitle() {
return windowTitle;
}
@Override
public void setTitle(String value) {
title = value;
}
@Override
public String getTitle() {
return title;
}
@Override
public void setTitleImage(IPath imagePath) {
this.titleImage = imagePath;
}
@Override
public IPath getTitleImage() {
return titleImage;
}
@Override
public void setProfileProperties(Map<String, String> properties) {
profileProperties.putAll(properties);
}
@Override
public Map<String, String> getProfileProperties() {
return profileProperties;
}
@Override
public void setEnvironmnetPaths(String[] paths) {
this.environmentPaths = paths;
}
@Override
public String[] getEnvironmentPaths() {
return environmentPaths;
}
@Override
public void setInstallLocation(IPath location) {
this.p2Location = location;
}
@Override
public IPath getInstallLocation() {
return getRootLocation().append(p2Location);
}
@Override
public void setRequireEmptyInstallDirectory(boolean requireEmptyCheck) {
this.checkEmtptyInstallDirectory = requireEmptyCheck;
}
@Override
public boolean getRequireEmptyInstallDirectory() {
return checkEmtptyInstallDirectory;
}
@Override
public void setLaunchItems(LaunchItem[] value) {
this.launchItems = value;
}
@Override
public LaunchItem[] getLaunchItems() {
return launchItems;
}
@Override
public void setUpdateSites(UpdateSite[] updateSites) {
this.updateSites = updateSites;
}
@Override
public UpdateSite[] getUpdateSites() {
return updateSites;
}
@Override
public void setProductId(String value) {
productId = value;
}
@Override
public String getProductId() {
return productId;
}
@Override
public void setProductName(String value) {
productName = value;
}
@Override
public String getProductName() {
return productName;
}
@Override
public void setProductCategory(String category) {
this.productCategory = category;
}
@Override
public String getProductCategory() {
return productCategory;
}
@Override
public void setProductVendor(String value) {
productVendor = value;
}
@Override
public String getProductVendor() {
return productVendor;
}
@Override
public void setProductVersionString(String value) {
productVersionText = value;
productVersion = InstallUtils.createVersion(value);
}
@Override
public String getProductVersionString() {
return productVersionText;
}
@Override
public Version getProductVersion() {
return productVersion;
}
@Override
public void setProductHelp(String value) {
productHelp = value;
}
@Override
public String getProductHelp() {
return productHelp;
}
@Override
public void setProductUninstallName(String value) {
uninstallproductName = value;
}
@Override
public String getProductUninstallName() {
return uninstallproductName;
}
@Override
public void setProfileName(String value) {
profileName = value;
}
@Override
public String getProfileName() {
return profileName;
}
@Override
public void setRemoveProfile(boolean removeProfile) {
this.removeProfile = removeProfile;
}
@Override
public boolean getRemoveProfile() {
return removeProfile;
}
@Override
public void setLicenses(LicenseDescriptor[] value) {
licenses = value;
}
@Override
public LicenseDescriptor[] getLicenses() {
return licenses;
}
@Override
public void setUninstallFiles(String[] value) {
uninstallFiles = value;
}
@Override
public String[] getUninstallFiles() {
return uninstallFiles;
}
@Override
public void setModuleIDs(String[] value) {
moduleIDs = value;
}
@Override
public String[] getModuleIDs() {
return moduleIDs;
}
@Override
public void setRootLocation(IPath location) {
this.rootLocation = location;
}
@Override
public IPath getRootLocation() {
return rootLocation;
}
@Override
public void setRequiredRoots(IVersionedId[] value) {
requiredRoots = value;
}
@Override
public IVersionedId[] getRequiredRoots() {
return requiredRoots;
}
@Override
public void setOptionalRoots(IVersionedId[] value) {
optionalRoots = value;
}
@Override
public IVersionedId[] getOptionalRoots() {
return optionalRoots;
}
@Override
public void setDefaultOptionalRoots(IVersionedId[] value) {
optionalRootsDefault = value;
}
@Override
public IVersionedId[] getDefaultOptionalRoots() {
return optionalRootsDefault;
}
@Override
public void setLinks(LinkDescription[] value) {
links = value;
}
@Override
public LinkDescription[] getLinks() {
return links;
}
@Override
public void setLinksLocation(IPath value) {
linksLocation = value;
}
@Override
public IPath getLinksLocation() {
return linksLocation;
}
@Override
public void setUninstallerName(String name) {
uninstallerName = name;
}
@Override
public String getUninstallerName() {
return uninstallerName;
}
@Override
public void setWizardPagesExcluded(String[] wizardPages) {
this.wizardPages = wizardPages;
}
@Override
public String[] getWizardPagesExcluded() {
return wizardPages;
}
@Override
public void setWizardPagesOrder(String[] wizardPages) {
this.wizardPagesOrder = wizardPages;
}
@Override
public String[] getWizardPagesOrder() {
return wizardPagesOrder;
}
@Override
public void setProgressPatterns(String[] find, String[] replace) {
this.progressFindPatterns = find;
this.progressReplacePatterns = replace;
}
@Override
public String[] getProgressFindPatterns() {
return progressFindPatterns;
}
@Override
public String[] getProgressReplacePatterns() {
return progressReplacePatterns;
}
@Override
public void setShowComponentVersions(boolean showComponentsVersion) {
this.showComponentVersions = showComponentsVersion;
}
@Override
public boolean getShowComponentVersions() {
return this.showComponentVersions;
}
@Override
public void setPageNavigation(WizardNavigation pageNavigation) {
this.pageNavigation = pageNavigation;
}
@Override
public WizardNavigation getPageNavigation() {
return pageNavigation;
}
@Override
public void setPageTitles(InstallPageTitle[] pageTitles) {
this.pageTitles = pageTitles;
}
@Override
public InstallPageTitle[] getPageTitles() {
return pageTitles;
}
@Override
public void setMissingRequirementExpressions(String[] find, String[] replace) {
missingRequirementExpressions = new String[find.length][2];
for (int index = 0; index < find.length; index ++) {
missingRequirementExpressions[index][0] = find[index];
missingRequirementExpressions[index][1] = replace[index];
}
}
@Override
public String[][] getMissingRequirementExpressions() {
return missingRequirementExpressions;
}
@Override
public void setIncludeAllRepositories(boolean include) {
this.includeRemoteRepositories = include;
}
@Override
public boolean getIncludeAllRepositories() {
return includeRemoteRepositories;
}
@Override
public void setPatch(boolean patch) {
this.patch = patch;
}
@Override
public boolean getPatch() {
return patch;
}
@Override
public void setRequires(IProductRange[] range) {
this.productRanges = range;
}
@Override
public IProductRange[] getRequires() {
return productRanges;
}
@Override
public void setUseInstallRegistry(boolean useRegistry) {
this.useInstallRegistry = useRegistry;
}
@Override
public boolean getUseInstallRegistry() {
return useInstallRegistry;
}
@Override
public void setDataLocation(IPath dataLocation) {
this.dataLocation = dataLocation;
}
@Override
public IPath getDataLocation() {
return dataLocation;
}
@Override
public void setUninstallMode(UninstallMode mode) {
this.uninstallMode = mode;
}
@Override
public UninstallMode getUninstallMode() {
return uninstallMode;
}
@Override
public void setOrderPlanner(boolean ordered) {
this.orderPlanner = ordered;
}
@Override
public boolean getOrderPlanner() {
return orderPlanner;
}
@Override
public void setWizardExpandedRoots(IVersionedId[] expandedRoots) {
this.expandedRoots = expandedRoots;
}
@Override
public IVersionedId[] getWizardExpandedRoots() {
return expandedRoots;
}
@Override
public void setInstallConstraints(IInstallConstraint[] relationships) {
this.relationships = relationships;
}
@Override
public IInstallConstraint[] getInstallConstraints() {
return relationships;
}
@Override
public void setSupportsUpgrade(boolean supportsUpgrade) {
this.supportsUpgrade = supportsUpgrade;
}
@Override
public boolean getSupportsUpgrade() {
return supportsUpgrade;
}
@Override
public void setSupportsUpdate(boolean supportsUpdate) {
this.supportsUpdate = supportsUpdate;
}
@Override
public boolean getSupportsUpdate() {
return supportsUpdate;
}
@Override
public void setExcludedActions(String[] actions) {
this.excludedActions = actions;
}
@Override
public String[] getExcludedActions() {
return excludedActions;
}
@Override
public void setInstallDataDefaults(Map<String, String> installData) {
this.installDataDefaults = installData;
}
@Override
public Map<String, String> getInstallDataDefaults() {
return installDataDefaults;
}
@Override
public void setMinimumUpgradeVersion(Version version) {
this.minimumUpgradeVersion = version;
}
@Override
public Version getMinimumUpgradeVersion() {
return minimumUpgradeVersion;
}
@Override
public void setInstallSizeFormat(String format) {
this.sizeFormat = format;
}
@Override
public String getInstallSizeFormat() {
return sizeFormat;
}
/**
* Resolves the value of a repository location property to a set of URI locations. The variables are replaced and
* the ${eclipse.p2.repos.mirror} variable is replaced with the value of the specified mirror property.
*
* @param propertyName Name of property to replace value
* @param mirrorProperty Mirror property to use for the ${eclipse.p2.repos.mirror} value
* @return Resolved URI
*/
private URI[] resolveRepositoryLocation(String propertyName, String mirrorProperty) {
URI[] locations = null;
// Get the repository location property value
String value = readProperty(propertyName);
if (value != null) {
// Get the mirror property value
String reposPropertyValue = readProperty(mirrorProperty);
// If it is not specified, just use the default mirror (if available)
if (reposPropertyValue == null) {
reposPropertyValue = readProperty(PROP_REPOS_MIRROR);
}
// Replace the ${eclipse.p2.repos.mirror} value
if (reposPropertyValue != null) {
value = value.replace("${" + PROP_REPOS_MIRROR + "}", reposPropertyValue);
}
// Resolve the repository locations
locations = getURIs(value, getBase());
}
return locations;
}
@Override
public List<IRepositoryLocation> getRepositoryLocations() {
ArrayList<IRepositoryLocation> locations = new ArrayList<IRepositoryLocation>();
// Mirror(s) defined
if (properties.containsKey(PROP_REPOS_MIRROR)) {
// Get the mirror properties
Map<String, String> mirrorProperties = getPrefixedProperties(PROP_REPOS_MIRROR);
// Add the mirror locations
for (Entry<String, String> property : mirrorProperties.entrySet()) {
String propertyName = property.getKey();
// Strip off the mirror property prefix to get mirror identifier
String groupId = stripIdentifierPrefix(propertyName, PROP_REPOS_MIRROR);
// If no identifier, it is the default mirror
if (groupId.isEmpty()) {
groupId = DEFAULT_MIRROR;
}
URI[] metadata = resolveRepositoryLocation(PROP_METADATA_REPOSITORY, propertyName);
URI[] artifact = resolveRepositoryLocation(PROP_ARTIFACT_REPOSITORY, propertyName);
locations.add(new RepositoryLocation(groupId, metadata, artifact));
}
}
// No mirrors defined
else {
URI[] metadata = resolveRepositoryLocation(PROP_METADATA_REPOSITORY, null);
URI[] artifact = resolveRepositoryLocation(PROP_ARTIFACT_REPOSITORY, null);
locations.add(new RepositoryLocation(DEFAULT_MIRROR, metadata, artifact));
}
return Collections.unmodifiableList(locations);
}
/**
* Strips an identifier prefix from a property name, including the '.' is present.
*
* @param propertyName Property name
* @param prefix Property identifier prefix
* @return Property name after prefix
*/
private String stripIdentifierPrefix(String propertyName, String prefix) {
if ((propertyName == null) || (prefix == null))
return null;
String stripped = propertyName.substring(prefix.length());
if (!stripped.isEmpty() && stripped.startsWith(".")) {
stripped = stripped.substring(1);
}
return stripped;
}
/**
* Repository location
*/
private class RepositoryLocation implements IRepositoryLocation {
/** Mirror identifier */
private String id;
/** Mirror meta-data locations */
private URI[] metadataLocations;
/** Mirror artifact locations */
private URI[] artifactLocations;
/**
* Constructor
*
* @param id Identifier
* @param metadataLocations Meta-data locations
* @param artifactLocations Artifact locations
*/
public RepositoryLocation(String id, URI[] metadataLocations, URI[] artifactLocations) {
this.id = id;
this.metadataLocations = metadataLocations;
this.artifactLocations = artifactLocations;
}
@Override
public String getId() {
return id;
}
@Override
public URI[] getMetadataLocations() {
return metadataLocations;
}
@Override
public URI[] getArtifactLocations() {
return artifactLocations;
}
@Override
public String toString() {
return getId();
}
}
@Override
public void setText(String type, String text) {
installerText.put(type, text);
}
@Override
public String getText(String type, String message) {
String text = installerText.get(type);
if (text == null) {
text = message;
}
return text;
}
@Override
public void setShowOptionalComponentsFirst(boolean showOptional) {
this.showOptionalComponentsFirst = showOptional;
}
@Override
public boolean getShowOptionalComponentsFirst() {
return showOptionalComponentsFirst;
}
@Override
public void setMirrorMode(MirrorMode mirrorMode) {
this.mirrorMode = mirrorMode;
}
@Override
public MirrorMode getMirrorMode() {
return mirrorMode;
}
@Override
public void setNetworkTimeout(int timeout) {
this.networkTimeout = timeout;
}
@Override
public int getNetworkTimeout() {
return networkTimeout;
}
@Override
public void setNetworkRetry(int retries) {
this.networkRetry = retries;
}
@Override
public int getNetworkRetry() {
return networkRetry;
}
@Override
public void setProductRoot(boolean root) {
this.productRoot = root;
}
@Override
public boolean getProductRoot() {
return productRoot;
}
}