Interface RepositoryService

  • All Known Implementing Classes:
    RepositoryCache

    public interface RepositoryService

    Identity Repository Interface.

    • Status: public
    • Stability: stable
    Version:
    3.1.1
    Author:
    Radovan Semancik

    This service provides repository for objects that are commonly found in identity management deployments. It is used for storage and retrieval of objects. It also supports modifications (relative changes), searching and basic coordination.

    Supported object types:

    • All object types from Common Schema
    • All object types from Identity Schema
    • All object types from IDM Model Schema

    Identity repository may add some kind of basic logic in addition to a pure storage of data. E.g. it may check referential consistency, validate schema, etc.

    The implementation may store the objects and properties in any suitable way and it is not required to check any schema beyond the basic common schema structures. However, the implementation MAY be able to check additional schema definitions, e.g. to check for mandatory and allowed properties and property types. This may be either explicit (e.g. implementation checking against provided XML schema) or implicit, conforming to the constraints of the underlying storage (e.g. LDAP schema enforced by underlying directory server). One way or another, the implementation may fail to store the objects that violate the schema. The method how the schemas are "loaded" to the implementation is not defined by this interface. This interface even cannot "reveal" the schema to its users (at least not now). Therefore clients of this interface must be prepared to handle schema violation errors.

    The implementation is not required to index the data or provide any other optimizations. This depends on the specific implementation, its configuration and the underlying storage system. Qualitative constraints (such as performance) are NOT defined by this interface definition.

    Naming Conventions

    operations should be named as <operation><objectType> e.g. addUser, modifyAccount, searchObjects. The operations that returns single object instance or works on single object should be named in singular (e.g. addUser). The operation that return multiple instances should be named in plural (e.g. listObjects). Operations names should be unified as well:

    • add, modify, delete - writing to repository, single object, need OID
    • get - retrieving single object by OID
    • list - returning all objects, no or fixed search criteria
    • search - returning subset of objects with flexible search criteria

    Notes

    The definition of this interface is somehow "fuzzy" at places. E.g. allowing schema-aware implementation but not mandating it, recommending to remove duplicates, but tolerating them, etc. The reason for this is to have better fit to the underlying storage mechanisms and therefore more efficient and simpler implementation. It may complicate the clients if the code needs to be generic and fit each and every implementation of this interface. However, such code will be quite rare. Most of the custom code will be developed to work on a specific storage (e.g. Oracle DB or LDAP) and therefore can be made slightly implementation-specific. Changing the storage in a running IDM system is extremely unlikely.

    TODO

    • TODO: Atomicity, consistency
    • TODO: security constraints
    • TODO: inherently thread-safe
    • TODO: note about distributed storage systems and weak/eventual consistency
    • TODO: task coordination

    • Method Detail

      • addObject

        <T extends ObjectTypeString addObject​(PrismObject<T> object,
                                                RepoAddOptions options,
                                                OperationResult parentResult)
                                         throws ObjectAlreadyExistsException,
                                                SchemaException

        Add new object.

        The OID provided in the input message may be empty. In that case the OID will be assigned by the implementation of this method and it will be provided as return value.

        This operation should fail if such object already exists (if object with the provided OID already exists).

        The operation may fail if provided OID is in an unusable format for the storage. Generating own OIDs and providing them to this method is not recommended for normal operation.

        Should be atomic. Should not allow creation of two objects with the same OID (even if created in parallel).

        The operation may fail if the object to be created does not conform to the underlying schema of the storage system or the schema enforced by the implementation.

        Note: no need for explicit type parameter here. The object parameter contains the information.

        Parameters:
        object - object to create
        parentResult - parent OperationResult (in/out)
        Returns:
        OID assigned to the created object
        Throws:
        ObjectAlreadyExistsException - object with specified identifiers already exists, cannot add
        SchemaException - error dealing with storage schema, e.g. schema violation
        IllegalArgumentException - wrong OID format, etc.
      • searchObjects

        @NotNull
        <T extends ObjectTypeSearchResultList<PrismObject<T>> searchObjects​(Class<T> type,
                                                                              ObjectQuery query,
                                                                              Collection<SelectorOptions<GetOperationOptions>> options,
                                                                              OperationResult parentResult)
                                                                       throws SchemaException

        Search for objects in the repository.

        If no search criteria specified, list of all objects of specified type is returned.

        Searches through all object types. Returns a list of objects that match search criteria.

        Returns empty list if object type is correct but there are no objects of that type. The ordering of the results is not significant and may be arbitrary unless sorting in the paging is used.

        Should fail if object type is wrong. Should fail if unknown property is specified in the query.

        Parameters:
        query - search query
        parentResult - parent OperationResult (in/out)
        Returns:
        all objects of specified type that match search criteria (subject to paging)
        Throws:
        IllegalArgumentException - wrong object type
        SchemaException - unknown property used in search query
      • searchObjectsIterative

        <T extends ObjectTypeSearchResultMetadata searchObjectsIterative​(Class<T> type,
                                                                           ObjectQuery query,
                                                                           ResultHandler<T> handler,
                                                                           Collection<SelectorOptions<GetOperationOptions>> options,
                                                                           boolean strictlySequential,
                                                                           OperationResult parentResult)
                                                                    throws SchemaException

        Search for objects in the repository in an iterative fashion.

        Searches through all object types. Calls a specified handler for each object found. If no search criteria specified, list of all objects of specified type is returned.

        Searches through all object types. Returns a list of objects that match search criteria.

        Returns empty list if object type is correct but there are no objects of that type. The ordering of the results is not significant and may be arbitrary unless sorting in the paging is used.

        Should fail if object type is wrong. Should fail if unknown property is specified in the query.

        Parameters:
        query - search query
        handler - result handler
        strictlySequential - takes care not to skip any object nor to process objects more than once; see below
        parentResult - parent OperationResult (in/out)
        Returns:
        all objects of specified type that match search criteria (subject to paging)
        Throws:
        IllegalArgumentException - wrong object type
        SchemaException - unknown property used in search query A note related to iteration method: There are three iteration methods (see IterationMethodType): - SINGLE_TRANSACTION: Fetches objects in single DB transaction. Not supported for all DBMSs. - SIMPLE_PAGING: Uses the "simple paging" method: takes objects (e.g.) numbered 0 to 49, then 50 to 99, then 100 to 149, and so on. The disadvantage is that if the order of objects is changed during operation (e.g. by inserting/deleting some of them) then some objects can be processed multiple times, where others can be skipped. - STRICTLY_SEQUENTIAL_PAGING: Uses the "strictly sequential paging" method: sorting returned objects by OID. This is (almost) reliable in such a way that no object would be skipped. However, custom paging cannot be used in this mode. If GetOperationOptions.iterationMethod is specified, it is used without any further considerations. Otherwise, the repository configuration determines whether to use SINGLE_TRANSACTION or a paging. In the latter case, strictlySequential flag determines between SIMPLE_PAGING (if false) and STRICTLY_SEQUENTIAL_PAGING (if true). If explicit GetOperationOptions.iterationMethod is not provided, and paging is prescribed, and strictlySequential flag is true and client-provided paging conflicts with the paging used by the iteration method, a warning is issued, and iteration method is switched to SIMPLE_PAGING. Sources of conflicts: - ordering is specified - offset is specified (limit is not a problem)
      • countObjects

        <T extends ObjectType> int countObjects​(Class<T> type,
                                                ObjectQuery query,
                                                Collection<SelectorOptions<GetOperationOptions>> options,
                                                OperationResult parentResult)
                                         throws SchemaException

        Returns the number of objects that match specified criteria.

        If no search criteria specified, count of all objects of specified type is returned.

        Should fail if object type is wrong. Should fail if unknown property is specified in the query.

        Parameters:
        query - search query
        parentResult - parent OperationResult (in/out)
        Returns:
        count of objects of specified type that match search criteria (subject to paging)
        Throws:
        IllegalArgumentException - wrong object type
        SchemaException - unknown property used in search query
      • modifyObject

        @NotNull
        <T extends ObjectTypeModifyObjectResult<T> modifyObject​(Class<T> type,
                                                                  String oid,
                                                                  Collection<? extends ItemDelta> modifications,
                                                                  OperationResult parentResult)
                                                           throws ObjectNotFoundException,
                                                                  SchemaException,
                                                                  ObjectAlreadyExistsException

        Modifies object using relative change description.

        Must fail if user with provided OID does not exists. Must fail if any of the described changes cannot be applied. Should be atomic.

        If two or more modify operations are executed in parallel, the operations should be merged. In case that the operations are in conflict (e.g. one operation adding a value and the other removing the same value), the result is not deterministic.

        The operation may fail if the modified object does not conform to the underlying schema of the storage system or the schema enforced by the implementation.

        TODO: optimistic locking Note: the precondition is checked only if actual modification is going to take place (not e.g. if the list of modifications is empty).
        Parameters:
        parentResult - parent OperationResult (in/out)
        Throws:
        ObjectNotFoundException - specified object does not exist
        SchemaException - resulting object would violate the schema
        ObjectAlreadyExistsException - if resulting object would have name which already exists in another object of the same type
        IllegalArgumentException - wrong OID format, described change is not applicable
      • listAccountShadowOwner

        @Deprecated
        PrismObject<UserType> listAccountShadowOwner​(String accountOid,
                                                     OperationResult parentResult)
                                              throws ObjectNotFoundException
        Deprecated.

        Returns the User object representing owner of specified account (account shadow).

        May return null if there is no owner specified for the account.

        May only be called with OID of AccountShadow object.

        Implements the backward "owns" association between account shadow and user. Forward association is implemented by property "account" of user object.

        This is a "list" operation even though it may return at most one owner. However the operation implies searching the repository for an owner, which may be less efficient that following a direct association. Hence it is called "list" to indicate that there may be non-negligible overhead.

        Parameters:
        accountOid - OID of account shadow
        parentResult - parentResult parent OperationResult (in/out)
        Returns:
        User object representing owner of specified account
        Throws:
        ObjectNotFoundException - specified object does not exist
        IllegalArgumentException - wrong OID format
      • searchShadowOwner

        <F extends FocusTypePrismObject<F> searchShadowOwner​(String shadowOid,
                                                               Collection<SelectorOptions<GetOperationOptions>> options,
                                                               OperationResult parentResult)

        Returns the object representing owner of specified shadow.

        Implements the backward "owns" association between account shadow and user. Forward association is implemented by linkRef reference in subclasses of FocusType.

        Returns null if there is no owner for the shadow.

        This is a "search" operation even though it may return at most one owner. However the operation implies searching the repository for an owner, which may be less efficient that following a direct association. Hence it is called "search" to indicate that there may be non-negligible overhead.

        This method should not die even if the specified shadow does not exist. Even if the shadow is gone, it still may be used in some linkRefs. This method should be able to find objects with such linkeRefs otherwise we will not be able to do proper cleanup.

        Parameters:
        shadowOid - OID of shadow
        parentResult - parentResult parent OperationResult (in/out)
        Returns:
        Object representing owner of specified account (subclass of FocusType)
        Throws:
        IllegalArgumentException - wrong OID format
      • listResourceObjectShadows

        <T extends ShadowTypeList<PrismObject<T>> listResourceObjectShadows​(String resourceOid,
                                                                              Class<T> resourceObjectShadowType,
                                                                              OperationResult parentResult)
                                                                       throws ObjectNotFoundException,
                                                                              SchemaException

        Search for resource object shadows of a specified type that belong to the specified resource.

        Returns a list of such object shadows or empty list if nothing was found.

        Implements the backward "has" association between resource and resource object shadows. Forward association is implemented by property "resource" of resource object shadow.

        May only be called with OID of Resource object.

        Parameters:
        resourceOid - OID of resource definition (ResourceType)
        parentResult - parentResult parent OperationResult (in/out)
        Returns:
        resource object shadows of a specified type from specified resource
        Throws:
        ObjectNotFoundException - specified object does not exist
        SchemaException - found object is not type of ShadowType
        IllegalArgumentException - wrong OID format
      • advanceSequence

        long advanceSequence​(String oid,
                             OperationResult parentResult)
                      throws ObjectNotFoundException,
                             SchemaException
        This operation is guaranteed to be atomic. If two threads or even two nodes request a value from the same sequence at the same time then different values will be returned.
        Parameters:
        oid - sequence OID
        parentResult - Operation result
        Returns:
        next unallocated counter value
        Throws:
        ObjectNotFoundException - the sequence does not exist
        SchemaException - the sequence cannot produce a value (e.g. maximum counter reached)
      • getRepositoryDiag

        RepositoryDiag getRepositoryDiag()
        Provide repository run-time configuration and diagnostic information.
      • repositorySelfTest

        void repositorySelfTest​(OperationResult parentResult)
        Runs a short, non-descructive repository self test. This methods should never throw a (checked) exception. All the results should be recorded under the provided result structure (including fatal errors). This should implement ONLY self-tests that are IMPLEMENTATION-SPECIFIC. It must not implement self-tests that are generic and applies to all repository implementations. Such self-tests must be implemented in higher layers. If the repository has no self-tests then the method should return immediately without changing the result structure. It must not throw an exception in this case.
      • testOrgClosureConsistency

        void testOrgClosureConsistency​(boolean repairIfNecessary,
                                       OperationResult testResult)
        Checks a closure for consistency, repairing any problems found. This methods should never throw a (checked) exception. All the results should be in the returned result structure (including fatal errors). The current implementation expects closure to be of reasonable size - so it could be fetched into main memory as well as recomputed online (perhaps up to ~250K entries). In future, this method will be reimplemented. BEWARE, this method locks out the M_ORG_CLOSURE table, so org-related operations would wait until it completes. TODO this method is SQL service specific; it should be generalized/fixed somehow.
      • executeQueryDiagnostics

        RepositoryQueryDiagResponse executeQueryDiagnostics​(RepositoryQueryDiagRequest request,
                                                            OperationResult result)
        A bit of hack - execute arbitrary query, e.g. hibernate query in case of SQL repository. Use with all the care!
        Parameters:
        request - Diagnostics request
        result - Operation result
        Returns:
        diagnostics response
      • getApproximateSupportedMatchingRule

        QName getApproximateSupportedMatchingRule​(Class<?> dataType,
                                                  QName originalMatchingRule)
        Returns matching rule supported by the repository for a given data type (String, PolyString, ...), for originally intended matching rule. New matching rule must NOT be less selective than the original one. I.e. if values V1, V2 would not match under the original one, they must not also match under the replacement. Therefore it is safe to replace distinguishedName with stringIgnoreCase (but not e.g. the other way around; nor exchangeEmailAddresses can be replaced by stringIgnoreCase, because the prefix part is case sensitive). The assumption is that for unsupported matching rules the repository will store normalized values. And it will normalize any values that are used in queries. This is the obligation of the client. So, theoretically, it is safe to replace any such matching rule with default (exact) matching rule. But if we replace it with something that does not return false positives (i.e. something that is not less sensitive), we get some resiliency w.r.t. non-normalized values in repository. TODO TODO TODO think again If the original matching rule is not supported by the given data type (e.g. trying to use exchangeEmailAddress on PolyString), the result may be arbitrary. TODO think again also about this
      • createAndRegisterConflictWatcher

        ConflictWatcher createAndRegisterConflictWatcher​(@NotNull
                                                         String oid)
      • unregisterConflictWatcher

        void unregisterConflictWatcher​(ConflictWatcher watcher)