r=bernd rs=brendan git-svn-id: svn://10.0.0.236/trunk@191013 18797224-902f-48f8-a5cc-f745e15eee43
1473 lines
44 KiB
Java
1473 lines
44 KiB
Java
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
/*
|
|
* SoftwareUpdate.java 1.0 96/12/19
|
|
*
|
|
*/
|
|
package netscape.softupdate;
|
|
|
|
import java.net.*;
|
|
import java.util.Vector;
|
|
import java.util.Hashtable;
|
|
import java.lang.Thread;
|
|
|
|
import netscape.util.*;
|
|
import netscape.applet.AppletClassLoader;
|
|
import netscape.security.Principal;
|
|
import netscape.security.Target;
|
|
import netscape.security.UserTarget;
|
|
import netscape.security.PrivilegeManager;
|
|
import netscape.security.AppletSecurity;
|
|
import netscape.security.UserDialogHelper;
|
|
import netscape.security.ForbiddenTargetException;
|
|
import netscape.javascript.JSObject;
|
|
|
|
final public class SoftwareUpdate {
|
|
|
|
/* Security strategy
|
|
* Each routine that does something unsafe checks the permissions there
|
|
*/
|
|
// leave the numeric constants for backward compatibility!
|
|
public static final int LIMITED_INSTALL= 0;
|
|
public static final int FULL_INSTALL = 1;
|
|
public static final int SILENT_INSTALL = 2;
|
|
|
|
protected static final String IMPERSONATOR = "Impersonator";
|
|
public static final String INSTALL_PRIV = "SoftwareInstall";
|
|
public static final String SILENT_PRIV = "SilentInstall";
|
|
public static final String FOLDER_FILE_URL = "File URL";
|
|
|
|
/* Errors -200 to -300 */
|
|
public static final int BAD_PACKAGE_NAME = -200;
|
|
public static final int UNEXPECTED_ERROR = -201;
|
|
public static final int ACCESS_DENIED = -202;
|
|
public static final int TOO_MANY_CERTIFICATES = -203; // Installer file must have 1 certificate
|
|
public static final int NO_INSTALLER_CERTIFICATE = -204; // Installer file must have a certificate
|
|
public static final int NO_CERTIFICATE = -205; // Extracted file is not signed
|
|
public static final int NO_MATCHING_CERTIFICATE = -206; // Extracted file does not match installer certificate
|
|
public static final int UNKNOWN_JAR_FILE = -207; // JAR file has not been opened
|
|
public static final int INVALID_ARGUMENTS = -208; // Bad arguments to a function
|
|
public static final int ILLEGAL_RELATIVE_PATH = -209; // Illegal relative path
|
|
public static final int USER_CANCELLED = -210; // User cancelled
|
|
public static final int INSTALL_NOT_STARTED = -211;
|
|
public static final int SILENT_MODE_DENIED = -212;
|
|
public static final int NO_SUCH_COMPONENT = -213; // no such component in the registry.
|
|
public static final int FILE_DOES_NOT_EXIST = -214; //File cannot be deleted as it does not exist
|
|
public static final int FILE_READ_ONLY = -215; // File cannot be deleted as it is read only.
|
|
public static final int FILE_IS_DIRECTORY = -216; // File cannot be deleted as it is a directory
|
|
public static final int NOT_IN_REGISTRY = -217; // Component not found in registry
|
|
public static final int APPLE_SINGLE_ERR = -218; // error in AppleSingle unpacking
|
|
|
|
public static final int SUCCESS = 0;
|
|
public static final int REBOOT_NEEDED = 999;
|
|
|
|
protected String packageName; // Name of the package we are installing
|
|
protected String userPackageName; // User-readable package name
|
|
protected Vector installedFiles; // List of files/processes to be installed
|
|
protected Hashtable patchList; // files that have been patched (orig name is key)
|
|
protected VersionInfo versionInfo; // Component version info
|
|
private FolderSpec packageFolder; // default folder for package
|
|
private ProgressMediator progress; // Progress feedback
|
|
private int userChoice; // User feedback: -1 unknown, 0 is cancel, 1 is OK
|
|
private boolean silent; // Silent upgrade?
|
|
private boolean force; // Force install?
|
|
private int lastError; // the most recent non-zero error
|
|
|
|
|
|
/**
|
|
* @param env JavaScript environment (this inside the installer). Contains installer directives
|
|
* @param inUserPackageName Name of tha package installed. This name is displayed to the user
|
|
*/
|
|
public
|
|
SoftwareUpdate( JSObject env, String inUserPackageName)
|
|
{
|
|
userPackageName = inUserPackageName;
|
|
installPrincipal = null;
|
|
packageName = null;
|
|
packageFolder = null;
|
|
progress = null;
|
|
patchList = new java.util.Hashtable();
|
|
zigPtr = 0;
|
|
userChoice = -1;
|
|
lastError = 0;
|
|
/* Need to verify that this is a SoftUpdate JavaScript object */
|
|
VerifyJSObject(env);
|
|
jarName = (String) env.getMember("src");
|
|
try
|
|
{
|
|
silent = ((Boolean) env.getMember("silent")).booleanValue();
|
|
force = ((Boolean) env.getMember("force")).booleanValue();
|
|
}
|
|
catch (Throwable t)
|
|
{
|
|
System.out.println("Unexpected throw getting silent/force" );
|
|
silent = false;
|
|
force = false;
|
|
}
|
|
}
|
|
|
|
protected void
|
|
finalize() throws Throwable
|
|
{
|
|
CleanUp();
|
|
super.finalize();
|
|
}
|
|
|
|
/* VerifyJSObject
|
|
* Make sure that JSObject is of type SoftUpdate.
|
|
* Since SoftUpdate JSObject can only be created by C code
|
|
* we cannot be spoofed
|
|
*/
|
|
private native void
|
|
VerifyJSObject(JSObject obj);
|
|
/*
|
|
* Reads in the installer certificate, and creates its principal
|
|
*/
|
|
private void
|
|
InitializeInstallerCertificate() throws SoftUpdateException
|
|
{
|
|
Object[] certArray = null;
|
|
|
|
certArray = getCertificates( zigPtr, installerJarName );
|
|
|
|
if ( certArray == null || certArray.length == 0 )
|
|
throw new SoftUpdateException( Strings.error_NoCertificate(), NO_INSTALLER_CERTIFICATE) ;
|
|
|
|
if ( certArray.length > 1 )
|
|
throw new SoftUpdateException( Strings.error_TooManyCertificates(), TOO_MANY_CERTIFICATES);
|
|
|
|
installPrincipal = new netscape.security.Principal( Principal.CERT_KEY,
|
|
(byte[])certArray[0] );
|
|
}
|
|
|
|
/*
|
|
* checks if our principal has privileges for silent install
|
|
*/
|
|
private void
|
|
CheckSilentPrivileges()
|
|
{
|
|
if (silent == false)
|
|
return;
|
|
try
|
|
{
|
|
/* Request impersonation privileges */
|
|
netscape.security.PrivilegeManager privMgr;
|
|
Target impersonation, target;
|
|
|
|
privMgr = AppletSecurity.getPrivilegeManager();
|
|
impersonation = Target.findTarget( IMPERSONATOR );
|
|
privMgr.enablePrivilege( impersonation );
|
|
|
|
/* check the security permissions */
|
|
target = Target.findTarget( SILENT_PRIV );
|
|
|
|
privMgr.checkPrivilegeGranted( target, GetPrincipal(), null );
|
|
}
|
|
catch(Throwable t)
|
|
{
|
|
System.out.println(Strings.error_SilentModeDenied());
|
|
silent = false;
|
|
}
|
|
}
|
|
|
|
/* Request the security privileges, so that the security dialogs
|
|
* pop up
|
|
*/
|
|
private void
|
|
RequestSecurityPrivileges()
|
|
{
|
|
netscape.security.PrivilegeManager privMgr;
|
|
Target impersonation, target;
|
|
|
|
privMgr = AppletSecurity.getPrivilegeManager();
|
|
impersonation = Target.findTarget( IMPERSONATOR );
|
|
privMgr.enablePrivilege( impersonation );
|
|
|
|
/* check the security permissions */
|
|
target = Target.findTarget( INSTALL_PRIV );
|
|
privMgr.enablePrivilege( target, GetPrincipal() );
|
|
}
|
|
|
|
protected final netscape.security.Principal
|
|
GetPrincipal() {
|
|
return installPrincipal;
|
|
}
|
|
|
|
protected final String
|
|
GetUserPackageName() {
|
|
return userPackageName;
|
|
}
|
|
|
|
protected final String
|
|
GetRegPackageName() {
|
|
return packageName;
|
|
}
|
|
|
|
protected final boolean
|
|
GetSilent() {
|
|
return silent;
|
|
}
|
|
|
|
/**
|
|
* @return enumeration of InstallObjects
|
|
*/
|
|
protected final java.util.Enumeration
|
|
GetInstallQueue() {
|
|
if (installedFiles != null)
|
|
return installedFiles.elements();
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* @return the most recent non-zero error code
|
|
* @see ResetError
|
|
*/
|
|
public int GetLastError()
|
|
{
|
|
return lastError;
|
|
}
|
|
|
|
/**
|
|
* resets remembered error code to zero
|
|
* @see GetLastError
|
|
*/
|
|
public void ResetError()
|
|
{
|
|
lastError = 0;
|
|
}
|
|
|
|
/**
|
|
* saves non-zero error codes so they can be seen by GetLastError()
|
|
*/
|
|
private int saveError(int errcode)
|
|
{
|
|
if ( errcode != SUCCESS )
|
|
lastError = errcode;
|
|
return errcode;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @return the folder object suitable to be passed into AddSubcomponent
|
|
* @param folderID One of the predefined folder names
|
|
* @see AddSubcomponent
|
|
*/
|
|
public FolderSpec
|
|
GetFolder(String folderID)
|
|
{
|
|
FolderSpec spec = null;
|
|
try
|
|
{
|
|
int errCode = 0;
|
|
|
|
if ((folderID.compareTo("Installed") != 0) && (folderID.compareTo(FOLDER_FILE_URL) != 0))
|
|
{
|
|
spec = new FolderSpec(folderID, packageName, userPackageName);
|
|
if (folderID == "User Pick") // Force the prompt
|
|
{
|
|
String ignore = spec.GetDirectoryPath();
|
|
}
|
|
}
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
return null;
|
|
}
|
|
return spec;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return the full path to a component as it is known to the
|
|
* Version Registry
|
|
* @param component Version Registry component name
|
|
*/
|
|
public FolderSpec GetComponentFolder( String component )
|
|
{
|
|
String dir;
|
|
FolderSpec spec = null;
|
|
|
|
dir = VersionRegistry.getDefaultDirectory( component );
|
|
|
|
if ( dir == null )
|
|
{
|
|
dir = VersionRegistry.componentPath( component );
|
|
if ( dir != null )
|
|
{
|
|
int i;
|
|
|
|
if ((i = dir.lastIndexOf(java.lang.System.getProperty("file.separator"))) > 0)
|
|
{
|
|
char c[] = new char[i];
|
|
dir.getChars(0, i, c, 0);
|
|
dir = new String( c );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( dir != null ) /* We have a directory */
|
|
{
|
|
spec = new FolderSpec("Installed", dir, userPackageName);
|
|
}
|
|
return spec;
|
|
}
|
|
|
|
public FolderSpec GetComponentFolder( String component, String subdir )
|
|
{
|
|
return GetFolder( GetComponentFolder( component ), subdir );
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* sets the default folder for the package
|
|
* @param folder a folder object obtained through GetFolder()
|
|
*/
|
|
public void SetPackageFolder( FolderSpec folder )
|
|
{
|
|
packageFolder = folder;
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns a Windows Profile object if you're on windows,
|
|
* null if you're not or if there's a security error
|
|
*/
|
|
public Object
|
|
GetWinProfile(FolderSpec folder, String file)
|
|
{
|
|
WinProfile profile = null;
|
|
String osName = System.getProperty("os.name");
|
|
|
|
try {
|
|
if ( packageName == null ) {
|
|
throw new SoftUpdateException(
|
|
Strings.error_WinProfileMustCallStart(),
|
|
INSTALL_NOT_STARTED );
|
|
}
|
|
|
|
if ( osName.indexOf("Windows") >= 0 || osName.equals("Win32s") ||
|
|
osName.equals("OS/2") )
|
|
{
|
|
profile = new WinProfile(this, folder, file);
|
|
}
|
|
}
|
|
catch (Throwable e) {
|
|
profile = null;
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return profile;
|
|
}
|
|
|
|
/**
|
|
* @return an object for manipulating the Windows Registry.
|
|
* Null if you're not on windows
|
|
*/
|
|
public Object GetWinRegistry()
|
|
{
|
|
WinReg registry = null;
|
|
String osName = System.getProperty("os.name");
|
|
|
|
try {
|
|
if ( packageName == null )
|
|
throw new SoftUpdateException(
|
|
Strings.error_WinProfileMustCallStart(),
|
|
INSTALL_NOT_STARTED);
|
|
|
|
if ( osName.indexOf("Windows") >= 0 || osName.equals("Win32s")) {
|
|
registry = new WinReg(this);
|
|
}
|
|
}
|
|
catch (Throwable e) {
|
|
registry = null;
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return registry;
|
|
}
|
|
|
|
/* JAR file manipulation */
|
|
|
|
private String installerJarName; // Name of the installer file
|
|
private String jarName; // Name of the JAR file
|
|
private int zigPtr; // Stores the pointer to ZIG *
|
|
private netscape.security.Principal installPrincipal; /* principal with the signature from the JAR file */
|
|
|
|
|
|
/* Open/close the jar file
|
|
*/
|
|
private native void OpenJARFile() throws SoftUpdateException;
|
|
private native void CloseJARFile();
|
|
|
|
/* getCertificates
|
|
* native encapsulation that calls AppletClassLoader.getCertificates
|
|
* we cannot call this method from Java because it is private.
|
|
* The method cannot be made public because it is a security risk
|
|
*/
|
|
private native Object[] getCertificates(int zigPtr, String inJarLocation);
|
|
|
|
/**
|
|
* extract the file out of the JAR directory and places it into temporary
|
|
* directory.
|
|
* two security checks:
|
|
* - the certificate of the extracted file must match the installer certificate
|
|
* - must have privileges to extract the jar file
|
|
* @param inJarLocation file name inside the JAR file
|
|
*/
|
|
protected String
|
|
ExtractJARFile( String inJarLocation, String finalFile ) throws SoftUpdateException,
|
|
netscape.security.AppletSecurityException
|
|
{
|
|
if (zigPtr == 0)
|
|
throw new SoftUpdateException("JAR file has not been opened", UNKNOWN_JAR_FILE);
|
|
|
|
/* Security checks */
|
|
Target target;
|
|
PrivilegeManager privMgr;
|
|
privMgr = AppletSecurity.getPrivilegeManager();
|
|
target = Target.findTarget( INSTALL_PRIV );
|
|
|
|
privMgr.checkPrivilegeEnabled(target);
|
|
|
|
/* Make sure that the certificate of the extracted file matches
|
|
the installer certificate */
|
|
/* XXX this needs to be optimized, so that we do not create a principal
|
|
for every certificate */
|
|
{
|
|
int i;
|
|
boolean haveMatch = false;
|
|
Object[] certArray = null;
|
|
certArray = getCertificates( zigPtr, inJarLocation );
|
|
if (certArray == null || certArray.length == 0)
|
|
{
|
|
throw new SoftUpdateException("Missing certificate for "
|
|
+ inJarLocation, NO_CERTIFICATE);
|
|
}
|
|
|
|
for (i=0; i < certArray.length; i++)
|
|
{
|
|
netscape.security.Principal prin = new netscape.security.Principal( Principal.CERT_KEY,
|
|
(byte[])certArray[i] );
|
|
if (installPrincipal.equals( prin ))
|
|
{
|
|
haveMatch = true;
|
|
break;
|
|
}
|
|
}
|
|
if (haveMatch == false)
|
|
throw new SoftUpdateException(Strings.error_MismatchedCertificate() + inJarLocation,
|
|
NO_MATCHING_CERTIFICATE);
|
|
}
|
|
|
|
/* Extract the file */
|
|
// System.out.println("Extracting " + inJarLocation);
|
|
String outExtractLocation;
|
|
outExtractLocation = NativeExtractJARFile(inJarLocation, finalFile);
|
|
// System.out.println("Extracted to " + outExtractLocation);
|
|
return outExtractLocation;
|
|
}
|
|
|
|
private native String
|
|
NativeExtractJARFile( String inJarLocation, String finalFile ) throws SoftUpdateException;
|
|
|
|
/**
|
|
* Call this to initialize the update
|
|
* Opens the jar file and gets the certificate of the installer
|
|
* Opens up the gui, and asks for proper security privileges
|
|
* @param vrPackageName Full qualified version registry name of the package
|
|
* (ex: "/Plugins/Adobe/Acrobat")
|
|
* null or empty package names are errors
|
|
* @param inVInfo version of the package installed.
|
|
* Can be null, in which case package is installed
|
|
* without a version. Having a null version, this package is
|
|
* automatically updated in the future (ie. no version check is performed).
|
|
* @param securityLevel ignored (was LIMITED_INSTALL or FULL_INSTALL)
|
|
*/
|
|
public int
|
|
StartInstall(String vrPackageName,
|
|
VersionInfo inVInfo,
|
|
int securityLevel)
|
|
{
|
|
// ignore securityLevel
|
|
return StartInstall( vrPackageName, inVInfo );
|
|
}
|
|
|
|
|
|
/**
|
|
* An new form that doesn't require the security level
|
|
*/
|
|
public int
|
|
StartInstall(String vrPackageName, VersionInfo inVInfo )
|
|
{
|
|
int errcode = SUCCESS;
|
|
ResetError();
|
|
|
|
try
|
|
{
|
|
if ( (vrPackageName == null) )
|
|
throw new SoftUpdateException( Strings.error_BadPackageName() , INVALID_ARGUMENTS );
|
|
|
|
packageName = vrPackageName;
|
|
while ( packageName.endsWith("/")) // Make sure that package name does not end with '/'
|
|
{
|
|
char c[] = new char[packageName.length() - 1];
|
|
packageName.getChars(0, packageName.length() -1, c, 0);
|
|
packageName = new String( c );
|
|
// System.out.println("Truncated package name is " + packageName);
|
|
|
|
}
|
|
versionInfo = inVInfo;
|
|
installedFiles = new java.util.Vector();
|
|
|
|
/* JAR initialization */
|
|
/* open the file, create a principal out of installer file certificate */
|
|
OpenJARFile();
|
|
InitializeInstallerCertificate();
|
|
CheckSilentPrivileges();
|
|
RequestSecurityPrivileges();
|
|
progress = new ProgressMediator(this);
|
|
progress.StartInstall();
|
|
|
|
// set up default package folder, if any
|
|
String path = VersionRegistry.getDefaultDirectory( packageName );
|
|
if ( path != null )
|
|
{
|
|
packageFolder = new FolderSpec("Installed", path, userPackageName);
|
|
}
|
|
}
|
|
catch(SoftUpdateException e)
|
|
{
|
|
errcode = e.GetError();
|
|
}
|
|
catch(ForbiddenTargetException e)
|
|
{
|
|
errcode = ACCESS_DENIED;
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
e.printStackTrace();
|
|
errcode = UNEXPECTED_ERROR;
|
|
}
|
|
|
|
saveError( errcode );
|
|
return errcode;
|
|
}
|
|
|
|
/**
|
|
* another StartInstall() simplification -- version as string
|
|
*/
|
|
public int
|
|
StartInstall(String vrPackageName, String inVer )
|
|
{
|
|
return StartInstall( vrPackageName, new VersionInfo( inVer ) );
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* UI feedback
|
|
*/
|
|
protected void
|
|
UserCancelled()
|
|
{
|
|
userChoice = 0;
|
|
AbortInstall();
|
|
}
|
|
|
|
protected void
|
|
UserApproved()
|
|
{
|
|
userChoice = 1;
|
|
}
|
|
|
|
/**
|
|
* Proper completion of the install
|
|
* Copies all the files to the right place
|
|
* returns 0 on success, <0 error code on failure
|
|
*/
|
|
public int
|
|
FinalizeInstall()
|
|
{
|
|
boolean rebootNeeded = false;
|
|
int result = SUCCESS;
|
|
try
|
|
{
|
|
if (packageName == null) // probably didn't call StartInstall()
|
|
{
|
|
throw new SoftUpdateException(
|
|
Strings.error_WinProfileMustCallStart(),
|
|
INSTALL_NOT_STARTED );
|
|
}
|
|
|
|
// Wait for user approval
|
|
progress.ConfirmWithUser();
|
|
while ( userChoice == -1 )
|
|
Thread.sleep(10);
|
|
|
|
if (userChoice != 1)
|
|
{
|
|
AbortInstall();
|
|
lastError = USER_CANCELLED;
|
|
return USER_CANCELLED;
|
|
}
|
|
|
|
// Register default package folder if set
|
|
if ( packageFolder != null )
|
|
{
|
|
VersionRegistry.setDefaultDirectory( packageName,
|
|
packageFolder.toString() );
|
|
}
|
|
|
|
/* call Complete() on all the elements */
|
|
/* If an error occurs in the middle, call Abort() on the rest */
|
|
java.util.Enumeration ve = GetInstallQueue();
|
|
InstallObject ie = null;
|
|
|
|
try // Main loop
|
|
{
|
|
VersionRegistry.uninstallCreate(packageName, userPackageName);
|
|
while ( ve.hasMoreElements() )
|
|
{
|
|
ie = (InstallObject)ve.nextElement();
|
|
try {
|
|
ie.Complete();
|
|
}
|
|
catch (SoftUpdateException e) {
|
|
if (e.GetError() == REBOOT_NEEDED)
|
|
rebootNeeded = true;
|
|
else
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
if (ie != null)
|
|
ie.Abort();
|
|
|
|
while (ve.hasMoreElements())
|
|
{
|
|
try
|
|
{
|
|
ie = (InstallObject)ve.nextElement();
|
|
ie.Abort();
|
|
}
|
|
catch(Throwable t)
|
|
{
|
|
// t.printStackTrace();
|
|
}
|
|
}
|
|
throw(e); // Rethrow out of main loop
|
|
}
|
|
|
|
// add overall version for package
|
|
if ( versionInfo != null )
|
|
{
|
|
result = VersionRegistry.installComponent(
|
|
packageName, null, versionInfo );
|
|
}
|
|
}
|
|
catch (SoftUpdateException e)
|
|
{
|
|
result = e.GetError();
|
|
}
|
|
catch (ForbiddenTargetException e)
|
|
{
|
|
result = ACCESS_DENIED;
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
e.printStackTrace();
|
|
System.out.println( Strings.error_Unexpected() + " FinalizeInstall");
|
|
result = UNEXPECTED_ERROR;
|
|
}
|
|
finally
|
|
{
|
|
if ( installedFiles != null )
|
|
installedFiles.removeAllElements();
|
|
CleanUp();
|
|
}
|
|
|
|
if (result == SUCCESS && rebootNeeded)
|
|
result = REBOOT_NEEDED;
|
|
|
|
saveError( result );
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Aborts the install :), cleans up all the installed files
|
|
*/
|
|
public synchronized void AbortInstall()
|
|
{
|
|
try
|
|
{
|
|
if (installedFiles != null)
|
|
{
|
|
java.util.Enumeration ve = GetInstallQueue();
|
|
while ( ve.hasMoreElements() )
|
|
{
|
|
InstallObject ie;
|
|
ie = (InstallObject)ve.nextElement();
|
|
try // We just want to loop through all of them if possible
|
|
{
|
|
ie.Abort();
|
|
}
|
|
catch (Throwable t)
|
|
{
|
|
}
|
|
}
|
|
installedFiles.removeAllElements();
|
|
installedFiles = null;
|
|
}
|
|
CloseJARFile();
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
System.out.println( Strings.error_Unexpected() + " AbortInstall");
|
|
e.printStackTrace();
|
|
}
|
|
finally
|
|
{
|
|
try {
|
|
CleanUp();
|
|
}
|
|
catch (Throwable e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* CleanUp
|
|
* call it when done with the install
|
|
*
|
|
*/
|
|
private synchronized void CleanUp()
|
|
{
|
|
if (progress != null)
|
|
progress.Complete();
|
|
|
|
CloseJARFile();
|
|
progress = null;
|
|
zigPtr = 0;
|
|
if ( installedFiles != null )
|
|
{
|
|
// if (installedFiles.size() != 0)
|
|
// System.err.println("Installed files are not empty!");
|
|
java.util.Enumeration ve = GetInstallQueue();
|
|
while ( ve.hasMoreElements() )
|
|
{
|
|
InstallObject ie;
|
|
ie = (InstallObject)ve.nextElement();
|
|
ie.Abort();
|
|
}
|
|
installedFiles.removeAllElements();
|
|
}
|
|
installedFiles = null;
|
|
packageName = null; // used to see if StartInstall() has been called
|
|
}
|
|
|
|
/**
|
|
* ScheduleForInstall
|
|
* call this to put an InstallObject on the install queue
|
|
* Do not call installedFiles.addElement directly, because this routine also handles
|
|
* progress messages
|
|
*/
|
|
protected void ScheduleForInstall(InstallObject ob) throws SoftUpdateException
|
|
{
|
|
// flash current item
|
|
if (progress != null)
|
|
progress.SetStatus( ob );
|
|
|
|
// do any unpacking or other set-up
|
|
ob.Prepare();
|
|
|
|
|
|
// Add to installation list if we haven't thrown out
|
|
installedFiles.addElement( ob );
|
|
if (progress != null)
|
|
progress.ScheduleForInstall( ob );
|
|
}
|
|
|
|
/**
|
|
* GetQualifiedRegName
|
|
*
|
|
* This routine converts a package-relative component registry name
|
|
* into a full name that can be used in calls to the version registry.
|
|
*/
|
|
private String GetQualifiedRegName( String name )
|
|
{
|
|
String packagePrefix = (packageName.length() == 0) ? "" : packageName+"/" ;
|
|
|
|
if (name.toUpperCase().startsWith("=COMM=/"))
|
|
// bug 66403: JRI_GetStringUTFChars() returns bad string in native
|
|
// code after a substring() method call (str looks OK in java!)
|
|
// name = name.substring(7);
|
|
name = (name.substring(7)+"===").substring(0,name.length()-7);
|
|
else if (name.charAt(0) != '/') // Relative package path
|
|
name = packagePrefix + name;
|
|
|
|
return name;
|
|
}
|
|
|
|
/**
|
|
* Extract a file from JAR archive to the disk, and update the
|
|
* version registry. Actually, keep a record of elements to be installed. FinalizeInstall()
|
|
* does the real installation. Install elements are accepted if they meet one of the
|
|
* following criteria:
|
|
* 1) There is no entry for this subcomponnet in the registry
|
|
* 2) The subcomponent version info is newer than the one installed
|
|
* 3) The subcomponent version info is null
|
|
*
|
|
* @param name path of the package in the registry. Can be:
|
|
* absolute: "/Plugins/Adobe/Acrobat/Drawer.exe"
|
|
* relative: "Drawer.exe". Relative paths are relative to main package name
|
|
* null: if null jarLocation is assumed to be the relative path
|
|
* @param version version of the subcomponent. Can be null
|
|
* @param jarSource location of the file to be installed inside JAR
|
|
* @param folderSpec one of the predefined folder locations
|
|
* @see GetFolder
|
|
* @param relativePath where the file should be copied to on the local disk.
|
|
* Relative to folder
|
|
* if null, use the path to the JAR source.
|
|
* @param forceInstall if true, file is always replaced
|
|
*/
|
|
public int AddSubcomponent(String name,
|
|
VersionInfo version,
|
|
String jarSource,
|
|
FolderSpec folderSpec,
|
|
String relativePath,
|
|
boolean forceInstall)
|
|
{
|
|
InstallFile ie;
|
|
int result = SUCCESS;
|
|
try
|
|
{
|
|
if ( jarSource == null || jarSource.length() == 0 || folderSpec == null )
|
|
throw (new SoftUpdateException( "", INVALID_ARGUMENTS ));
|
|
|
|
if (packageName == null) {
|
|
// probably didn't call StartInstall()
|
|
throw new SoftUpdateException( Strings.error_BadPackageNameAS(),
|
|
BAD_PACKAGE_NAME);
|
|
}
|
|
|
|
if ((name == null) || (name.length() == 0)) {
|
|
// Default subName = location in jar file
|
|
name = GetQualifiedRegName( jarSource );
|
|
}
|
|
else
|
|
name = GetQualifiedRegName( name );
|
|
|
|
if ( (relativePath == null) || (relativePath.length() == 0))
|
|
relativePath = jarSource;
|
|
|
|
/* Check for existence of the newer version */
|
|
|
|
boolean versionNewer = false;
|
|
if ( (forceInstall == false ) &&
|
|
(version != null) &&
|
|
( VersionRegistry.validateComponent( name ) == 0 ) )
|
|
{
|
|
VersionInfo oldVersion = VersionRegistry.componentVersion(name);
|
|
if ( version.compareTo( oldVersion ) > 0 )
|
|
versionNewer = true;
|
|
}
|
|
else
|
|
versionNewer = true;
|
|
|
|
if (versionNewer)
|
|
{
|
|
ie = new InstallFile( this, name, version, jarSource,
|
|
folderSpec, relativePath, forceInstall );
|
|
ScheduleForInstall( ie );
|
|
}
|
|
}
|
|
catch (SoftUpdateException e)
|
|
{
|
|
result = e.GetError();
|
|
}
|
|
catch (ForbiddenTargetException e)
|
|
{
|
|
result = ACCESS_DENIED;
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
System.out.println(Strings.error_Unexpected() + "AddSubcomponent");
|
|
e.printStackTrace();
|
|
result = UNEXPECTED_ERROR;
|
|
}
|
|
|
|
saveError( result );
|
|
return result;
|
|
}
|
|
|
|
|
|
/**
|
|
* Various alternate flavors of AddSubcomponent()
|
|
*/
|
|
|
|
public int AddSubcomponent( String jarSource )
|
|
{
|
|
return AddSubcomponent( "", versionInfo, jarSource, packageFolder, "", force );
|
|
}
|
|
|
|
public int AddSubcomponent( String name, String jarSource )
|
|
{
|
|
return AddSubcomponent( name, versionInfo, jarSource, packageFolder, "", force );
|
|
}
|
|
|
|
public int AddSubcomponent( String regname, String jarSource, boolean forceInstall )
|
|
{
|
|
return AddSubcomponent( regname, versionInfo, jarSource, packageFolder, "", forceInstall );
|
|
}
|
|
|
|
public int AddSubcomponent( String regname, VersionInfo version, String jarSource )
|
|
{
|
|
return AddSubcomponent( regname, version, jarSource, packageFolder, "", force );
|
|
}
|
|
|
|
public int AddSubcomponent( String regname, VersionInfo version, String jarSource, boolean forceInstall )
|
|
{
|
|
return AddSubcomponent( regname, version, jarSource, packageFolder, "", forceInstall );
|
|
}
|
|
|
|
public int AddSubcomponent( String regname, String jarSource, String relativePath )
|
|
{
|
|
return AddSubcomponent( regname, versionInfo, jarSource, packageFolder, relativePath, force );
|
|
}
|
|
|
|
public int AddSubcomponent( String regname, String jarSource, String relativePath, boolean forceInstall )
|
|
{
|
|
return AddSubcomponent( regname, versionInfo, jarSource, packageFolder, relativePath, forceInstall );
|
|
}
|
|
|
|
public int AddSubcomponent( String regname, String jarSource, FolderSpec folderSpec, String relativePath )
|
|
{
|
|
return AddSubcomponent( regname, versionInfo, jarSource, folderSpec, relativePath, force );
|
|
}
|
|
|
|
public int AddSubcomponent( String regname, String jarSource, FolderSpec folderSpec, String relativePath,
|
|
boolean forceInstall )
|
|
{
|
|
return AddSubcomponent( regname, versionInfo, jarSource, folderSpec, relativePath, forceInstall );
|
|
}
|
|
|
|
public int AddSubcomponent( String regname, VersionInfo version, String jarSource, FolderSpec folderSpec,
|
|
String relativePath )
|
|
{
|
|
return AddSubcomponent( regname, version, jarSource, folderSpec, relativePath, force );
|
|
}
|
|
|
|
/**
|
|
* executes the file
|
|
* @param jarSource name of the file to execute inside JAR archive
|
|
* @param args command-line argument string (Win/Unix only)
|
|
*/
|
|
public int
|
|
Execute(String jarSource)
|
|
{
|
|
return Execute( jarSource, null );
|
|
}
|
|
|
|
public int
|
|
Execute(String jarSource, String args)
|
|
{
|
|
int errcode = SUCCESS;
|
|
|
|
try
|
|
{
|
|
InstallExecute ie = new InstallExecute( this, jarSource, args);
|
|
ScheduleForInstall( ie );
|
|
}
|
|
catch (SoftUpdateException e)
|
|
{
|
|
errcode = e.GetError();
|
|
}
|
|
catch (ForbiddenTargetException e)
|
|
{
|
|
errcode = ACCESS_DENIED;
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
e.printStackTrace();
|
|
System.out.println(Strings.error_Unexpected() + "Execute");
|
|
errcode = UNEXPECTED_ERROR;
|
|
}
|
|
|
|
saveError( errcode );
|
|
return errcode;
|
|
}
|
|
|
|
/**
|
|
* Mac-only, simulates Mac toolbox Gestalt function
|
|
* OSErr Gestalt(String selector, long * response)
|
|
* @param selector 4-character string,
|
|
* @return 2 item array. 1st item corresponds to OSErr,
|
|
* 2nd item corresponds to response
|
|
*/
|
|
public int[] Gestalt(String selector)
|
|
{
|
|
int a[] = new int[2];
|
|
a[0] = 0;
|
|
a[1] = 0;
|
|
try
|
|
{
|
|
a[1] = NativeGestalt(selector);
|
|
}
|
|
catch (SoftUpdateException s)
|
|
{
|
|
a[0] = s.GetError();
|
|
}
|
|
catch (Throwable t)
|
|
{
|
|
a[0] = -1;
|
|
System.out.println(Strings.error_Unexpected() + "Gestalt");
|
|
}
|
|
return a;
|
|
}
|
|
|
|
private native int
|
|
NativeGestalt(String selector) throws SoftUpdateException;
|
|
|
|
|
|
|
|
/**
|
|
* Patch
|
|
*
|
|
*/
|
|
|
|
public int Patch( String regName, VersionInfo version, String patchname )
|
|
{
|
|
int errcode = SUCCESS;
|
|
|
|
if ( regName == null || patchname == null )
|
|
return saveError( INVALID_ARGUMENTS );
|
|
|
|
String rname = GetQualifiedRegName( regName );
|
|
|
|
try {
|
|
InstallPatch ip = new InstallPatch(this, rname, version, patchname);
|
|
ScheduleForInstall( ip );
|
|
}
|
|
catch (SoftUpdateException e) {
|
|
errcode = e.GetError();
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
System.out.println(Strings.error_Unexpected() + "Patch");
|
|
e.printStackTrace();
|
|
errcode = UNEXPECTED_ERROR;
|
|
}
|
|
saveError( errcode );
|
|
return errcode;
|
|
}
|
|
|
|
public int Patch( String regName, String patchname )
|
|
{
|
|
return Patch( regName, versionInfo, patchname );
|
|
}
|
|
|
|
public int
|
|
Patch( String regName, VersionInfo version, String patchname,
|
|
FolderSpec folder, String filename )
|
|
{
|
|
if ( folder == null || regName == null || regName.length() == 0 || patchname == null )
|
|
return saveError( INVALID_ARGUMENTS );
|
|
|
|
int errcode = SUCCESS;
|
|
|
|
try {
|
|
String rname = GetQualifiedRegName( regName );
|
|
|
|
InstallPatch ip = new InstallPatch( this, rname, version,
|
|
patchname, folder, filename );
|
|
ScheduleForInstall( ip );
|
|
}
|
|
catch (SoftUpdateException e) {
|
|
errcode = e.GetError();
|
|
}
|
|
catch (Throwable e) {
|
|
System.out.println(Strings.error_Unexpected() + "Patch");
|
|
e.printStackTrace();
|
|
errcode = UNEXPECTED_ERROR;
|
|
}
|
|
saveError( errcode );
|
|
return errcode;
|
|
}
|
|
|
|
public int
|
|
Patch( String regName, String patchname, FolderSpec folder, String file )
|
|
{
|
|
return Patch( regName, versionInfo, patchname, folder, file );
|
|
}
|
|
|
|
private native int NativeMakeDirectory (String path);
|
|
|
|
/**
|
|
* This method deletes the specified file from the disk. It does not look
|
|
* for the file in the registry and is guaranteed to muddle any uninstall
|
|
* reference counting. Its main purpose is to delete files installed or
|
|
* created outside of SmartUpdate.
|
|
*/
|
|
public int DeleteFile(FolderSpec folder, String relativeFileName)
|
|
{
|
|
int errcode = SUCCESS;
|
|
|
|
try
|
|
{
|
|
InstallDelete id = new InstallDelete( this, folder, relativeFileName );
|
|
ScheduleForInstall( id );
|
|
}
|
|
catch (SoftUpdateException e)
|
|
{
|
|
errcode = e.GetError();
|
|
if (errcode == FILE_DOES_NOT_EXIST) {
|
|
errcode = SUCCESS;
|
|
}
|
|
}
|
|
catch (netscape.security.AppletSecurityException e)
|
|
{
|
|
errcode = ACCESS_DENIED;
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
e.printStackTrace();
|
|
errcode = UNEXPECTED_ERROR;
|
|
}
|
|
|
|
saveError( errcode );
|
|
return errcode;
|
|
}
|
|
|
|
|
|
/**
|
|
* This method finds named registry component and deletes both the file and the
|
|
* entry in the Client VR. registryName is the name of the component in the registry.
|
|
* Returns usual errors codes + code to indicate item doesn't exist in registry, registry
|
|
* item wasn't a file item, or the related file doesn't exist. If the file is in use we will
|
|
* store the name and to try to delete it on subsequent start-ups until we're successful.
|
|
*/
|
|
public int DeleteComponent(String registryName)
|
|
{
|
|
int errcode = SUCCESS;
|
|
|
|
try
|
|
{
|
|
InstallDelete id = new InstallDelete( this, registryName );
|
|
ScheduleForInstall( id );
|
|
}
|
|
catch (SoftUpdateException e)
|
|
{
|
|
errcode = e.GetError();
|
|
if (errcode == FILE_DOES_NOT_EXIST) {
|
|
errcode = SUCCESS;
|
|
}
|
|
}
|
|
catch (netscape.security.AppletSecurityException e)
|
|
{
|
|
errcode = ACCESS_DENIED;
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
e.printStackTrace();
|
|
errcode = UNEXPECTED_ERROR;
|
|
}
|
|
if (errcode == FILE_DOES_NOT_EXIST)
|
|
{
|
|
errcode = SUCCESS;
|
|
}
|
|
saveError( errcode );
|
|
return errcode;
|
|
}
|
|
|
|
|
|
public FolderSpec GetFolder( String targetFolder, String subdirectory )
|
|
{
|
|
if (targetFolder.compareTo(FOLDER_FILE_URL) == 0)
|
|
{
|
|
String newPath;
|
|
String path = NativeFileURLToNative("/"+subdirectory );
|
|
if ( path != null )
|
|
{
|
|
if (path.endsWith(System.getProperty("file.separator")))
|
|
{
|
|
return new FolderSpec("Installed", path, userPackageName);
|
|
}
|
|
else
|
|
{
|
|
newPath = path + System.getProperty("file.separator");
|
|
return new FolderSpec("Installed", newPath, userPackageName);
|
|
}
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
else
|
|
return GetFolder( GetFolder(targetFolder), subdirectory );
|
|
}
|
|
|
|
private native long NativeDiskSpaceAvailable (String path);
|
|
private native String NativeFileURLToNative (String path);
|
|
private native String[] ExtractDirEntries(String Dir);
|
|
|
|
public FolderSpec GetFolder( FolderSpec folder, String subdir )
|
|
{
|
|
FolderSpec spec = null;
|
|
String path;
|
|
String newPath;
|
|
|
|
if ( subdir == null || subdir.length() == 0 )
|
|
{
|
|
// no subdir, return what we were passed
|
|
spec = folder;
|
|
}
|
|
else if ( folder != null )
|
|
{
|
|
try {
|
|
path = folder.MakeFullPath( subdir );
|
|
} catch (Exception e ) {
|
|
path = null;
|
|
}
|
|
|
|
if (path != null)
|
|
{
|
|
if (path.endsWith(System.getProperty("file.separator")))
|
|
{
|
|
spec = new FolderSpec("Installed", path, userPackageName);
|
|
}
|
|
else
|
|
{
|
|
newPath = path + System.getProperty("file.separator");
|
|
spec = new FolderSpec("Installed", newPath, userPackageName);
|
|
}
|
|
}
|
|
}
|
|
return spec;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* This method returns true if there is enough free diskspace, false if there isn't.
|
|
* The drive containg the folder is checked for # of free bytes.
|
|
*/
|
|
public long DiskSpaceAvailable( FolderSpec folder )
|
|
{
|
|
String path = folder.toString();
|
|
|
|
if (path == null)
|
|
return 0;
|
|
|
|
return NativeDiskSpaceAvailable (path);
|
|
}
|
|
|
|
|
|
/**
|
|
* This method is used to install an entire subdirectory of the JAR.
|
|
* Any files so installed are individually entered into the registry so they
|
|
* can be uninstalled later. Like AddSubcomponent the directory is installed
|
|
* only if the version specified is greater than that already registered,
|
|
* or if the force parameter is true.The final version presented is the complete
|
|
* form, the others are for convenience and assume values for the missing
|
|
* arguments.
|
|
*/
|
|
|
|
|
|
public int AddDirectory( String name,
|
|
VersionInfo version,
|
|
String jarSource,
|
|
FolderSpec folderSpec,
|
|
String subdir,
|
|
boolean forceInstall)
|
|
|
|
{
|
|
InstallFile ie;
|
|
int result = SUCCESS;
|
|
try
|
|
{
|
|
if ( jarSource == null || jarSource.length() == 0 || folderSpec == null )
|
|
throw (new SoftUpdateException( "", INVALID_ARGUMENTS ));
|
|
|
|
if (packageName == null) {
|
|
// probably didn't call StartInstall()
|
|
throw (new SoftUpdateException( Strings.error_BadPackageNameAS(),
|
|
BAD_PACKAGE_NAME));
|
|
}
|
|
|
|
if ((name == null) || (name.length() == 0)) {
|
|
// Default subName = location in jar file
|
|
name = GetQualifiedRegName( jarSource );
|
|
}
|
|
else
|
|
name = GetQualifiedRegName( name );
|
|
|
|
if ( subdir == null ) {
|
|
subdir = "";
|
|
}
|
|
else if ( subdir.length() != 0 ) {
|
|
subdir += "/";
|
|
}
|
|
|
|
|
|
System.out.println("AddDirectory " + name
|
|
+ " from " + jarSource + " into " +
|
|
folderSpec.MakeFullPath(subdir));
|
|
|
|
|
|
String[] matchingFiles = ExtractDirEntries( jarSource );
|
|
int i;
|
|
boolean bInstall;
|
|
VersionInfo oldVer;
|
|
|
|
for(i=0; i< matchingFiles.length;i++)
|
|
{
|
|
String fullRegName = name + "/" + matchingFiles[i];
|
|
|
|
if ( (forceInstall == false) && (version != null) &&
|
|
(VersionRegistry.validateComponent(fullRegName) == 0) )
|
|
{
|
|
// Only install if newer
|
|
oldVer = VersionRegistry.componentVersion(fullRegName);
|
|
bInstall = ( version.compareTo(oldVer) > 0 );
|
|
}
|
|
else {
|
|
// file doesn't exist or "forced" install
|
|
bInstall = true;
|
|
}
|
|
|
|
if ( bInstall ) {
|
|
ie = new InstallFile( this,
|
|
fullRegName,
|
|
version,
|
|
jarSource + "/" + matchingFiles[i],
|
|
(FolderSpec) folderSpec,
|
|
subdir + matchingFiles[i],
|
|
forceInstall );
|
|
|
|
ScheduleForInstall( ie );
|
|
}
|
|
}
|
|
}
|
|
catch (SoftUpdateException e)
|
|
{
|
|
result = e.GetError();
|
|
}
|
|
catch (ForbiddenTargetException e)
|
|
{
|
|
result = ACCESS_DENIED;
|
|
}
|
|
catch (Throwable e)
|
|
{
|
|
System.out.println(Strings.error_Unexpected() + "AddDirectory");
|
|
result = UNEXPECTED_ERROR;
|
|
}
|
|
|
|
saveError( result );
|
|
return (result);
|
|
}
|
|
|
|
// Alternate forms of AddDirectory()
|
|
|
|
public int AddDirectory( String jarSource )
|
|
{
|
|
return AddDirectory( "", versionInfo, jarSource, packageFolder,
|
|
"", force );
|
|
}
|
|
|
|
public int AddDirectory( String regName, String jarSource )
|
|
{
|
|
return AddDirectory( regName, versionInfo, jarSource, packageFolder,
|
|
"", force );
|
|
}
|
|
|
|
public int AddDirectory( String regName, String jarSource, boolean forceMode )
|
|
{
|
|
return AddDirectory( regName, versionInfo, jarSource, packageFolder,
|
|
"", forceMode );
|
|
}
|
|
|
|
public int AddDirectory( String regName, VersionInfo version, String jarSource)
|
|
{
|
|
return AddDirectory( regName, version, jarSource, packageFolder,
|
|
"", force );
|
|
}
|
|
|
|
public int AddDirectory( String regName, VersionInfo version, String jarSource,
|
|
boolean forceMode )
|
|
{
|
|
return AddDirectory( regName, version, jarSource, packageFolder,
|
|
"", forceMode );
|
|
}
|
|
|
|
public int AddDirectory( String regName, String jarSource,
|
|
FolderSpec folder, String subdir )
|
|
{
|
|
return AddDirectory( regName, versionInfo, jarSource, folder, subdir, force );
|
|
}
|
|
|
|
public int AddDirectory( String regName, String jarSource,
|
|
FolderSpec folder, String subdir, boolean forceMode )
|
|
{
|
|
return AddDirectory( regName, versionInfo, jarSource, folder, subdir, forceMode );
|
|
}
|
|
|
|
public int AddDirectory( String regName, VersionInfo version, String jarSource,
|
|
FolderSpec folder, String subdir )
|
|
{
|
|
return AddDirectory( regName, version, jarSource, folder, subdir, force );
|
|
}
|
|
|
|
|
|
// Uninstall
|
|
|
|
public int Uninstall(String packageName)
|
|
{
|
|
return NativeUninstall(packageName);
|
|
}
|
|
|
|
private native int NativeUninstall (String packageName);
|
|
|
|
}
|
|
|