/** * Gets the settings of a MIDlet suite from persistent storage. * <pre> * The format of the properties file will be: * * push interrupt setting as an jbyte * length of a permissions as an int * array of permissions jbytes * push options as jint * </pre> * * @param ppszError pointer to character string pointer to accept an error * @param suiteId ID of the suite * @param pEnabled pointer to an enabled setting * * @return error code (ALL_OK if successful) */ MIDPError read_enabled_state(char** ppszError, SuiteIdType suiteId, jboolean* pEnabled) { MidletSuiteData* pData; MIDPError status; /* load _suites.dat */ status = read_suites_data(ppszError); if (status != ALL_OK) { return status; } pData = g_pSuitesData; *pEnabled = 0; /* try to find a suite */ while (pData != NULL) { if (pData->suiteId == suiteId) { *pEnabled = pData->isEnabled; break; } pData = pData->nextEntry; } return ALL_OK; }
/** * Tells if a given suite is in a list of the installed suites. * * @param suiteId unique ID of the midlet suite * * @return ALL_OK if the suite is in the list of the installed suites, * NOT_FOUND if not, * IO_ERROR if an i/o error occured when reading the information * about the installed suites, * OUT_OF_MEMORY if out of memory or IO error, * SUITE_CORRUPTED_ERROR is suite is found in the list, but it's * corrupted. */ static MIDPError suite_in_list(SuiteIdType suiteId) { MIDPError status; char* pszError; MidletSuiteData* pData; /* load _suites.dat */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status != ALL_OK) { return status; } pData = get_suite_data(suiteId); if (pData != NULL) { /* * Make sure that suite is not corrupted. Return * SUITE_CORRUPTED_ERROR if the suite is corrupted. * Remove the suite before returning the status. */ status = check_for_corrupted_suite(suiteId); } else { status = NOT_FOUND; } return status; }
/** * Retrieves an ID of the storage where the midlet suite with the given suite ID * is stored. * * @param suiteId The application suite ID * @param pSuiteId [out] receives an ID of the storage where the suite is stored * * @return error code (ALL_OK if successful) */ MIDPError midp_suite_get_suite_storage(SuiteIdType suiteId, StorageIdType* pStorageId) { MIDPError status; MidletSuiteData* pData; char* pszError; if (pStorageId == NULL) { return BAD_PARAMS; } if (suiteId == INTERNAL_SUITE_ID) { /* handle a special case: predefined suite ID is given */ *pStorageId = INTERNAL_STORAGE_ID; return ALL_OK; } /* load _suites.dat */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status == ALL_OK) { pData = get_suite_data(suiteId); if (pData) { *pStorageId = pData->storageId; } else { *pStorageId = UNUSED_STORAGE_ID; status = NOT_FOUND; } } return status; }
/** * If the suite exists, this function returns a unique identifier of * MIDlet suite. Note that suite may be corrupted even if it exists. * If the suite doesn't exist, a new suite ID is created. * * @param vendor name of the vendor that created the application, as * given in a JAD file * @param name name of the suite, as given in a JAD file * @param pSuiteId [out] receives the platform-specific suite ID of the * application given by vendorName and appName, or string with * a null data if suite does not exist, or * out of memory error occured, or suite is corrupted. * * @return ALL_OK if suite found, * NOT_FOUND if suite does not exist (so a new ID was created), * other error code in case of error */ MIDPError midp_get_suite_id(const pcsl_string* vendor, const pcsl_string* name, SuiteIdType* pSuiteId) { MIDPError status; char *pszError; MidletSuiteData* pData; *pSuiteId = UNUSED_SUITE_ID; /* load _suites.dat */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status != ALL_OK) { return status; } pData = g_pSuitesData; /* try to find a suite */ while (pData != NULL) { if (pcsl_string_equals(&pData->varSuiteData.suiteName, name) && pcsl_string_equals(&pData->varSuiteData.suiteVendor, vendor)) { *pSuiteId = pData->suiteId; return ALL_OK; /* IMPL_NOTE: consider SUITE_CORRUPTED_ERROR */ } pData = pData->nextEntry; } /* suite was not found - create a new suite ID */ status = midp_create_suite_id(pSuiteId); return (status == ALL_OK) ? NOT_FOUND : status; }
/** * Retrieves the number of the installed components belonging * to the given midlet suite. * * @param suiteId [in] ID of the MIDlet suite the information about * whose components must be retrieved * @param pNumOfComponents [out] pointer to variable to accept the number * of components * * @returns error code (ALL_OK if no errors) */ MIDPError midp_get_number_of_components(SuiteIdType suiteId, int* pNumOfComponents) { MIDPError status; char* pszError; MidletSuiteData* pData; int n = 0; do { if (midpInit(LIST_LEVEL) != 0) { status = OUT_OF_MEMORY; break; } /* load _suites.dat */ status = read_suites_data(&pszError); if (status != ALL_OK) { storageFreeError(pszError); break; } pData = g_pSuitesData; /* walk through the linked list */ while (pData != NULL) { if (pData->suiteId == suiteId && pData->type == COMPONENT_DYNAMIC) { n++; } pData = pData->nextEntry; } *pNumOfComponents = n; } while(0); return status; }
/* * Reads information about the installed midlet suite's component * from the storage. * * @param componentId unique ID of the component * @param ci ComponentInfo object to fill with the information about * the midlet suite's component having the given ID * * @exception IOException if an the information cannot be read * @exception IllegalArgumentException if suiteId is invalid or ci is null */ KNIEXPORT KNI_RETURNTYPE_VOID KNIDECL( com_sun_midp_midletsuite_DynamicComponentStorage_getComponentInfo) { ComponentIdType componentId = KNI_GetParameterAsInt(1); MIDPError status = ALL_OK; KNI_StartHandles(3); KNI_DeclareHandle(componentInfoObject); KNI_DeclareHandle(componentInfoClass); KNI_DeclareHandle(tmpHandle); KNI_GetParameterAsObject(2, componentInfoObject); KNI_GetObjectClass(componentInfoObject, componentInfoClass); do { char *pszError = NULL; MidletSuiteData *pData = NULL; /* Ensure that suite data are read */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status != ALL_OK) { break; } pData = get_component_data(componentId); if (!pData) { status = NOT_FOUND; break; } KNI_RESTORE_INT_FIELD(componentInfoObject, componentInfoClass, "componentId", componentId); KNI_RESTORE_INT_FIELD(componentInfoObject, componentInfoClass, "suiteId", pData->suiteId); KNI_RESTORE_PCSL_STRING_FIELD(componentInfoObject, componentInfoClass, "displayName", &(pData->varSuiteData.displayName), tmpHandle); KNI_RESTORE_PCSL_STRING_FIELD(componentInfoObject, componentInfoClass, "version", &(pData->varSuiteData.suiteVersion), tmpHandle); KNI_RESTORE_BOOLEAN_FIELD(componentInfoObject, componentInfoClass, "trusted", pData->isTrusted); } while (0); if (status != ALL_OK) { if (status == NOT_FOUND) { KNI_ThrowNew(midpIllegalArgumentException, "bad component ID"); } else { KNI_ThrowNew(midpIOException, NULL); } } KNI_EndHandles(); KNI_ReturnVoid(); }
/** * Checks the integrity of the suite storage database and of the * installed suites. * * @param fullCheck 0 to check just an integrity of the database, * other value for full check * @param delCorruptedSuites != 0 to delete the corrupted suites, * 0 - to keep them (for re-installation). * * @return ALL_OK if no errors, * SUITE_CORRUPTED_ERROR if the suite database was corrupted * but has been successfully repaired, * another error code if the database is corrupted and * could not be repaired */ MIDPError midp_check_suites_integrity(int fullCheck, int delCorruptedSuites) { MIDPError status; char *pszError = NULL; int dbWasCorrupted = 0; /* Check if there is a previously started transaction exists. */ if (unfinished_transaction_exists()) { (void)rollback_transaction(); } /* Check if the suite database is corrupted and repair it if needed. */ status = read_suites_data(&pszError); if (status == SUITE_CORRUPTED_ERROR) { dbWasCorrupted = 1; status = repair_suite_db(); } if (status != ALL_OK) { /* give up, user interaction is needed */ return status; } /* if fullCheck is true, check all installed suites */ if (fullCheck) { int i, numOfSuites; SuiteIdType suiteId, *pSuiteIds = NULL; status = midp_get_suite_ids(&pSuiteIds, &numOfSuites); if (status == ALL_OK) { for (i = 0; i < numOfSuites; i++) { suiteId = pSuiteIds[i]; if (check_for_corrupted_suite(suiteId) == SUITE_CORRUPTED_ERROR) { dbWasCorrupted = 1; if (delCorruptedSuites) { midp_remove_suite(suiteId); } } } if (pSuiteIds != NULL) { midp_free_suite_ids(pSuiteIds, numOfSuites); } } } return dbWasCorrupted ? SUITE_CORRUPTED_ERROR : ALL_OK; }
/** * Tells if a given suite is in a list of the installed suites. * * @param suiteId unique ID of the midlet suite * * @return ALL_OK if the suite is in the list of the installed suites, * NOT_FOUND if not, * IO_ERROR if an i/o error occured when reading the information * about the installed suites, * OUT_OF_MEMORY if out of memory or IO error, * SUITE_CORRUPTED_ERROR is suite is found in the list, but it's * corrupted. */ static MIDPError suite_in_list(ComponentType type, SuiteIdType suiteId, ComponentIdType componentId) { MIDPError status; char* pszError; MidletSuiteData* pData; #if !ENABLE_DYNAMIC_COMPONENTS /** to supress compilation warnings */ (void)type; (void)componentId; #endif /* load _suites.dat */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status != ALL_OK) { return status; } #if ENABLE_DYNAMIC_COMPONENTS if (type == COMPONENT_DYNAMIC) { pData = get_component_data(componentId); if (pData == NULL) { status = NOT_FOUND; } } else { #endif /* ENABLE_DYNAMIC_COMPONENTS */ pData = get_suite_data(suiteId); if (pData != NULL) { /* * Make sure that suite is not corrupted. Return * SUITE_CORRUPTED_ERROR if the suite is corrupted. * Remove the suite before returning the status. */ status = check_for_corrupted_suite(suiteId); } else { status = NOT_FOUND; } #if ENABLE_DYNAMIC_COMPONENTS } #endif return status; }
/** * Retrieves the number of installed midlet suites. * * @param pNumOfSuites [out] pointer to variable to accept the number of suites * * @returns error code (ALL_OK if no errors) */ MIDPError midp_get_number_of_suites(int* pNumOfSuites) { MIDPError status; char* pszError; do { /* * This is a public API which can be called without the VM running * so we need automatically init anything needed, to make the * caller's code less complex. * * Initialization is performed in steps so that we do use any * extra resources such as the VM for the operation being performed. */ if (midpInit(LIST_LEVEL) != 0) { status = OUT_OF_MEMORY; break; } /* load _suites.dat */ status = read_suites_data(&pszError); if (status == ALL_OK) { #if ENABLE_DYNAMIC_COMPONENTS MidletSuiteData* pData = g_pSuitesData; int num = 0; /* walk through the linked list */ while (pData != NULL) { if (pData->type == COMPONENT_REGULAR_SUITE) { num++; } pData = pData->nextEntry; } *pNumOfSuites = num; #else *pNumOfSuites = g_numberOfSuites; #endif /* ENABLE_DYNAMIC_COMPONENTS */ } else { storageFreeError(pszError); } } while(0); return status; }
/** * Retrieves an ID of the requested type for the given suite. * * @param suiteId The application suite ID * @param resultType 0 to return suite storage ID, 1 - suite folder ID * @param pResult [out] receives the requested ID * * @return error code (ALL_OK if successful) */ static MIDPError get_suite_int_impl(SuiteIdType suiteId, int resultType, void* pResult) { MIDPError status; MidletSuiteData* pData; char* pszError; if (pResult == NULL) { return BAD_PARAMS; } if (suiteId == INTERNAL_SUITE_ID) { /* handle a special case: predefined suite ID is given */ if (resultType) { *(FolderIdType*)pResult = 0; } else { *(StorageIdType*)pResult = INTERNAL_STORAGE_ID; } return ALL_OK; } /* load _suites.dat */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status == ALL_OK) { pData = get_suite_data(suiteId); if (pData) { if (resultType) { *(FolderIdType*)pResult = pData->folderId; } else { *(StorageIdType*)pResult = pData->storageId; } } else { if (resultType) { *(FolderIdType*)pResult = -1; } else { *(StorageIdType*)pResult = UNUSED_STORAGE_ID; } status = NOT_FOUND; } } return status; }
/** * Checks if a midlet suite or dynamic component with the given name * created by the given vendor exists. * If it does, this function returns a unique identifier of the suite * or component. Note that the suite or component may be corrupted even * if it exists. If it doesn't, a new suite ID or component ID is created. * * @param type type of the component * @param suiteId if type == COMPONENT_DYNAMIC, contains ID of the suite this * components belongs to; unused otherwise * @param vendor name of the vendor that created the application or component, * as given in a JAD file * @param name name of the suite or component, as given in a JAD file * @param pId [out] receives the platform-specific suite ID or component ID * of the application given by vendor and name, or UNUSED_SUITE_ID / * UNUSED_COMPONENT_ID if suite does not exist, or out of memory * error occured, or the suite / component is corrupted. * * @return ALL_OK if suite or component found, * NOT_FOUND if suite or component does not exist (so a new ID * was created), other error code in case of error */ static MIDPError get_suite_or_component_id(ComponentType type, SuiteIdType suiteId, const pcsl_string* vendor, const pcsl_string* name, jint* pId) { MIDPError status; char *pszError; MidletSuiteData* pData; #if ENABLE_DYNAMIC_COMPONENTS if (type != COMPONENT_DYNAMIC) { *pId = (jint)UNUSED_SUITE_ID; } else { *pId = (jint)UNUSED_COMPONENT_ID; } #else (void)type; (void)suiteId; *pId = (jint)UNUSED_SUITE_ID; #endif /* ENABLE_DYNAMIC_COMPONENTS */ /* load _suites.dat */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status != ALL_OK) { return status; } pData = g_pSuitesData; /* try to find a suite */ while (pData != NULL) { if (pcsl_string_equals(&pData->varSuiteData.suiteName, name) && pcsl_string_equals(&pData->varSuiteData.suiteVendor, vendor) #if ENABLE_DYNAMIC_COMPONENTS && (type == pData->type) && (type != COMPONENT_DYNAMIC || (type == COMPONENT_DYNAMIC && suiteId == pData->suiteId)) #endif ) { #if ENABLE_DYNAMIC_COMPONENTS if (type != COMPONENT_DYNAMIC) { *pId = (jint)pData->suiteId; } else { *pId = (jint)pData->componentId; } #else *pId = (jint)pData->suiteId; #endif /* ENABLE_DYNAMIC_COMPONENTS */ return ALL_OK; /* IMPL_NOTE: consider SUITE_CORRUPTED_ERROR */ } pData = pData->nextEntry; } /* suite or component was not found - create a new suite or component ID */ #if ENABLE_DYNAMIC_COMPONENTS if (type != COMPONENT_DYNAMIC) { status = midp_create_suite_id((SuiteIdType*)pId); } else { status = midp_create_component_id((ComponentIdType*)pId); } #else status = midp_create_suite_id((SuiteIdType*)pId); #endif /* ENABLE_DYNAMIC_COMPONENTS */ return (status == ALL_OK) ? NOT_FOUND : status; }
/** * Moves the given midlet suite to another folder. * * @param suiteId ID of the suite * @param newFolderId ID of the folder where the suite must be moved * * @return ALL_OK if no errors or an error code */ MIDPError midp_move_suite_to_folder(SuiteIdType suiteId, FolderIdType newFolderId) { MIDPError status = ALL_OK; char* pszError = NULL; lockStorageList *node = NULL; MidletSuiteData* pSuiteData; FolderIdType oldFolderId; /* * This is a public API which can be called without the VM running * so we need automatically init anything needed, to make the * caller's code less complex. * * Initialization is performed in steps so that we do use any * extra resources such as the VM for the operation being performed. */ if (midpInit(REMOVE_LEVEL) != 0) { return OUT_OF_MEMORY; } /* load _suites.dat */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status != ALL_OK) { return status; } node = find_storage_lock(suiteId); if (node != NULL) { if (node->update != KNI_TRUE) { return SUITE_LOCKED; } } pSuiteData = get_suite_data(suiteId); if (pSuiteData == NULL) { remove_storage_lock(suiteId); return NOT_FOUND; } status = begin_transaction(TRANSACTION_MOVE_TO_FOLDER, suiteId, NULL); if (status != ALL_OK) { remove_storage_lock(suiteId); return status; } oldFolderId = pSuiteData->folderId; pSuiteData->folderId = newFolderId; status = write_suites_data(&pszError); storageFreeError(pszError); if (status != ALL_OK) { pSuiteData->folderId = oldFolderId; (void)rollback_transaction(); } else { (void)finish_transaction(); } remove_storage_lock(suiteId); return status; }
/** * Removes a software package given its suite ID * <p> * If the component is in use it must continue to be available * to the other components that are using it. The resources it * consumes must not be released until it is not in use. * * @param suiteId ID of the suite * * @return ALL_OK if no errors, * NOT_FOUND if the suite does not exist, * SUITE_LOCKED if the suite is locked, * BAD_PARAMS this suite cannot be removed */ MIDPError midp_remove_suite(SuiteIdType suiteId) { pcsl_string filename; char* pszError; pcsl_string suiteRoot; MIDPError status; int operationStarted = 0; void* fileIteratorHandle = NULL; MidpProperties properties; pcsl_string* pproperty; MidletSuiteData* pData = NULL; pcsl_string filenameBase; lockStorageList *node = NULL; /* get the filename base from the suite id */ status = build_suite_filename(suiteId, &PCSL_STRING_EMPTY, &filenameBase); if (status != ALL_OK) { return status; } node = find_storage_lock(suiteId); if (node != NULL) { if (node->update != KNI_TRUE) { return SUITE_LOCKED; } } /* * This is a public API which can be called without the VM running * so we need automatically init anything needed, to make the * caller's code less complex. * * Initialization is performed in steps so that we do use any * extra resources such as the VM for the operation being performed. */ if (midpInit(REMOVE_LEVEL) != 0) { return OUT_OF_MEMORY; } do { int rc; /* return code for rmsdb_... and storage_... */ /* load _suites.dat */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status != ALL_OK) { break; } /* check that the suite exists and it is not a preloaded one */ pData = get_suite_data(suiteId); if (pData == NULL) { status = NOT_FOUND; break; } /* notify the listeners that we starting to remove the suite */ operationStarted = 1; suite_listeners_notify(SUITESTORE_LISTENER_TYPE_REMOVE, SUITESTORE_OPERATION_START, ALL_OK, pData); if (pData->type == COMPONENT_PREINSTALLED_SUITE) { status = BAD_PARAMS; break; } status = begin_transaction(TRANSACTION_REMOVE_SUITE, suiteId, NULL); if (status != ALL_OK) { return status; } /* * Remove the files * Call the native RMS method to remove the RMS data. * This function call is needed for portability */ rc = rmsdb_remove_record_stores_for_suite(&filenameBase, suiteId); if (rc == KNI_FALSE) { status = SUITE_LOCKED; break; } pushdeletesuite(suiteId); /* * If there is a delete notify property, add the value to the delete * notify URL list. */ properties = midp_get_suite_properties(suiteId); if (properties.numberOfProperties > 0) { pproperty = midp_find_property(&properties, &DELETE_NOTIFY_PROP); if (pcsl_string_length(pproperty) > 0) { midpAddDeleteNotification(suiteId, pproperty); } pproperty = midp_find_property(&properties, &INSTALL_NOTIFY_PROP); if (pcsl_string_length(pproperty) > 0) { /* * Remove any pending install notifications since they are only * retried when the suite is run. */ midpRemoveInstallNotification(suiteId); } midp_free_properties(&properties); } if ((status = get_suite_storage_root(suiteId, &suiteRoot)) != ALL_OK) { break; } fileIteratorHandle = storage_open_file_iterator(&suiteRoot); if (!fileIteratorHandle) { status = IO_ERROR; break; } #if ENABLE_ICON_CACHE midp_remove_suite_icons(suiteId); #endif for (;;) { rc = storage_get_next_file_in_iterator(&suiteRoot, fileIteratorHandle, &filename); if (0 != rc) { break; } storage_delete_file(&pszError, &filename); pcsl_string_free(&filename); if (pszError != NULL) { storageFreeError(pszError); break; } } } while (0); pcsl_string_free(&suiteRoot); storageCloseFileIterator(fileIteratorHandle); (void)finish_transaction(); /* * Notify the listeners the we've finished removing the suite. * It should be done before remove_from_suite_list_and_save() * call because it frees pData structure. */ if (operationStarted) { suite_listeners_notify(SUITESTORE_LISTENER_TYPE_REMOVE, SUITESTORE_OPERATION_END, status, pData); } if (status == ALL_OK) { (void)remove_from_suite_list_and_save(suiteId); } remove_storage_lock(suiteId); return status; }
/** * Get the list installed of MIDlet suite IDs. * * Note that memory for the suite IDs is allocated by the callee, * and the caller is responsible for freeing it using midp_free_suite_ids(). * * @param ppSuites empty array of jints to fill with suite IDs * @param pNumOfSuites [out] pointer to variable to accept the number * of suites in the returned array * * @returns error code: ALL_OK if no errors, * OUT_OF_MEMORY if for out of memory, * IO_ERROR if an IO error */ MIDPError midp_get_suite_ids(SuiteIdType** ppSuites, int* pNumOfSuites) { MIDPError status; char* pszError; SuiteIdType* pSuiteIds; MidletSuiteData* pData; int numberOfSuites = 0; #if ENABLE_DYNAMIC_COMPONENTS int numberOfEntries = 0; #endif *ppSuites = NULL; *pNumOfSuites = 0; /* * This is a public API which can be called without the VM running * so we need automatically init anything needed, to make the * caller's code less complex. * * Initialization is performed in steps so that we do use any * extra resources such as the VM for the operation being performed. */ if (midpInit(LIST_LEVEL) != 0) { return OUT_OF_MEMORY; } /* load _suites.dat */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status != ALL_OK) { return status; } if (!g_numberOfSuites) { /* there are no installed suites */ return ALL_OK; } pData = g_pSuitesData; /* allocate a memory for the IDs */ pSuiteIds = pcsl_mem_malloc(g_numberOfSuites * sizeof(SuiteIdType)); if (pSuiteIds == NULL) { return OUT_OF_MEMORY; } /* walk through the linked list collecting suite IDs */ while (pData != NULL) { #if ENABLE_DYNAMIC_COMPONENTS if (pData->type == COMPONENT_REGULAR_SUITE) { #endif pSuiteIds[numberOfSuites] = pData->suiteId; numberOfSuites++; #if ENABLE_DYNAMIC_COMPONENTS } numberOfEntries++; #endif pData = pData->nextEntry; } #if ENABLE_DYNAMIC_COMPONENTS if (numberOfEntries != g_numberOfSuites) { #else if (numberOfSuites != g_numberOfSuites) { #endif /* * This should not happen: it means that something is wrong with * the list of structures containing the midlet suites information. */ pcsl_mem_free(pSuiteIds); return IO_ERROR; } *ppSuites = pSuiteIds; *pNumOfSuites = numberOfSuites; return ALL_OK; } /** * Frees a list of suite IDs. * * @param pSuiteIds point to an array of suite IDs * @param numberOfSuites number of elements in pSuites */ void midp_free_suite_ids(SuiteIdType* pSuiteIds, int numberOfSuites) { (void)numberOfSuites; pcsl_mem_free(pSuiteIds); }