/*
 * 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();
}
/**
 * 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;
}
/**
 * Native method void removeComponent(int componentId) of
 * com.sun.midp.midletsuite.DynamicComponentStorage.
 * <p>
 * Removes a dynamic component given its ID.
 * <p>
 * If the component is in use it must continue to be available
 * to the other components that are using it.
 *
 * @param componentId ID of the component ot remove
 *
 * @throws IllegalArgumentException if the component cannot be found
 * @throws MIDletSuiteLockedException is thrown, if the component is
 *                                    locked
 */
KNIEXPORT KNI_RETURNTYPE_VOID
KNIDECL(com_sun_midp_midletsuite_DynamicComponentStorage_removeComponent) {
    MIDPError status;
    MidletSuiteData* pData;
    ComponentIdType componentId = KNI_GetParameterAsInt(1);

    do {
        /* check that the component exists */
        pData = get_component_data(componentId);
        if (pData == NULL) {
            status = NOT_FOUND;
            break;
        }

        status = begin_transaction(TRANSACTION_REMOVE_COMPONENT,
                                   componentId, NULL);
        if (status != ALL_OK) {
            break;
        }

        status = delete_components_files(pData->suiteId, componentId);
        if (status != ALL_OK) {
            break;
        }

        (void)remove_from_component_list_and_save(pData->suiteId, componentId);
    } while(0);

    (void)finish_transaction();

    if (status == SUITE_LOCKED) {
        KNI_ThrowNew(midletsuiteLocked, NULL);
    } else if (status == BAD_PARAMS || status == NOT_FOUND) {
        KNI_ThrowNew(midpIllegalArgumentException, "bad component ID");
    } else if (status != ALL_OK) {
        KNI_ThrowNew(midpRuntimeException,
            (status == OUT_OF_MEMORY) ? "Out of memory!" : "Remove failed");
    }

    KNI_ReturnVoid();
}