blob: 088e3848464e0054fd01d9051614614de046c28f [file] [log] [blame]
package org.eclipse.epp.installer.internal.win32.core.operations;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.eclipse.epp.installer.core.InstallOptions;
import org.eclipse.epp.installer.core.Variables;
import org.eclipse.epp.installer.core.model.ISequence;
import org.eclipse.epp.installer.core.model.ISingleton;
import org.eclipse.epp.installer.core.operations.CreateUninstallerOperation;
import org.eclipse.epp.installer.core.operations.RegisterProductOperation;
import org.eclipse.epp.installer.internal.core.operations.IRegisterProductOptions;
import org.eclipse.epp.installer.internal.core.operations.ProxyOperation;
import org.eclipse.epp.installer.internal.core.operations.StubOperation;
import org.eclipse.epp.installer.internal.win32.core.ProductRegistry;
import com.ice.jni.registry.Registry;
import com.ice.jni.registry.RegistryException;
import com.ice.jni.registry.RegistryKey;
/**
* RegisterProductOperation used to create correct uninstall product entry in windows
* registry.<br/> So user will be able to uninstall application from Windows Add/Remove
* proggrams dialog.<br/> This is Windows only operation.<br/> <br/> As uninstall
* command used <i>javaw.exe -jar InstallDir\install.jar --uninstall</i> command.<br/>
* <br/> Next values of install options used to set registry values:<br/> To set
* Displayed Name used "DisplayName" install options value( see OPTION_DISPLAY_NAME in
* {@link org.eclipse.epp.installer.core.InstallOptions } ).<br/> To set Displayed
* Icon used "DisplayIcon" install options value.<br/> To set Displayed Version used
* "DisplayVersion" install options value.<br/> To set Publisher name used "Publisher"
* install options value( see OPTION_PUBLISHER in
* {@link org.eclipse.epp.installer.core.InstallOptions } ).<br/>
*/
public class Win32RegisterProductOperation extends StubOperation
implements ISequence, ISingleton
{
/**
* Registry path used to store value in.
*/
public static final String REGISTRY_UNINSTALL_KEY = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
/**
* Construct new instance of RegisterProductOperation.
*/
public Win32RegisterProductOperation(ProxyOperation operation) {
super(operation);
}
protected InstallOptions getOptions() {
return ((RegisterProductOperation) this.getProxyOperation()).getInstallOptions();
}
private String getResolvedString(String string) {
InstallOptions options = this.getOptions();
return Variables.resolve(options.getString(string), options);
}
/**
* Retrieve and resolve a value for either the first option key, or if failing that,
* then the second option key.
*
* @param keys the keys used to retrieve value from install options. This method tries
* the first key and if that fails, tries the second, and so on in order,
* stopping when a key is found to have a value or all keys have been
* tried.
* @return the resolved value or null if undetermined
*/
private String getResolvedOption(String[] keys) {
InstallOptions options = getOptions();
String value = null;
for (int i = 0; i < keys.length; i++) {
String eachKey = keys[i];
if (eachKey != null && eachKey.length() != 0) {
value = options.getString(eachKey);
if (value != null && value.length() > 0)
break;
}
}
if (value != null)
value = Variables.resolve(value, options);
return value;
}
/**
* Resolve each of the specified keys in order until a single key resolves or no more
* keys remain. If a resolved name is obtained, then append new instance of
* CreateRegistryKeyOperation for the specified path and name to list of
* prerequisites.
*
* @param path registry path
* @param optionKeys the keys used to retrieve the name from install options. This
* method tries the first key and if that fails, tries the second, and so
* on in order, stopping when a key resolves or all keys have been tried.
* @param checkExistance indicates that CreateRegistryKeyOperation will not be created
* if key already exists
* @return the new registry path or <code>null</code> if it could not be created
*/
private String createRegistryKeyOperation(String path, String[] optionKeys, boolean checkExistance) {
String name = getResolvedOption(optionKeys);
if (name != null && name.length() != 0) {
return createRegistryKeyOperation(path, name, checkExistance);
}
System.out.println("CreateRegistryKeyOperation: cannot resolve keys");
System.out.println(" path: " + path);
StringBuffer buf = new StringBuffer(100);
for (int i = 0; i < optionKeys.length; i++) {
buf.append(i == 0 ? " keys: " : ", ");
buf.append(optionKeys[i]);
}
System.out.println(buf.toString());
return null;
}
/**
* Resolve each of the specified keys in order until a single key resolves or no more
* keys remain. If a resolved name is obtained, then append new instance of
* CreateRegistryKeyOperation for the specified path and name to list of
* prerequisites.
*
* @param path registry path
* @param optionKeys the keys used to retrieve the name from install options. This
* method tries the first key and if that fails, tries the second, and so
* on in order, stopping when a key resolves or all keys have been tried.
* @return the new registry path or <code>null</code> if it could not be created
*/
private String createRegistryKeyOperation(String path, String[] optionKeys) {
return createRegistryKeyOperation(path, optionKeys, false);
}
/**
* Append new instance of CreateRegistryKeyOperation for the specified path and name
* to list of prerequisites.
*
* @param path registry path
* @param name the new child path element
* @param checkExistance indicates that CreateRegistryKeyOperation will not be created
* if key already exists
* @return the new registry path or <code>null</code> if it could not be created
*/
private String createRegistryKeyOperation(String path, String name, boolean checkExistance) {
if (path != null && path.length() != 0 && name != null && name.length() != 0) {
if (checkExistance) {
if (!keyExists(path, name)) // do nothing if key is already created
add(new CreateRegistryKeyOperation(path, name));
} else {
add(new CreateRegistryKeyOperation(path, name));
}
return path + "\\" + name;
}
System.out.println("CreateRegistryKeyOperation: invalid argument");
System.out.println(" path: " + path);
System.out.println(" name: " + name);
return null;
}
/**
* Append new instance of CreateRegistryKeyOperation for the specified path and name
* to list of prerequisites.
*
* @param path registry path
* @param name the new child path element
* @return the new registry path or <code>null</code> if it could not be created
*/
private String createRegistryKeyOperation(String path, String name) {
return createRegistryKeyOperation(path, name, false);
}
/**
* Resolve each of the specified keys in order until a single key resolves or no more
* keys remain. If a resolved value is obtained, then append new instance of
* RegistrySetValueOperation for specified path, name and value to list of
* Prerequisites.
*
* @param path registry path
* @param name the name used to store value in registry
* @param optionKeys the keys used to retrieve the value from install options. This
* method tries the first key and if that fails, tries the second, and so
* on in order, stopping when a key resolves or all keys have been tried.
* @return return <code>false</code> if one of the arguments is invalid or the
* option keys could not be resolved
*/
private boolean addRegistryValueOperation(String path, String name, String[] optionKeys) {
String value = getResolvedOption(optionKeys);
if (value != null) {
return addRegistryValueOperation(path, name, value);
}
System.out.println("RegistrySetValueOperation: cannot resolve keys");
System.out.println(" path: " + path);
System.out.println(" name: " + name);
StringBuffer buf = new StringBuffer(100);
for (int i = 0; i < optionKeys.length; i++) {
buf.append(i == 0 ? " keys: " : ", ");
buf.append(optionKeys[i]);
}
System.out.println(buf.toString());
return false;
}
/**
* Append new instance of RegistrySetValueOperation for specified path, name and value
* to list of Prerequisites.
*
* @param path registry path
* @param name the name used to store value in registry
* @param value the value to store in the registry
* @return return <code>false</code> if one of the arguments is invalid
*/
private boolean addRegistryValueOperation(String path, String name, String value) {
if (path != null && path.length() != 0 && name != null && name.length() != 0 && value != null) {
add(new RegistrySetValueOperation(path, name, value));
return true;
}
System.out.println("RegistrySetValueOperation: invalid argument");
System.out.println(" path: " + path);
System.out.println(" name: " + name);
System.out.println(" value: " + value);
return false;
}
private boolean keyExists(String path, String name) {
return keyExists(path + "\\" + name);
}
private boolean keyExists(String path) {
RegistryKey key = Registry.openSubkey(Registry.HKEY_LOCAL_MACHINE, path, RegistryKey.ACCESS_READ);
if (key != null)
return true;
return false;
}
private boolean valueEquals(String path, String name, String value) {
RegistryKey key = Registry.openSubkey(Registry.HKEY_LOCAL_MACHINE,
path, RegistryKey.ACCESS_READ);
if (key != null) {
try {
String v = key.getStringValue(name);
if (v != null && v.trim().length() > 0)
if (v.equals(value))
return true;
} catch (RegistryException e) {
e.printStackTrace();
}
}
return false;
}
// TODO: javadoc
private String addKey(String path, String name, String field, String value) {
if (path != null && path.length() != 0 && name != null && name.length() != 0
&& field != null && field.length() != 0 && value != null) {
String regPath = path + "\\" + name;
String nameWithNumber = name;
int number = 0;
while (true) {
if (!keyExists(path, nameWithNumber)) {
regPath = createRegistryKeyOperation(path, nameWithNumber);
break;
} else if (valueEquals(regPath, field, value)) {
// create key even if it already exists in
// order to add log record
regPath = createRegistryKeyOperation(path, nameWithNumber);
break;
}
nameWithNumber = name + " (" + number + ")";
regPath = path + "\\" + nameWithNumber;
number++;
}
return regPath;
}
System.out.println("addKey: invalid argument");
System.out.println(" path: " + path);
System.out.println(" name: " + name);
System.out.println(" field: " + field);
System.out.println(" value: " + value);
return null;
}
// TODO: javadoc
private String addKey(String path, String[] optionKeys, String field, String value) {
if (optionKeys != null && optionKeys.length != 0) {
String name = getResolvedOption(optionKeys);
return addKey(path, name, field, value);
}
System.out.println("addKey: invalid argument");
System.out.println(" optionKeys: " + optionKeys);
return null;
}
/**
* Add needed sub oprtations to set of Prerequisites.
*
* @throws Exception
*/
public void prepare() throws Exception {
RegisterProductOperation operation = (RegisterProductOperation) this.getProxyOperation();
String installDir = getResolvedString(InstallOptions.OPTION_INSTALL_DIR);
/*********************************************************************************
* Registry Entries for Ready for Rational Certification <br>
* Software\\<publisher>\\<productName>\\<version>
*/
String publisherRegPath = createRegistryKeyOperation(ProductRegistry.REGISTRY_SOFTWARE_KEY, new String[]{
IRegisterProductOptions.OPTION_REGISTRY_PUBLISHER, InstallOptions.OPTION_PUBLISHER
});
if (publisherRegPath != null) {
String productNameRegPath = createRegistryKeyOperation(publisherRegPath, new String[]{
IRegisterProductOptions.OPTION_REGISTRY_PRODUCT_NAME, InstallOptions.OPTION_PRODUCT_NAME
});
if (productNameRegPath != null) {
String regPath = addKey(productNameRegPath,
new String[] {
IRegisterProductOptions.OPTION_REGISTRY_PRODUCT_VERSION,
InstallOptions.OPTION_PRODUCT_VERSION },
ProductRegistry.LOCATION_VALUE_NAME, installDir);
addRegistryValueOperation(regPath, ProductRegistry.LOCATION_VALUE_NAME, installDir);
}
}
/***********************************************************************
* Registry Entries for Windows Add/Remove Programs <br>
* Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\<productName>
*/
String uninstallRegName = null;
String uninstallProductName = getResolvedOption(new String[]{
IRegisterProductOptions.OPTION_REGISTRY_PRODUCT_NAME, InstallOptions.OPTION_PRODUCT_NAME
});
String uninstallProductVersion = getResolvedOption(new String[]{
IRegisterProductOptions.OPTION_REGISTRY_PRODUCT_VERSION, InstallOptions.OPTION_PRODUCT_VERSION
});
String uninstallRegPath = null;
if (uninstallProductName != null && uninstallProductName.length() > 0) {
if (uninstallProductVersion != null && uninstallProductVersion.length() > 0)
uninstallRegName = uninstallProductName + " " + uninstallProductVersion;
else
uninstallRegName = uninstallProductName;
uninstallRegPath = addKey(REGISTRY_UNINSTALL_KEY, uninstallRegName, "InstallLocation", installDir);
}
if (uninstallRegPath != null) {
// The command to launch the uninstaller
// addRegistryValueOperation(uninstallRegPath, "UninstallString", "javaw.exe" + " -jar \"" + installDir + "\\"
// + operation.getUninstallJarName() + "\" --uninstall");
addRegistryValueOperation(uninstallRegPath, "UninstallString", operation.getUninstallJarName());
// The installation directory
addRegistryValueOperation(uninstallRegPath, "InstallLocation", installDir);
// The installation date in YYYYMMDD format
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Calendar c1 = Calendar.getInstance(); // today
addRegistryValueOperation(uninstallRegPath, "InstallDate", sdf.format(c1.getTime()));
// The name to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "DisplayName", new String[]{
IRegisterProductOptions.OPTION_UNINSTALL_NAME, InstallOptions.OPTION_DISPLAY_NAME
});
// The icon to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "DisplayIcon", new String[]{
IRegisterProductOptions.OPTION_UNINSTALL_ICON,
});
// The version to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "DisplayVersion", new String[]{
IRegisterProductOptions.OPTION_UNINSTALL_VERSION, InstallOptions.OPTION_PRODUCT_VERSION
});
// The publisher to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "Publisher", getResolvedOption(new String[]{
IRegisterProductOptions.OPTION_UNINSTALL_PUBLISHER, IRegisterProductOptions.OPTION_REGISTRY_PUBLISHER, InstallOptions.OPTION_PUBLISHER
}));
// The support string to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "Contact", getResolvedString(
IRegisterProductOptions.OPTION_UNINSTALL_CONTACT
));
// The link to the support website to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "HelpLink", getResolvedString(
IRegisterProductOptions.OPTION_UNINSTALL_HELP_LINK
));
// The telephone number for support to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "HelpTelephone", getResolvedString(
IRegisterProductOptions.OPTION_UNINSTALL_HELP_TELEPHONE
));
// The link to the website for application updates to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "URLUpdateInfo", getResolvedString(
IRegisterProductOptions.OPTION_UNINSTALL_URL_UPDATE_INFO
));
// The link to the application home page to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "URLInfoAbout", getResolvedString(
IRegisterProductOptions.OPTION_UNINSTALL_URL_INFO_ABOUT
));
// The link to the application README to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "Readme", getResolvedString(
IRegisterProductOptions.OPTION_UNINSTALL_README
));
// The comments to display in Windows Add/Remove Programs
addRegistryValueOperation(uninstallRegPath, "Comments", getResolvedString(
IRegisterProductOptions.OPTION_UNINSTALL_COMMENTS
));
// The release type
addRegistryValueOperation(uninstallRegPath, "ReleaseType", getResolvedString(
IRegisterProductOptions.OPTION_UNINSTALL_RELEASE_TYPE
));
// The install log file
addRegistryValueOperation(uninstallRegPath, "LogFile", installDir
+ "\\" + CreateUninstallerOperation.INSTALL_LOG
);
// The install log file
addRegistryValueOperation(uninstallRegPath, "RegistryLocation",
"HKLM\\" + uninstallRegPath
);
}
/*
* TODO [author=Dan] support other key/value pairs:
* InstallSource, RegCompany, RegOwner, EstimatedSize,
* QuietUninstallString, QuietDisplayName,
* ProductID, VersionMajor/VersionMinor (DWORD),
* ParentDisplayName/ParentKeyName,
* NoModify/NoRepair (DWORD), ModifyPath
*/
}
/**
* Return operation name.
*/
public String toString() {
return "Registering product...";
}
public boolean equals(Object obj) {
return getClass().isInstance(obj);
}
public int hashCode() {
return getClass().hashCode();
}
}