Installerpublic abstract class Installer extends Object An Installer manages MIDlet suites and libraries
present in a Java application environment. An MIDlet suite
distributed as a descriptor and JAR pair.
The descriptor identifies the configuration and contains security
information and the manifest of the JAR describes the contents.
The implementation of an Installer is
specific to the platform and provides access to
procedures that make an MIDlet suite visible to users.
Each installed package is uniquely identified by a storage name
constructed from the combination
of the values of the MIDlet-Name and
MIDlet-Vendor attributes.
The syntax and content of the strings used to identify
installed packages are implementation dependent.
Only packages installed or upgraded using this API appear
in the list of known packages. |
Fields Summary |
---|
public static final int | DOWNLOADING_JADStatus code to signal connection to the JAD server was successful. | public static final int | DOWNLOADED_1K_OF_JADStatus code to signal that another 1K of the JAD has been download. | public static final int | DOWNLOADING_JARStatus code to signal connection to the JAR server was successful. | public static final int | DOWNLOADED_1K_OF_JARStatus code to signal that another 1K of the JAR has been download. | public static final int | VERIFYING_SUITEStatus code to signal that download is done and the suite is being
verified. | public static final int | GENERATING_APP_IMAGEStatus code to signal that application image is being generating. | public static final int | VERIFYING_SUITE_CLASSESStatus code to signal that suite classes are being verified. | public static final int | STORING_SUITEStatus code for local writing of the verified MIDlet suite.
Stopping the install at this point has no effect, so there user
should not be given a chance to stop the install. | public static final int | CORRUPTED_SUITEStatus code for corrupted suite | protected static final String | MICROEDITION_PROFILESSystem property containing the supported microedition profiles | protected static final String | MICROEDITION_CONFIGSystem property containing the microedition configuration | protected static final String | MICROEDITION_LOCALESystem property containing the microedition locale | public static final String | JAD_MTMedia-Type for valid application descriptor files. | public static final String | JAR_MT_1Media-Type for valid Jar file. | public static final String | JAR_MT_2Media-Type for valid Jar file. | protected static final String | TMP_FILENAMEFilename to save the JAR of the suite temporarily. This is used
to avoid overwriting an existing JAR prior to verification. | protected Verifier | verifierMidlet suite signature verifier. | protected InstallStateImpl | stateHolds the install state. | protected com.sun.midp.midletsuite.InstallInfo | infoAn alias for more state.installInfo to get more compact record. | protected com.sun.midp.midletsuite.SuiteSettings | settingsAn alias for more state.suiteSettings to get more compact record. | protected String | cldcConfigHolds the CLDC configuration string. | protected final String | cldcRuntimeEnvHolds the device's Runtime Execution Environment string. | private Vector | supportedProfilesHolds the MIDP supported profiles. | protected String | unsignedSecurityDomainUse this to be the security domain for unsigned suites. | protected String | additionalPermissionsInclude this permissions into the list of permissions
given in MIDlet-Permissions jad attribute for unsigned
suites. |
Constructors Summary |
---|
Installer()Constructor of the Installer.
state = getInstallState();
verifier = new VerifierImpl(state);
/* Aliases for more compact record. */
info = state.installInfo;
settings = state.suiteSettings;
|
Methods Summary |
---|
private void | applyCurrentUserLevelPermissions(byte[] current, byte[] domainPermissions, byte[] next)Apply the previous user level permission of the currently installed
version of a suite to the next version of the suite in a secure way.
for (int i = 0; i < current.length && i < next.length; i++) {
switch (current[i]) {
case Permissions.ALLOW:
case Permissions.NEVER:
// not a user level permission
continue;
}
switch (domainPermissions[i]) {
case Permissions.ALLOW:
case Permissions.NEVER:
// not a user level permission
continue;
case Permissions.ONESHOT:
if (current[i] == Permissions.SESSION) {
// do not apply
continue;
}
// fall through; per-session permissions may be permitted.
case Permissions.SESSION:
if (current[i] == Permissions.BLANKET ||
current[i] == Permissions.BLANKET_GRANTED) {
// do not apply
continue;
}
// fall through to store the permission for the next version.
default:
next[i] = current[i];
continue;
}
}
| private void | applyExtraPermissions()If some additional (i.e. that are not listed in jad) permissions must
be allowed, add them to the value of MIDlet-Permissions attribute.
if (additionalPermissions != null) {
String newPermissions = state.jadProps.getProperty(
MIDletSuite.PERMISSIONS_PROP);
if (newPermissions != null && newPermissions.length() > 0) {
newPermissions += ",";
}
if ("all".equals(additionalPermissions)) {
int i;
byte[] domainPermissions = Permissions.forDomain(
info.domain)[Permissions.MAX_LEVELS];
newPermissions = "";
for (i = 0; i < Permissions.NUMBER_OF_PERMISSIONS - 1; i++) {
if (domainPermissions[i] != Permissions.NEVER) {
newPermissions += Permissions.getName(i) + ",";
}
}
// the same for the last permission, but without ","
if (domainPermissions[i] != Permissions.NEVER) {
newPermissions += Permissions.getName(i);
}
} else {
newPermissions += additionalPermissions;
}
state.jadProps.setProperty(MIDletSuite.PERMISSIONS_PROP,
newPermissions);
/*
* If the Midlet-Permissions attribute presents in there
* manifest, it must be the same as in jad because the suite
* is trusted.
*/
String jarPermissions = state.jarProps.getProperty(
MIDletSuite.PERMISSIONS_PROP);
if (jarPermissions != null) {
state.jarProps.setProperty(MIDletSuite.PERMISSIONS_PROP,
newPermissions);
}
}
| private void | checkConfiguration()Checks to make sure the configration need by the application
is supported.
Send a message back to the server if the check fails and
throw an exception.
String config;
config = state.getAppProperty(MIDletSuite.CONFIGURATION_PROP);
if (config == null || config.length() == 0) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAR_MSG);
throw new InvalidJadException(
InvalidJadException.MISSING_CONFIGURATION);
}
if (cldcConfig == null) {
// need to call trim to remove trailing spaces
cldcConfig =
System.getProperty(MICROEDITION_CONFIG).trim();
}
if (matchVersion(cldcConfig, config)) {
// success, done
return;
}
postInstallMsgBackToProvider(OtaNotifier.INCOMPATIBLE_MSG);
throw new InvalidJadException(InvalidJadException.DEVICE_INCOMPATIBLE);
| protected void | checkForDifferentDomains(java.lang.String url)If the JAD belongs to an installed suite, check the URL against the
installed one. Set the state.exception if the user needs to be warned.
String previousUrl = state.previousInstallInfo.getDownloadUrl();
// perform a domain check not a straight compare
if (info.authPath == null && previousUrl != null) {
HttpUrl old = new HttpUrl(previousUrl);
HttpUrl current = new HttpUrl(url);
if ((current.domain != null && old.domain == null) ||
(current.domain == null && old.domain != null) ||
(current.domain != null && old.domain != null &&
!current.domain.regionMatches(true, 0, old.domain, 0,
old.domain.length()))) {
/*
* The jad is at new location, could be bad,
* let the user decide
*/
state.exception = new InvalidJadException(
InvalidJadException.JAD_MOVED, previousUrl);
return;
}
}
| protected void | checkForJadManifestMismatches()Checks to see that if any properties that are both in the JAD and
JAR manifest are not equal and throw a exception and notify the
server when a mismatch is found. Only used for trusted suites.
for (int i = 0; i < state.jarProps.size(); i++) {
String key = state.jarProps.getKeyAt(i);
String value = state.jarProps.getValueAt(i);
String dup = state.jadProps.getProperty(key);
if (dup == null) {
continue;
}
if (!dup.equals(value)) {
postInstallMsgBackToProvider(
OtaNotifier.ATTRIBUTE_MISMATCH_MSG);
throw new InvalidJadException(
InvalidJadException.ATTRIBUTE_MISMATCH, key);
}
}
| private void | checkMidpPermission()Checks if the calling suite has Permissions.MIDP permission.
If not, the SecurityException is thrown.
MIDletSuite midletSuite = MIDletStateHandler.
getMidletStateHandler().getMIDletSuite();
// if a MIDlet suite is not started, assume the JAM is calling.
if (midletSuite != null) {
midletSuite.checkIfPermissionAllowed(Permissions.MIDP);
}
| protected void | checkPreviousVersion()See if there is an installed version of the suite being installed and
if so, make an necessary checks. Will set state fields, including
the exception field for warning the user.
int id;
MIDletSuiteImpl midletSuite;
String installedVersion;
int cmpResult;
// Check if app already exists
id = MIDletSuiteStorage.getSuiteID(info.suiteVendor, info.suiteName);
if (id == MIDletSuite.UNUSED_SUITE_ID) {
// there is no previous version
return;
}
try {
midletSuite =
state.midletSuiteStorage.getMIDletSuite(id, true);
if (midletSuite == null) {
// there is no previous version
return;
}
checkVersionFormat(info.suiteVersion);
state.isPreviousVersion = true;
// This is now an update, use the old ID
info.id = id;
state.previousSuite = midletSuite;
state.previousInstallInfo = midletSuite.getInstallInfo();
if (state.force) {
// do not ask questions, force an overwrite
return;
}
// If it does, check version information
installedVersion = midletSuite.getProperty(
MIDletSuite.VERSION_PROP);
cmpResult = vercmp(info.suiteVersion,
installedVersion);
if (cmpResult < 0) {
// older version, warn user
state.exception = new InvalidJadException(
InvalidJadException.OLD_VERSION,
installedVersion);
return;
}
if (cmpResult == 0) {
// already installed, warn user
state.exception = new InvalidJadException(
InvalidJadException.ALREADY_INSTALLED,
installedVersion);
return;
}
// new version, warn user
state.exception = new InvalidJadException(
InvalidJadException.NEW_VERSION,
installedVersion);
return;
} catch (MIDletSuiteCorruptedException mce) {
if (state.listener != null) {
state.listener.updateStatus(CORRUPTED_SUITE, state);
}
} catch (NumberFormatException nfe) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAD_MSG);
throw new
InvalidJadException(InvalidJadException.INVALID_VERSION);
}
| private void | checkRuntimeEnv()Checks to make sure the runtime environment required by
the application is supported.
Send a message back to the server if the check fails and
throw an exception.
String execEnv;
execEnv = state.getAppProperty(MIDletSuite.RUNTIME_EXEC_ENV_PROP);
if (execEnv == null || execEnv.length() == 0) {
execEnv = MIDletSuite.RUNTIME_EXEC_ENV_DEFAULT;
}
// need to call trim to remove trailing spaces
execEnv = execEnv.trim();
if (execEnv.equals(cldcRuntimeEnv)) {
// success, done
return;
}
postInstallMsgBackToProvider(OtaNotifier.INCOMPATIBLE_MSG);
throw new InvalidJadException(InvalidJadException.DEVICE_INCOMPATIBLE);
| private static void | checkVersionFormat(java.lang.String ver)Checks the format of a version string.
Versions must be in the form xxx.yyy.zzz, where:
xxx is the major version
yyy is the minor version
zzz is the micro version
It is acceptable to omit the micro and possibly the minor versions.
If these are not included in the version string, the period immediately
preceding the number must also be removed. So, the versions
xxx.yyy or xxx are also valid.
Version numbers do not have to be three digits wide. However, you may
pad versions with leading zeros if desired.
int length;
int start = 0;
int end;
length = ver.length();
for (int i = 0; ; i++) {
// check for more than 3 parts or a trailing '.'
if (i == 3 || start == length) {
throw new NumberFormatException();
}
end = ver.indexOf('.", start);
if (end == -1) {
end = length;
}
// throws NFE if the substring is not all digits
Integer.parseInt(ver.substring(start, end));
if (end == length) {
// we are done
return;
}
// next time around start after the index of '.'
start = end + 1;
}
| protected abstract byte[] | downloadJAD()Downloads an application descriptor file from the given URL.
| protected abstract int | downloadJAR(java.lang.String filename)Downloads an application archive file from the given URL into the
given file. Automatically handle re-tries.
| protected byte[] | getInitialPermissions(java.lang.String domain)Builds the initial API permission for suite currently being installed.
byte[][] domainPermissions = Permissions.forDomain(domain);
byte[] permissions = Permissions.getEmptySet();
// only the current level of each permission has to be adjusted
getRequestedPermissions(MIDletSuite.PERMISSIONS_PROP,
domainPermissions[Permissions.CUR_LEVELS],
permissions, true);
getRequestedPermissions(MIDletSuite.PERMISSIONS_OPT_PROP,
domainPermissions[Permissions.CUR_LEVELS],
permissions, false);
return permissions;
| protected com.sun.midp.installer.InstallStateImpl | getInstallState()Creates an instance of InstallState of the appropriate type
depending on the installer type. Should be overloaded in the
inherited classes.
if (state == null) {
state = new InstallStateImpl();
// IMPL_NOTE: "info" and "settings" aliases must be updated
// after calling getInstallState().
}
return state;
| private void | getRequestedPermissions(java.lang.String propName, byte[] domainPermissions, byte[] permissions, boolean required)Gets the permissions for a domain that are requested the manifest.
String jadPermissionLine;
String reqPermissionLine;
Vector reqPermissions;
String permission;
boolean found;
int i;
reqPermissionLine = state.getAppProperty(propName);
if (reqPermissionLine == null || reqPermissionLine.length() == 0) {
// Zero properties are allowed.
return;
}
reqPermissions = Util.getCommaSeparatedValues(reqPermissionLine);
if (reqPermissions.size() == 0) {
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAD_MSG);
throw new InvalidJadException(InvalidJadException.INVALID_VALUE);
}
for (int j = 0; j < reqPermissions.size(); j++) {
permission = (String)reqPermissions.elementAt(j);
if (permission.length() == 0) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAD_MSG);
throw new
InvalidJadException(InvalidJadException.INVALID_VALUE);
}
found = false;
for (i = 0; i < Permissions.NUMBER_OF_PERMISSIONS; i++) {
if (Permissions.getName(i).equals(permission)) {
if (domainPermissions[i] != Permissions.NEVER) {
found = true;
}
break;
}
}
if (!found) {
if (required) {
postInstallMsgBackToProvider(
OtaNotifier.AUTHORIZATION_FAILURE_MSG);
throw new InvalidJadException(
InvalidJadException.AUTHORIZATION_FAILURE, permission);
}
continue;
}
permissions[i] = domainPermissions[i];
}
| public static java.lang.String | getUrlPath(java.lang.String url)Retrieves a path component of the given URL.
if (url == null) {
return null;
}
/* this will parse any kind of URL, not only Http */
HttpUrl parsedUrl = new HttpUrl(url);
String path = parsedUrl.path;
/*
IMPL_NOTE: In current implementation of HttpUrl
the absolute path always begins with '/' which
would make getUrlPath() produce the win32
paths in the form "/C:/path/to/file" that is
rejected by the filesystem.
The initial '/' in 'path' is currently the only
flag which allows to distinguish between absolute
and relative url.
Probably there should be a special flag in HttpUrl
to distinguish between absolute and relative urls.
Moreover it seems necessary to have platform-dependent
conversion procedure from url path to filesystem path.
*/
if (path != null) {
if (path.charAt(0) == '/") {
path = path.substring (1, path.length ());
}
}
return path;
| public static java.lang.String | getUrlScheme(java.lang.String url, java.lang.String defaultScheme)Retrieves a scheme component of the given URL.
if (url == null) {
return null;
}
/* this will parse any kind of URL, not only Http */
HttpUrl parsedUrl = new HttpUrl(url);
if (parsedUrl.scheme == null) {
return defaultScheme;
}
return parsedUrl.scheme;
| public int | installJad(java.lang.String location, int storageId, boolean force, boolean removeRMS, InstallListener installListener)Installs a software package from the given URL. The URL is assumed
refer to an application descriptor.
If the component to be installed is the same as an existing
component (by comparing the MIDlet-Name ,
MIDlet-Vendor attributes)
then this install is an upgrade if the version number is greater
than the current version. If so, the new version replaces in its
entirety the current version.
It is implementation dependent when the upgraded component is
made available for use.
The implementation of install must be robust in the presence
of failures such as running out of memory. If this method
throws an exception then the package must not be installed
and any previous version of the component must be left intact
and operational.
To receive status updates and installer warnings, provide an install
listener. If no listener is provided all warnings will be thrown
as exceptions.
info.jadUrl = location;
state.force = force;
state.removeRMS = removeRMS;
state.nextStep = 1;
state.listener = installListener;
state.chmanager = CHManager.getManager(null);
state.storageId = storageId;
return performInstall();
| public int | installJar(java.lang.String location, java.lang.String name, int storageId, boolean force, boolean removeRMS, InstallListener installListener)Installs a software package from the given URL. The URL is assumed
refer to a JAR.
If the component to be installed is the same as an existing
component (by comparing the MIDlet-Name ,
MIDlet-Vendor attributes)
then this install is an upgrade if the version number is greater
than the current version. If so, the new version replaces in its
entirety the current version.
It is implementation dependent when the upgraded component is
made available for use.
The implementation of install must be robust in the presence
of failures such as running out of memory. If this method
throws an exception then the package must not be installed
and any previous version of the component must be left intact
and operational.
To receive status updates and installer warnings, provide an install
listener. If no listener is provided all warnings will be thrown
as exceptions.
if (location == null || location.length() == 0) {
throw
new IllegalArgumentException("Must specify URL of .jar file");
}
info.jadUrl = null;
info.jarUrl = location;
info.suiteName = name;
state.force = force;
state.removeRMS = removeRMS;
state.file = new File();
state.nextStep = 5;
state.listener = installListener;
state.chmanager = CHManager.getManager(null);
state.storageId = storageId;
return performInstall();
| private void | installStep1()Downloads the JAD, save it in the install state.
Parse the JAD, make sure it has
the required properties, and save them in the install state.
if (info.jadUrl == null || info.jadUrl.length() == 0) {
throw
new IllegalArgumentException("Must specify URL of .jad file");
}
try {
state.jad = downloadJAD();
} catch (OutOfMemoryError e) {
try {
postInstallMsgBackToProvider(
OtaNotifier.INSUFFICIENT_MEM_MSG);
} catch (Throwable t) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"Throwable during posting install message");
}
}
throw new
InvalidJadException(InvalidJadException.TOO_MANY_PROPS);
}
if (state.exception != null) {
return;
}
state.jadProps = new JadProperties();
try {
state.jadProps.load(new ByteArrayInputStream(state.jad),
state.jadEncoding);
} catch (OutOfMemoryError e) {
state.jad = null;
try {
postInstallMsgBackToProvider(
OtaNotifier.INSUFFICIENT_MEM_MSG);
} catch (Throwable t) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"Throwable during posting install message");
}
}
throw new
InvalidJadException(InvalidJadException.TOO_MANY_PROPS);
} catch (InvalidJadException ije) {
state.jad = null;
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAD_MSG);
throw ije;
} catch(java.io.UnsupportedEncodingException uee) {
state.jad = null;
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAD_MSG);
throw new InvalidJadException(
InvalidJadException.UNSUPPORTED_CHAR_ENCODING,
state.jadEncoding);
}
info.suiteName = state.jadProps.getProperty(
MIDletSuite.SUITE_NAME_PROP);
if (info.suiteName == null || info.suiteName.length() == 0) {
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAD_MSG);
throw new
InvalidJadException(InvalidJadException.MISSING_SUITE_NAME);
}
info.suiteVendor = state.jadProps.getProperty(MIDletSuite.VENDOR_PROP);
if (info.suiteVendor == null || info.suiteVendor.length() == 0) {
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAD_MSG);
throw new
InvalidJadException(InvalidJadException.MISSING_VENDOR);
}
info.suiteVersion = state.jadProps.getProperty(
MIDletSuite.VERSION_PROP);
if (info.suiteVersion == null || info.suiteVersion.length() == 0) {
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAD_MSG);
throw new
InvalidJadException(InvalidJadException.MISSING_VERSION);
}
try {
checkVersionFormat(info.suiteVersion);
} catch (NumberFormatException nfe) {
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAD_MSG);
throw new InvalidJadException(
InvalidJadException.INVALID_VERSION);
}
info.id = state.midletSuiteStorage.createSuiteID();
checkPreviousVersion();
state.nextStep++;
| private void | installStep2()If the JAD belongs to an installed suite, check the URL against the
installed one.
state.nextStep++;
if (state.isPreviousVersion) {
checkForDifferentDomains(info.jadUrl);
}
| private void | installStep3()Makes sure the suite can fit in storage.
String sizeString;
int dataSize;
int suiteSize;
sizeString = state.jadProps.getProperty(MIDletSuite.JAR_SIZE_PROP);
if (sizeString == null) {
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAD_MSG);
throw new
InvalidJadException(InvalidJadException.MISSING_JAR_SIZE);
}
try {
info.expectedJarSize = Integer.parseInt(sizeString);
} catch (NumberFormatException e) {
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAD_MSG);
throw new
InvalidJadException(InvalidJadException.INVALID_VALUE);
}
sizeString = state.jadProps.getProperty(MIDletSuite.DATA_SIZE_PROP);
if (sizeString == null) {
dataSize = 0;
} else {
try {
dataSize = Integer.parseInt(sizeString);
} catch (NumberFormatException e) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAD_MSG);
throw new
InvalidJadException(InvalidJadException.INVALID_VALUE);
}
}
/*
* A suite is a jad + jar + manifest + url + data size.
* lets say the manifest is the same size as the jad
* since we do know at this point. the size is in bytes,
* UTF-8 chars can be upto 3 bytes
*/
suiteSize = info.expectedJarSize + (state.jad.length * 2) +
(info.jadUrl.length() * 3) + dataSize;
state.jad = null;
state.file = new File();
if (suiteSize > state.file.getBytesAvailableForFiles(state.storageId)) {
postInstallMsgBackToProvider(
OtaNotifier.INSUFFICIENT_MEM_MSG);
// the size reported to the user should be in K and rounded up
throw new
InvalidJadException(InvalidJadException.INSUFFICIENT_STORAGE,
Integer.toString((suiteSize + 1023)/ 1024));
}
info.jarUrl = state.jadProps.getProperty(MIDletSuite.JAR_URL_PROP);
if (info.jarUrl == null || info.jarUrl.length() == 0) {
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAD_MSG);
throw new
InvalidJadException(InvalidJadException.MISSING_JAR_URL);
}
state.nextStep++;
| private void | installStep4()Confirm installation with the user.
synchronized (state) {
/* One more check to see if user has already canceled */
if (state.stopInstallation) {
postInstallMsgBackToProvider(
OtaNotifier.USER_CANCELLED_MSG);
throw new IOException("stopped");
}
/*
* Not canceled, so ignore cancel requests for now because below we
* are going to ask anyway if user wants to install suite
*/
state.ignoreCancel = true;
}
if (state.listener != null &&
!state.listener.confirmJarDownload(state)) {
state.stopInstallation = true;
postInstallMsgBackToProvider(
OtaNotifier.USER_CANCELLED_MSG);
throw new IOException("stopped");
}
synchronized (state) {
/* Allow cancel requests again */
state.ignoreCancel = false;
}
state.nextStep++;
| private void | installStep5()Downloads the JAR, make sure it is the correct size, make sure
the required attributes match the JAD's. Then store the
application.
int bytesDownloaded;
MIDletInfo midletInfo;
String midlet;
// Send out delete notifications that have been queued, first
OtaNotifier.postQueuedDeleteMsgsBackToProvider(state.proxyUsername,
state.proxyPassword);
// Save jar file to temp name; we need to do this to read the
// manifest entry, but, don't want to overwrite an existing
// application in case there are problems with the manifest
state.storageRoot = File.getStorageRoot(state.storageId);
info.jarFilename = state.storageRoot + TMP_FILENAME;
bytesDownloaded = downloadJAR(info.jarFilename);
if (state.exception != null) {
return;
}
try {
state.storage = new RandomAccessStream();
state.installInfo.authPath =
verifier.verifyJar(state.storage, info.jarFilename);
if (state.listener != null) {
state.listener.updateStatus(VERIFYING_SUITE, state);
}
// Create JAR Properties (From .jar file's MANIFEST)
try {
state.manifest = JarReader.readJarEntry(
info.jarFilename, MIDletSuite.JAR_MANIFEST);
if (state.manifest == null) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAR_MSG);
throw new
InvalidJadException(InvalidJadException.CORRUPT_JAR,
MIDletSuite.JAR_MANIFEST);
}
} catch (OutOfMemoryError e) {
try {
postInstallMsgBackToProvider(
OtaNotifier.INSUFFICIENT_MEM_MSG);
} catch (Throwable t) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"Throwable during posting the install message");
}
}
throw new
InvalidJadException(InvalidJadException.TOO_MANY_PROPS);
} catch (IOException ioe) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAR_MSG);
throw new
InvalidJadException(InvalidJadException.CORRUPT_JAR,
MIDletSuite.JAR_MANIFEST);
}
state.jarProps = new ManifestProperties();
try {
state.jarProps.load(new ByteArrayInputStream(state.manifest));
state.manifest = null;
} catch (OutOfMemoryError e) {
state.manifest = null;
try {
postInstallMsgBackToProvider(
OtaNotifier.INSUFFICIENT_MEM_MSG);
} catch (Throwable t) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"Throwable while posting install message ");
}
}
throw new
InvalidJadException(InvalidJadException.TOO_MANY_PROPS);
} catch (InvalidJadException ije) {
state.manifest = null;
try {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAR_MSG);
} catch (Throwable t) {
// ignore
}
throw ije;
}
for (int i = 1; ; i++) {
midlet = state.getAppProperty("MIDlet-" + i);
if (midlet == null) {
break;
}
/*
* Verify the MIDlet class is present in the JAR
* An exception thrown if not.
* Do the proper install notify on an exception
*/
try {
midletInfo = new MIDletInfo(midlet);
verifyMIDlet(midletInfo.classname);
} catch (InvalidJadException ije) {
if (ije.getReason() == InvalidJadException.INVALID_VALUE) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAD_MSG);
} else {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAR_MSG);
}
throw ije;
}
}
// move on to the next step after a warning
state.nextStep++;
// Check Manifest entries against .jad file
if (info.jadUrl != null) {
if (bytesDownloaded != info.expectedJarSize) {
postInstallMsgBackToProvider(
OtaNotifier.JAR_SIZE_MISMATCH_MSG);
throw new InvalidJadException(
InvalidJadException.JAR_SIZE_MISMATCH);
}
if (!info.suiteName.equals(state.jarProps.getProperty(
MIDletSuite.SUITE_NAME_PROP))) {
postInstallMsgBackToProvider(
OtaNotifier.ATTRIBUTE_MISMATCH_MSG);
throw new InvalidJadException(
InvalidJadException.SUITE_NAME_MISMATCH);
}
if (!info.suiteVersion.equals(
state.jarProps.getProperty(MIDletSuite.VERSION_PROP))) {
postInstallMsgBackToProvider(
OtaNotifier.ATTRIBUTE_MISMATCH_MSG);
throw new InvalidJadException(
InvalidJadException.VERSION_MISMATCH);
}
if (!info.suiteVendor.equals(
state.jarProps.getProperty(MIDletSuite.VENDOR_PROP))) {
postInstallMsgBackToProvider(
OtaNotifier.ATTRIBUTE_MISMATCH_MSG);
throw new InvalidJadException(
InvalidJadException.VENDOR_MISMATCH);
}
} else {
info.expectedJarSize = bytesDownloaded;
info.suiteName = state.jarProps.getProperty(
MIDletSuite.SUITE_NAME_PROP);
if (info.suiteName == null || info.suiteName.length() == 0) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAR_MSG);
throw new InvalidJadException(
InvalidJadException.MISSING_SUITE_NAME);
}
info.suiteVendor = state.jarProps.getProperty(
MIDletSuite.VENDOR_PROP);
if (info.suiteVendor == null ||
info.suiteVendor.length() == 0) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAR_MSG);
throw new InvalidJadException(
InvalidJadException.MISSING_VENDOR);
}
info.suiteVersion = state.jarProps.getProperty(
MIDletSuite.VERSION_PROP);
if (info.suiteVersion == null ||
info.suiteVersion.length() == 0) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAR_MSG);
throw new InvalidJadException(
InvalidJadException.MISSING_VERSION);
}
try {
checkVersionFormat(info.suiteVersion);
} catch (NumberFormatException nfe) {
postInstallMsgBackToProvider(
OtaNotifier.INVALID_JAR_MSG);
throw new InvalidJadException(
InvalidJadException.INVALID_VERSION);
}
// if already installed, check the domain of the JAR URL
info.id = state.midletSuiteStorage.createSuiteID();
checkPreviousVersion();
}
} catch (Exception e) {
state.file.delete(info.jarFilename);
if (e instanceof IOException) {
throw (IOException)e;
}
throw (RuntimeException)e;
}
| private void | installStep6()If the JAR belongs to an installed suite if there was
no JAD, check the URL against the installed one.
state.nextStep++;
if (info.jadUrl == null && state.isPreviousVersion) {
checkForDifferentDomains(info.jarUrl);
}
| private void | installStep7()Checks the permissions and store the suite.
try {
if (info.authPath != null) {
// suite was signed
info.domain = verifier.getSecurityDomainName(info.authPath[0]);
if (state.listener != null &&
!state.listener.confirmAuthPath(state)) {
state.stopInstallation = true;
postInstallMsgBackToProvider(
OtaNotifier.USER_CANCELLED_MSG);
throw new IOException("stopped");
}
} else {
info.domain = unsignedSecurityDomain;
}
info.trusted = Permissions.isTrusted(info.domain);
// Do not overwrite trusted suites with untrusted ones
if (!info.trusted && state.isPreviousVersion &&
state.previousSuite.isTrusted()) {
postInstallMsgBackToProvider(
OtaNotifier.AUTHORIZATION_FAILURE_MSG);
/*
* state.previousInstallInfo.authPath can be null in the case
* if the previously installed suite was not signed but its
* domain was set to some trusted one by AutoTester using
* setUnsignedSecurityDomain().
*/
throw new InvalidJadException(
InvalidJadException.TRUSTED_OVERWRITE_FAILURE,
state.previousInstallInfo.authPath != null ?
state.previousInstallInfo.authPath[0] : "");
}
/*
* The unidentified suites do not get checked for requested
* permissions.
*/
if (Permissions.UNIDENTIFIED_DOMAIN_BINDING.equals(info.domain)) {
settings.setPermissions((Permissions.forDomain(
info.domain)) [Permissions.CUR_LEVELS]);
/*
* To keep public key management simple, there is only one
* trusted keystore. So it is possible that the CA for
* the suite is untrusted. This may be done on purpose for
* testing. This is OK, but do not confuse the user by saying
* the untrusted suite is authorized, so set the CA name to
* null.
*/
info.authPath = null;
} else {
/*
* For identified suites, make sure an properties duplicated in
* both the manifest and JAD are the same.
*/
if (info.jadUrl != null) {
checkForJadManifestMismatches();
}
/*
* This is needed by the AutoTester: sometimes it is required
* to allow some permissions even if they are not listed in jad.
*/
applyExtraPermissions();
settings.setPermissions(getInitialPermissions(info.domain));
}
if (state.isPreviousVersion) {
applyCurrentUserLevelPermissions(
state.previousSuite.getPermissions(),
(Permissions.forDomain(info.domain))
[Permissions.MAX_LEVELS],
settings.getPermissions());
if (state.removeRMS) {
// override suite comparisons, just remove RMS
RecordStoreFactory.removeRecordStoresForSuite(null,
info.id);
} else {
processPreviousRMS();
}
}
state.securityHandler = new SecurityHandler(
settings.getPermissions(), info.domain);
checkRuntimeEnv();
checkConfiguration();
matchProfile();
try {
state.chmanager.preInstall(this,
(InstallState)state,
(MIDletSuite)state,
(info.authPath == null ?
null : info.authPath[0]));
} catch (InvalidJadException jex) {
// Post the correct install notify msg back to the server
String msg = OtaNotifier.INVALID_CONTENT_HANDLER;
if (jex.getReason() ==
InvalidJadException.CONTENT_HANDLER_CONFLICT) {
msg = OtaNotifier.CONTENT_HANDLER_CONFLICT;
}
postInstallMsgBackToProvider(msg);
throw jex;
} catch (SecurityException se) {
postInstallMsgBackToProvider(
OtaNotifier.AUTHORIZATION_FAILURE_MSG);
// since our state object put the permission in message
throw new InvalidJadException(
InvalidJadException.AUTHORIZATION_FAILURE,
se.getMessage());
}
// make sure at least 1 second has passed
try {
long waitTime = 1000 -
(System.currentTimeMillis() - state.startTime);
if (waitTime > 0 && waitTime <= 1000) {
Thread.sleep(waitTime);
}
} catch (InterruptedException ie) {
// ignore
}
synchronized (state) {
// this is the point of no return, one last check
if (state.stopInstallation) {
postInstallMsgBackToProvider(
OtaNotifier.USER_CANCELLED_MSG);
throw new IOException("stopped");
}
state.ignoreCancel = true;
}
if (state.listener != null) {
state.listener.updateStatus(STORING_SUITE, state);
}
registerPushConnections();
/** Do the Content Handler registration updates now */
state.chmanager.install();
/*
* Store suite will remove the suite including push connections,
* if there an error, but may not remove the temp jar file.
*/
MIDletInfo midletInfo = state.getMidletInfo();
String midletClassNameToRun = null, iconName;
MIDletSuiteInfo msi;
iconName = state.getAppProperty("MIDlet-Icon");
if (iconName != null) {
iconName.trim();
}
if (midletInfo != null) {
midletClassNameToRun = midletInfo.classname;
if (iconName == null) {
// If an icon for the suite is not specified,
// use the first midlet's icon.
iconName = midletInfo.icon;
}
}
msi = new MIDletSuiteInfo(info.id);
msi.displayName = state.getDisplayName();
msi.midletToRun = midletClassNameToRun;
msi.numberOfMidlets = state.getNumberOfMIDlets();
/* default is to enable a newly installed suite */
msi.enabled = true;
msi.trusted = info.trusted;
msi.preinstalled = false;
msi.iconName = iconName;
msi.storageId = state.storageId;
state.midletSuiteStorage.storeSuite(info, settings, msi,
state.jadProps, state.jarProps);
} catch (Throwable e) {
state.file.delete(info.jarFilename);
if (e instanceof IOException) {
throw (IOException)e;
}
if (e instanceof OutOfMemoryError) {
try {
postInstallMsgBackToProvider(
OtaNotifier.INSUFFICIENT_MEM_MSG);
} catch (Throwable t) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"Throwable during posting install message");
}
}
throw new
InvalidJadException(InvalidJadException.TOO_MANY_PROPS);
}
throw (RuntimeException)e;
}
state.nextStep++;
try {
postInstallMsgBackToProvider(OtaNotifier.SUCCESS_MSG);
} catch (Throwable t) {
/*
* The suite is successfully installed, but the post of the
* status message failed. Do not let this failure prevent
* the suite from being used.
*/
}
| private void | installStep8()Installation time optimizations are to be done in this step.
MONET optimization, VERIFY ONCE optimization, etc.
This step is done after obligatory installation part,
so the suite is downloaded, checked and stored by this moment.
// In case of installation from JAR the suite id as well as other
// properties are read from .jar file's MANIFEST rather then from
// JAD file. Only after that application image can be generated.
if (Constants.MONET_ENABLED) {
if (state.listener != null) {
state.listener.updateStatus(GENERATING_APP_IMAGE, state);
}
MIDletAppImageGenerator.createAppImage(
info.id, state.midletSuiteStorage);
}
// Verification caching should be done if MONET disabled only
else if (Constants.VERIFY_ONCE) {
if (state.listener != null) {
state.listener.updateStatus(VERIFYING_SUITE_CLASSES, state);
}
// Preverify all suite classes
// in the case of success store hash value of the suite
try {
info.verifyHash =
MIDletSuiteVerifier.verifySuiteClasses(info.id,
state.midletSuiteStorage);
if (info.verifyHash != null) {
state.midletSuiteStorage.storeSuiteVerifyHash(
info.id, info.verifyHash);
}
} catch (Throwable t) {
// Notify installation listener of verifcation error
state.exception = new InvalidJadException(
InvalidJadException.JAR_CLASSES_VERIFICATION_FAILED);
if (state.listener != null) {
state.listener.updateStatus(
VERIFYING_SUITE_CLASSES, state);
}
// Clean exception since this step is optional and its
// problems shouldn't cause whole installation failure
state.exception = null;
}
}
state.nextStep++;
| public boolean | isJadSigned()Checks to see if the JAD has a signature, but does not verify the
signature. This is a place holder the the Secure Installer and
just returns false.
return verifier.isJadSigned();
| protected abstract boolean | isSameUrl(java.lang.String url1, java.lang.String url2)Compares two URLs for equality in sense that they have the same
scheme, host and path.
| private void | matchProfile()Tries to match one of the supported profiles with a profile
listed in string of profiles separated by a space.
Send a message back to the server if a match is not found and
throw an exception.
String profiles = state.getAppProperty(MIDletSuite.PROFILE_PROP);
if (profiles == null || profiles.length() == 0) {
postInstallMsgBackToProvider(OtaNotifier.INVALID_JAR_MSG);
throw new
InvalidJadException(InvalidJadException.MISSING_PROFILE);
}
// build the list of supported profiles if needed
if (supportedProfiles == null) {
int start;
int nextSpace = -1;
String meProfiles =
System.getProperty(MICROEDITION_PROFILES);
if (meProfiles == null || meProfiles.length() == 0) {
throw new RuntimeException(
"system property microedition.profiles not set");
}
supportedProfiles = new Vector();
// need to call trim to remove trailing spaces
meProfiles = meProfiles.trim();
for (; ; ) {
start = nextSpace + 1;
nextSpace = meProfiles.indexOf(' ", start);
// consecutive spaces, keep searching
if (nextSpace == start) {
continue;
}
if ((nextSpace < 0)) {
supportedProfiles.addElement(
meProfiles.substring(start, meProfiles.length()));
break;
}
supportedProfiles.addElement(
meProfiles.substring(start, nextSpace));
}
}
/*
* for each profiles listed in MicroEdition-Profile, we need to
* find a matching profile in microedition.profiles.
*/
int current = 0;
int nextSeparatorIndex = 0;
String requestedProfile;
boolean supported = false;
// convert tab to space so that the parsing later is simplified
StringBuffer tmp = new StringBuffer(profiles);
boolean modified = false;
while ((nextSeparatorIndex = profiles.indexOf('\t", current)) != -1) {
tmp.setCharAt(nextSeparatorIndex, ' ");
current++;
modified = true;
}
if (modified) {
profiles = tmp.toString();
}
// reset the indices
current = nextSeparatorIndex = 0;
do {
// get the next requested profiles
nextSeparatorIndex = profiles.indexOf(' ", current);
if (nextSeparatorIndex == current) {
// consecutive spaces, keep searching
current++;
continue;
}
if (nextSeparatorIndex == -1) {
// last (or the only one) value in the list
requestedProfile =
profiles.substring(current, profiles.length());
} else {
requestedProfile =
profiles.substring(current, nextSeparatorIndex);
current = nextSeparatorIndex + 1;
}
/*
* try to match each requested profiles against the supported
* ones.
*/
supported = false;
for (int i = 0; i < supportedProfiles.size(); i++) {
String supportedProfile =
(String)supportedProfiles.elementAt(i);
if (matchVersion(supportedProfile, requestedProfile)) {
supported = true;
break;
}
}
// short circuit the test if there is one mismatch
if (!supported) {
break;
}
} while (nextSeparatorIndex != -1);
// matched all requested profiles against supported ones
if (supported) {
return;
}
postInstallMsgBackToProvider(OtaNotifier.INCOMPATIBLE_MSG);
throw new InvalidJadException(InvalidJadException.DEVICE_INCOMPATIBLE);
| private static boolean | matchVersion(java.lang.String name1, java.lang.String name2)Match the name of the configuration or profile, and return
true if the first name has a greater or equal version than the
second. The names of the format "XXX-Y.Y" (e.g. CLDC-1.0, MIDP-2.0)
as used in the system properties (microedition.configuration &
microedition.profiles).
This is used for checking both configuration and profiles.
int dash1 = name1.indexOf('-");
if (dash1 < 0) {
return false;
}
int dash2 = name2.indexOf('-");
if (dash2 < 0) {
return false;
}
String base1 = name1.substring(0, dash1);
String base2 = name2.substring(0, dash2);
if (!base1.equals(base2)) {
return false;
}
String ver1 = name1.substring(dash1 + 1, name1.length());
String ver2 = name2.substring(dash2 + 1, name2.length());
return (vercmp(ver1, ver2) >= 0);
| protected int | performInstall()Performs an install.
state.midletSuiteStorage = MIDletSuiteStorage.getMIDletSuiteStorage();
/* Disable push interruptions during install. */
PushRegistryInternal.enablePushLaunch(false);
try {
state.startTime = System.currentTimeMillis();
while (state.nextStep < 9) {
/*
* clear the previous warning, so we can tell if another has
* happened
*/
state.exception = null;
if (state.stopInstallation) {
postInstallMsgBackToProvider(
OtaNotifier.USER_CANCELLED_MSG);
throw new IOException("stopped");
}
switch (state.nextStep) {
case 1:
installStep1();
break;
case 2:
installStep2();
break;
case 3:
installStep3();
break;
case 4:
installStep4();
break;
case 5:
installStep5();
break;
case 6:
installStep6();
break;
case 7:
installStep7();
break;
case 8:
installStep8();
break;
default:
// for safety/completeness.
Logging.report(Logging.CRITICAL, LogChannels.LC_AMS,
"Installer: Unknown step: " + state.nextStep);
break;
}
if (state.exception != null) {
if (state.listener == null) {
throw state.exception;
}
if (!state.listener.warnUser(state)) {
state.stopInstallation = true;
postInstallMsgBackToProvider(
OtaNotifier.USER_CANCELLED_MSG);
throw state.exception;
}
}
}
} finally {
if (state.previousSuite != null) {
state.previousSuite.close();
}
if (info.jarFilename != null) {
if (state.file.exists(info.jarFilename)) {
try {
state.file.delete(info.jarFilename);
} catch (Exception e) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"delete file threw an Exception");
}
}
}
}
PushRegistryInternal.enablePushLaunch(true);
}
return info.id;
| protected void | postInstallMsgBackToProvider(java.lang.String message)Posts a status message back to the provider's URL in JAD.
OtaNotifier.postInstallMsgBackToProvider(message, state,
state.proxyUsername, state.proxyPassword);
| protected void | processPreviousRMS()If this is an update, make sure the RMS data is handle correctly
according to the OTA spec.
From the OTA spec:
The RMS record stores of a MIDlet suite being updated MUST be
managed as follows:
-
If the cryptographic signer of the new MIDlet suite and the
original MIDlet suite are identical, then the RMS record
stores MUST be retained and made available to the new MIDlet
suite.
-
If the scheme, host, and path of the URL that the new
Application Descriptor is downloaded from is identical to the
scheme, host, and path of the URL the original Application
Descriptor was downloaded from, then the RMS MUST be retained
and made available to the new MIDlet suite.
-
If the scheme, host, and path of the URL that the new MIDlet
suite is downloaded from is identical to the scheme, host, and
path of the URL the original MIDlet suite was downloaded from,
then the RMS MUST be retained and made available to the new
MIDlet suite.
-
If the above statements are false, then the device MUST ask
the user whether the data from the original MIDlet suite
should be retained and made available to the new MIDlet
suite.
if (!RecordStoreFactory.suiteHasRmsData(info.id)) {
return;
}
if (state.previousInstallInfo.authPath != null &&
info.authPath != null &&
info.authPath[0].equals(
state.previousInstallInfo.authPath[0])) {
// signers the same
return;
}
if (isSameUrl(info.jadUrl, state.previousInstallInfo.getJadUrl()) ||
isSameUrl(info.jarUrl, state.previousInstallInfo.getJarUrl())) {
return;
}
// ask the user, if no listener assume no for user's answer
if (state.listener != null) {
if (state.listener.keepRMS(state)) {
// user wants to keep the data
return;
}
}
// this is a good place to check for a stop installing call
if (state.stopInstallation) {
postInstallMsgBackToProvider(
OtaNotifier.USER_CANCELLED_MSG);
throw new IOException("stopped");
}
RecordStoreFactory.removeRecordStoresForSuite(null, info.id);
| private void | redoPreviousPushConnections()Registers the push connections for previous version after
and aborted update.
for (int i = 1; ; i++) {
String pushProp;
pushProp = state.previousSuite.getProperty("MIDlet-Push-" + i);
if (pushProp == null) {
break;
}
/*
* Parse the comma separated values -
* " connection, midlet, role, filter"
*/
int comma1 = pushProp.indexOf(',", 0);
int comma2 = pushProp.indexOf(',", comma1 + 1);
String conn = pushProp.substring(0, comma1).trim();
String midlet = pushProp.substring(comma1+1, comma2).trim();
String filter = pushProp.substring(comma2+1).trim();
/* Register the new push connection string. */
try {
PushRegistryInternal.registerConnectionInternal(
state, conn, midlet, filter, true);
} catch (IOException e) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"registerConnectionInternal threw an IOException");
}
} catch (ClassNotFoundException e) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_AMS,
"registerConnectionInternal threw a " +
"ClassNotFoundException");
}
}
}
| private void | registerPushConnections()Registers the push connections for the application.
Send a message back to the server if a connection cannot be
registered and throw an exception.
byte[] curLevels = settings.getPermissions();
if (state.isPreviousVersion) {
PushRegistryInternal.unregisterConnections(info.id);
}
for (int i = 1; ; i++) {
String pushProp;
pushProp = state.getAppProperty("MIDlet-Push-" + i);
if (pushProp == null) {
break;
}
/*
* Parse the comma separated values -
* " connection, midlet, role, filter"
*/
int comma1 = pushProp.indexOf(',", 0);
int comma2 = pushProp.indexOf(',", comma1 + 1);
String conn = pushProp.substring(0, comma1).trim();
String midlet = pushProp.substring(comma1+1, comma2).trim();
String filter = pushProp.substring(comma2+1).trim();
/* Register the new push connection string. */
try {
PushRegistryInternal.registerConnectionInternal(state,
conn, midlet, filter, false);
} catch (Exception e) {
/* If already registered, abort the installation. */
PushRegistryInternal.unregisterConnections(info.id);
if (state.isPreviousVersion) {
// put back the old ones, removed above
redoPreviousPushConnections();
}
if (e instanceof SecurityException) {
postInstallMsgBackToProvider(
OtaNotifier.AUTHORIZATION_FAILURE_MSG);
// since our state object put the permission in message
throw new InvalidJadException(
InvalidJadException.AUTHORIZATION_FAILURE,
e.getMessage());
}
postInstallMsgBackToProvider(
OtaNotifier.PUSH_REG_FAILURE_MSG);
if (e instanceof IllegalArgumentException) {
throw new InvalidJadException(
InvalidJadException.PUSH_FORMAT_FAILURE, pushProp);
}
if (e instanceof ConnectionNotFoundException) {
throw new InvalidJadException(
InvalidJadException.PUSH_PROTO_FAILURE, pushProp);
}
if (e instanceof IOException) {
throw new InvalidJadException(
InvalidJadException.PUSH_DUP_FAILURE, pushProp);
}
if (e instanceof ClassNotFoundException) {
throw new InvalidJadException(
InvalidJadException.PUSH_CLASS_FAILURE, pushProp);
}
// error in the implementation code
throw (RuntimeException)e;
}
}
if (state.isPreviousVersion) {
// preserve the push options when updating
settings.setPushOptions(state.previousSuite.getPushOptions());
// use the old setting
settings.setPushInterruptSetting(
(byte)state.previousSuite.getPushInterruptSetting());
// The old suite may have not had push connections
if (settings.getPushInterruptSetting() != Permissions.NEVER) {
return;
}
}
if (curLevels[Permissions.PUSH] == Permissions.NEVER) {
settings.setPushInterruptSetting(Permissions.NEVER);
} else if (curLevels[Permissions.PUSH] == Permissions.ALLOW) {
// Start the default at session for usability when denying.
settings.setPushInterruptSetting(Permissions.SESSION);
} else {
settings.setPushInterruptSetting(curLevels[Permissions.PUSH]);
}
| public void | setExtraPermissions(java.lang.String extraPermissions)Sets the permissions that must be allowed not depending on their
presence in the application descriptor file.
Can only be called by JAM for testing.
checkMidpPermission();
additionalPermissions = extraPermissions;
| public void | setUnsignedSecurityDomain(java.lang.String domain)Sets security domain for unsigned suites. The default is untrusted.
Can only be called by JAM for testing.
checkMidpPermission();
unsignedSecurityDomain = domain;
| public boolean | stopInstalling()Stops the installation. If installer is not installing then this
method has no effect. This will cause the install method to
throw an IOException if the install is not writing the suite
to storage which is the point of no return.
if (state == null) {
return false;
}
synchronized (state) {
if (state.ignoreCancel) {
return false;
}
state.stopInstallation = true;
}
return true;
| protected int | transferData(java.io.InputStream in, java.io.OutputStream out, int chunkSize)Function that actually does the work of transferring file data.
Updates the listener every 1 K bytes.
If the amount of data to be read is larger than maxDLSize
we will break the input into chunks no larger than
chunkSize . This prevents the VM from running out of
memory when processing large files.
byte[] buffer = new byte[chunkSize];
int bytesRead;
int totalBytesWritten = 0;
if (state.listener != null) {
state.listener.updateStatus(state.beginTransferDataStatus, state);
}
try {
for (int nextUpdate = totalBytesWritten + 1024; ; ) {
bytesRead = in.read(buffer);
if (state.listener != null && (bytesRead == -1 ||
totalBytesWritten + bytesRead >= nextUpdate)) {
synchronized (state) {
if (state.stopInstallation) {
throw new IOException("stopped");
}
state.listener.updateStatus(state.transferStatus,
state);
}
nextUpdate = totalBytesWritten + 1024;
}
if (bytesRead == -1) {
return totalBytesWritten;
}
out.write(buffer, 0, bytesRead);
totalBytesWritten += bytesRead;
}
} catch (IOException ioe) {
if (state.stopInstallation) {
postInstallMsgBackToProvider(
OtaNotifier.USER_CANCELLED_MSG);
throw new IOException("stopped");
} else {
throw ioe;
}
}
| private static int | vercmp(java.lang.String ver1, java.lang.String ver2)Compares two version strings. The return values are very similar to
that of strcmp() in 'C'. If the first version is less than the second
version, a negative number will be returned. If the first version is
greater than the second version, a positive number will be returned.
If the two versions are equal, zero is returned.
Versions must be in the form xxx.yyy.zzz, where:
xxx is the major version
yyy is the minor version
zzz is the micro version
It is acceptable to omit the micro and possibly the minor versions.
If these are not included in the version string, the period immediately
preceding the number must also be removed. So, the versions
xxx.yyy or xxx are also valid.
Version numbers do not have to be three digits wide. However, you may
pad versions with leading zeros if desired.
If a version number is omitted, its value is assumed to be zero. All
tests will be based on this assumption.
For example:
1.04 > 1.
1.04 < 1.4.1
1.04 = 1.4.0
String strVal1;
String strVal2;
int intVal1;
int intVal2;
int idx1 = 0;
int idx2 = 0;
int newidx;
if ((ver1 == null) && (ver2 == null)) {
return 0;
}
if (ver1 == null) {
return -1;
}
if (ver2 == null) {
return 1;
}
for (int i = 0; i < 3; i++) {
strVal1 = "0"; // Default value
strVal2 = "0"; // Default value
if (idx1 >= 0) {
newidx = ver1.indexOf('.", idx1);
if (newidx < 0) {
strVal1 = ver1.substring(idx1);
} else {
strVal1 = ver1.substring(idx1, newidx);
newidx++; // Idx of '.'; need to go to next char
}
idx1 = newidx;
}
if (idx2 >= 0) {
newidx = ver2.indexOf('.", idx2);
if (newidx < 0) {
strVal2 = ver2.substring(idx2);
} else {
strVal2 = ver2.substring(idx2, newidx);
newidx++;
}
idx2 = newidx;
}
intVal1 = Integer.parseInt(strVal1); // May throw NFE
intVal2 = Integer.parseInt(strVal2); // May throw NFE
if (intVal1 > intVal2) {
return 1;
}
if (intVal1 < intVal2) {
return -1;
}
}
return 0;
| public void | verifyMIDlet(java.lang.String classname)Verify that a class is present in the JAR file.
If the classname is invalid or is not found an
InvalidJadException is thrown.
if (classname == null ||
classname.length() == 0) {
throw new
InvalidJadException(InvalidJadException.INVALID_VALUE);
}
String file = classname.replace('.", '/").concat(".class");
try {
/* Attempt to read the MIDlet from the JAR file. */
if (JarReader.readJarEntry(info.jarFilename, file) != null) {
return; // File found, normal return
}
// Fall into throwing the exception
} catch (IOException ioe) {
// Fall into throwing the exception
}
// Throw the InvalidJadException
throw new InvalidJadException(InvalidJadException.CORRUPT_JAR, file);
| public boolean | wasStopped()Tells if the installation was stopped by another thread.
if (state == null) {
return false;
}
return state.stopInstallation;
|
|