/*
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.evolveum.midpoint.provisioning.ucf.api;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.schema.PrismSchema;
import com.evolveum.midpoint.schema.SearchResultMetadata;
import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition;
import com.evolveum.midpoint.schema.processor.ResourceAttribute;
import com.evolveum.midpoint.schema.processor.ResourceObjectIdentification;
import com.evolveum.midpoint.schema.processor.ResourceSchema;
import com.evolveum.midpoint.schema.processor.SearchHierarchyConstraints;
import com.evolveum.midpoint.schema.result.AsynchronousOperationResult;
import com.evolveum.midpoint.schema.result.AsynchronousOperationReturnValue;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.statistics.ConnectorOperationalStatus;
import com.evolveum.midpoint.task.api.StateReporter;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.PagedSearchCapabilityType;
import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
/**
* Connector instance configured for a specific resource.
*
* This is kind of connector facade. It is an API provided by
* the "Unified Connector Framework" to the midPoint provisioning
* component. There is no associated SPI yet. That may come in the
* future when this interface stabilizes a bit.
*
* This interface provides an unified facade to a connector capabilities
* in the Unified Connector Framework interface. The connector is configured
* to a specific resource instance and therefore can execute operations on
* resource.
*
* Calls to this interface always try to reach the resource and get the
* actual state on resource. The connectors are not supposed to cache any
* information. Therefore the methods do not follow get/set java convention
* as the data are not regular javabean properties.
*
* @see ConnectorFactory
*
* @author Radovan Semancik
*
*/
public interface ConnectorInstance {
public static final String OPERATION_CONFIGURE = ConnectorInstance.class.getName() + ".configure";
public static final String OPERATION_INITIALIZE = ConnectorInstance.class.getName() + ".initialize";
/**
*
* The connector instance will be configured to the state that it can
* immediately access the resource. The resource configuration is provided as
* a parameter to this method.
*
* @param configuration
* @throws ConfigurationException
*/
void configure(PrismContainerValue<?> configuration, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, SchemaException, ConfigurationException;
ConnectorOperationalStatus getOperationalStatus() throws ObjectNotFoundException;
/**
* Get necessary information from the remote system.
*
* This method will initialize the configured connector. It may contact the remote system in order to do so,
* e.g. to download the schema. It will cache the information inside connector instance until this method
* is called again. It must be called after configure() and before any other method that is accessing the
* resource.
*
* If resource schema and capabilities are already cached by midPoint they may be passed to the connector instance.
* Otherwise the instance may need to fetch them from the resource which may be less efficient.
*
*
* @param caseIgnoreAttributeNames
* @param parentResult
* @throws CommunicationException
* @throws GenericFrameworkException
* @throws ConfigurationException
*/
void initialize(ResourceSchema resourceSchema, Collection<Object> capabilities, boolean caseIgnoreAttributeNames, OperationResult parentResult)
throws CommunicationException, GenericFrameworkException, ConfigurationException;
/**
* Retrieves native connector capabilities.
*
* The capabilities specify what the connector can do without any kind of simulation or other workarounds.
* The set of capabilities may depend on the connector configuration (e.g. if a "disable" or password attribute
* was specified in the configuration or not).
*
* It may return null. Such case means that the capabilities cannot be determined.
*
* @param parentResult
* @return
* @throws CommunicationException
* @throws GenericFrameworkException
* @throws ConfigurationException
*/
Collection<Object> fetchCapabilities(OperationResult parentResult) throws CommunicationException,
GenericFrameworkException, ConfigurationException;
/**
* Retrieves the schema from the resource.
*
* The schema may be considered to be an XSD schema, but it is returned in a
* "parsed" format and it is in fact a bit stricter and richer midPoint
* schema.
*
* It may return null. Such case means that the schema cannot be determined.
*
* @see PrismSchema
*
* @return Up-to-date resource schema.
* @throws CommunicationException error in communication to the resource
* - nothing was fetched.
* @throws ConfigurationException
*/
ResourceSchema fetchResourceSchema(List<QName> generateObjectClasses, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, ConfigurationException;
/**
* Retrieves a specific object from the resource.
*
* This method is fetching an object from the resource that is identified
* by its primary identifier. It is a "targeted" method in this aspect and
* it will fail if the object is not found.
*
* The objectClass provided as a parameter to this method must correspond
* to one of the object classes in the schema. The object class must match
* the object. If it does not, the behavior of this operation is undefined.
*
* The returned ResourceObject is "disconnected" from schema. It means that
* any call to the getDefinition() method of the returned object will
* return null.
*
* TODO: object not found error
*
* @param objectClass objectClass of the object to fetch (QName).
* @param identifiers primary identifiers of the object.
* @return object fetched from the resource (no schema)
* @throws CommunicationException error in communication to the resource
* - nothing was fetched.
* @throws SchemaException error converting object from native (connector) format
*/
<T extends ShadowType> PrismObject<T> fetchObject(Class<T> type, ResourceObjectIdentification resourceObjectIdentification, AttributesToReturn attributesToReturn, StateReporter reporter,
OperationResult parentResult)
throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException,
SecurityViolationException, ConfigurationException;
/**
* Execute iterative search operation.
*
* This method will execute search operation on the resource and will pass
* any objects that are found. A "handler" callback will be called for each
* of the objects found.
*
* The call to this method will return only after all the callbacks were
* called, therefore it is not asynchronous in a strict sense.
*
* If nothing is found the method should behave as if there is an empty result set
* (handler is never called) and the call should result in a success.
* The ObjectNotFoundException should be throws only if there is an error in search
* parameters, e.g. if search base points to an non-existent object.
*
* @param objectClass
* @param handler
* @return
* @throws CommunicationException
* @throws SchemaException error converting object from the native (connector) format
* @throws ObjectNotFoundException if something from the search parameters refers non-existent object.
* e.g. if search base points to an non-existent object.
*/
<T extends ShadowType> SearchResultMetadata search(ObjectClassComplexTypeDefinition objectClassDefinition, ObjectQuery query, ResultHandler<T> handler, AttributesToReturn attributesToReturn, PagedSearchCapabilityType pagedSearchConfigurationType, SearchHierarchyConstraints searchHierarchyConstraints, StateReporter reporter,
OperationResult parentResult)
throws CommunicationException, GenericFrameworkException, SchemaException, SecurityViolationException,
ObjectNotFoundException;
/**
* Counts objects on resource.
*
* This method will count objects on the resource by executing a paged search operation,
* returning the "estimated objects count" information.
*
* If paging is not available, it throws an exception.
*
* @param objectClassDefinition
* @param query
* @param pagedSearchConfigurationType
* @param parentResult
* @throws CommunicationException
* @throws SchemaException
* @throws java.lang.UnsupportedOperationException
*/
int count(ObjectClassComplexTypeDefinition objectClassDefinition, ObjectQuery query, PagedSearchCapabilityType pagedSearchConfigurationType, StateReporter reporter,
OperationResult parentResult)
throws CommunicationException, GenericFrameworkException, SchemaException, UnsupportedOperationException;
/**
* TODO: This should return indication how the operation went, e.g. what changes were applied, what were not
* and what were not determined.
*
* The exception should be thrown only if the connector is sure that nothing was done on the resource.
* E.g. in case of connect timeout or connection refused. Timeout during operation should not cause the
* exception as something might have been done already.
*
* The connector may return some (or all) of the attributes of created object. The connector should do
* this only such operation is efficient, e.g. in case that the created object is normal return value from
* the create operation. The connector must not execute additional operation to fetch the state of
* created resource. In case that the new state is not such a normal result, the connector must
* return null. Returning empty set means that the connector supports returning of new state, but nothing
* was returned (e.g. due to a limiting configuration). Returning null means that connector does not support
* returning of new object state and the caller should explicitly invoke fetchObject() in case that the
* information is needed.
*
* @param object
* @param additionalOperations
* @throws CommunicationException
* @throws SchemaException resource schema violation
* @return created object attributes. May be null.
* @throws ObjectAlreadyExistsException object already exists on the resource
*/
AsynchronousOperationReturnValue<Collection<ResourceAttribute<?>>> addObject(PrismObject<? extends ShadowType> object, Collection<Operation> additionalOperations, StateReporter reporter,
OperationResult parentResult) throws CommunicationException, GenericFrameworkException, SchemaException,
ObjectAlreadyExistsException, ConfigurationException;
/**
* TODO: This should return indication how the operation went, e.g. what changes were applied, what were not
* and what results are we not sure about.
*
* Returns a set of attributes that were changed as a result of the operation. This may include attributes
* that were changed as a side effect of the operations, e.g. attributes that were not originally specified
* in the "changes" parameter.
*
* The exception should be thrown only if the connector is sure that nothing was done on the resource.
* E.g. in case of connect timeout or connection refused. Timeout during operation should not cause the
* exception as something might have been done already.
*
* @param identifiers The set of identifiers. Their values may change as a result of the operation, e.g. when the resource object is renamed.
* @param changes
* @throws CommunicationException
* @throws SchemaException
* @throws ObjectAlreadyExistsException in case that the modified object conflicts with another existing object (e.g. while renaming an object)
*/
AsynchronousOperationReturnValue<Collection<PropertyModificationOperation>> modifyObject(ObjectClassComplexTypeDefinition objectClass, Collection<? extends ResourceAttribute<?>> identifiers, Collection<Operation> changes, StateReporter reporter,
OperationResult parentResult)
throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException,
SecurityViolationException, ObjectAlreadyExistsException, ConfigurationException;
AsynchronousOperationResult deleteObject(ObjectClassComplexTypeDefinition objectClass, Collection<Operation> additionalOperations, Collection<? extends ResourceAttribute<?>> identifiers, StateReporter reporter,
OperationResult parentResult)
throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException, ConfigurationException;
Object executeScript(ExecuteProvisioningScriptOperation scriptOperation, StateReporter reporter, OperationResult parentResult) throws CommunicationException, GenericFrameworkException;
/**
* Creates a live Java object from a token previously serialized to string.
*
* Serialized token is not portable to other connectors or other resources.
* However, newer versions of the connector should understand tokens generated
* by previous connector version.
*
* @param serializedToken
* @return
*/
PrismProperty<?> deserializeToken(Object serializedToken);
/**
* Returns the latest token. In other words, returns a token that
* corresponds to a current state of the resource. If fetchChanges
* is immediately called with this token, nothing should be returned
* (Figuratively speaking, neglecting concurrent resource modifications).
*
* @return
* @throws CommunicationException
*/
<T> PrismProperty<T> fetchCurrentToken(ObjectClassComplexTypeDefinition objectClass, StateReporter reporter, OperationResult parentResult) throws CommunicationException, GenericFrameworkException;
/**
* Token may be null. That means "from the beginning of history".
*
* @param lastToken
* @return
*/
List<Change> fetchChanges(ObjectClassComplexTypeDefinition objectClass, PrismProperty<?> lastToken, AttributesToReturn attrsToReturn, StateReporter reporter,
OperationResult parentResult) throws CommunicationException, GenericFrameworkException, SchemaException, ConfigurationException;
//public ValidationResult validateConfiguration(ResourceConfiguration newConfiguration);
//public void applyConfiguration(ResourceConfiguration newConfiguration) throws MisconfigurationException;
// Maybe this should be moved to ConnectorManager? In that way it can also test connector instantiation.
void test(OperationResult parentResult);
void dispose();
}