Esempio n. 1
0
 /// <summary>Asynchronously returns an <see cref="T:Microsoft.OData.ODataBatchOperationResponseMessage" /> for reading the content of a batch operation.</summary>
 /// <returns>A task that when completed returns a response message for reading the content of a batch operation.</returns>
 public Task <ODataBatchOperationResponseMessage> CreateOperationResponseMessageAsync()
 {
     this.VerifyCanCreateOperationResponseMessage(/*synchronousCall*/ false);
     return(TaskUtils.GetTaskForSynchronousOperation <ODataBatchOperationResponseMessage>(
                this.CreateOperationResponseMessageImplementation)
            .FollowOnFaultWith(t => this.State = ODataBatchReaderState.Exception));
 }
Esempio n. 2
0
        /// <summary>
        /// Verify the json array of the batch payload.
        /// </summary>
        /// <returns>The batch reader's Operation state.</returns>
        private ODataBatchReaderState StartReadingBatchArray()
        {
            this.batchStream.JsonReader.ReadStartArray();

            ODataBatchReaderState nextState = ODataBatchReaderState.Operation;

            return(nextState);
        }
        /// <summary>
        /// Asynchronously verify the JSON array of the batch payload.
        /// </summary>
        /// <returns>
        /// A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains the batch reader's Operation state.
        /// </returns>
        private async Task <ODataBatchReaderState> StartReadingBatchArrayAsync()
        {
            await this.batchStream.JsonReader.ReadStartArrayAsync()
            .ConfigureAwait(false);

            ODataBatchReaderState nextState = ODataBatchReaderState.Operation;

            return(nextState);
        }
Esempio n. 4
0
        /// <summary>
        /// Catch any exception thrown by the action passed in; in the exception case move the writer into
        /// state Exception and then rethrow the exception.
        /// </summary>
        /// <typeparam name="T">The type of the result returned from the <paramref name="action"/>.</typeparam>
        /// <param name="action">The action to execute.</param>
        /// <returns>The result of the <paramref name="action"/>.</returns>
        private T InterceptException <T>(Func <T> action)
        {
            try
            {
                return(action());
            }
            catch (Exception e)
            {
                if (ExceptionUtils.IsCatchableExceptionType(e))
                {
                    this.State = ODataBatchReaderState.Exception;
                }

                throw;
            }
        }
Esempio n. 5
0
        private bool ReadImplementation()
        {
            switch (this.State)
            {
            case ODataBatchReaderState.Initial:
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.Operation:
                if (this.operationState == OperationState.None)
                {
                    throw new ODataException(Strings.ODataBatchReader_NoMessageWasCreatedForOperation);
                }
                this.operationState = OperationState.None;
                if (this.contentIdToAddOnNextRead != null)
                {
                    this.urlResolver.AddContentId(this.contentIdToAddOnNextRead);
                    this.contentIdToAddOnNextRead = null;
                }
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.ChangesetStart:
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.ChangesetEnd:
                this.ResetChangeSetSize();
                this.batchStream.ResetChangeSetBoundary();
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.Completed:
            case ODataBatchReaderState.Exception:
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation));

            default:
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation));
            }
            return((this.batchReaderState != ODataBatchReaderState.Completed) && (this.batchReaderState != ODataBatchReaderState.Exception));
        }
Esempio n. 6
0
        /// <summary>
        /// Examine changeset states for the current message and setup reader state accordingly if
        /// changeset related state transition is detected.
        /// </summary>
        /// <param name="messagePropertiesCache">Current message properties.</param>
        /// <returns>The next state for the reader.</returns>
        private ODataBatchReaderState DetectChangesetStates(ODataJsonLightBatchPayloadItemPropertiesCache messagePropertiesCache)
        {
            // Validate message Id.
            string valueId = (string)messagePropertiesCache.GetPropertyValue(
                ODataJsonLightBatchPayloadItemPropertiesCache.PropertyNameId);

            string currentGroup = (string)messagePropertiesCache.GetPropertyValue(
                ODataJsonLightBatchPayloadItemPropertiesCache.PropertyNameAtomicityGroup);

            // ChangesetEnd check first; If not, check for changesetStart.
            bool changesetEnd   = this.atomicGroups.IsChangesetEnd(currentGroup);
            bool changesetStart = false;

            if (!changesetEnd)
            {
                if (currentGroup != null)
                {
                    // Add message Id to atomic group (create new group if needed).
                    // Also detect changeset start.
                    changesetStart = this.atomicGroups.AddMessageIdAndGroupId(valueId, currentGroup);
                }
            }

            // If we have changeset state change detected, set the state here.
            ODataBatchReaderState nextState = ODataBatchReaderState.Operation;

            if (changesetEnd)
            {
                nextState = ODataBatchReaderState.ChangesetEnd;
            }
            else if (changesetStart)
            {
                nextState = ODataBatchReaderState.ChangesetStart;
            }

            return(nextState);
        }
Esempio n. 7
0
 /// <summary>
 /// Sets the 'Exception' state and then throws an ODataException with the specified error message.
 /// </summary>
 /// <param name="errorMessage">The error message for the exception.</param>
 private void ThrowODataException(string errorMessage)
 {
     this.State = ODataBatchReaderState.Exception;
     throw new ODataException(errorMessage);
 }
Esempio n. 8
0
        /// <summary>
        /// Continues reading from the batch message payload.
        /// </summary>
        /// <returns>true if more items were read; otherwise false.</returns>
        private bool ReadImplementation()
        {
            Debug.Assert(this.operationState != OperationState.StreamRequested, "Should have verified that no operation stream is still active.");

            switch (this.State)
            {
            case ODataBatchReaderState.Initial:
                // The stream should be positioned at the beginning of the batch content,
                // that is before the first boundary (or the preamble if there is one).
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.Operation:
                // When reaching this state we already read the MIME headers of the operation.
                // Clients MUST call CreateOperationRequestMessage
                // or CreateOperationResponseMessage to read at least the headers of the operation.
                // This is important since we need to read the ContentId header (if present) and
                // add it to the URL resolver.
                if (this.operationState == OperationState.None)
                {
                    // No message was created; fail
                    throw new ODataException(Strings.ODataBatchReader_NoMessageWasCreatedForOperation);
                }

                // Reset the operation state; the operation state only
                // tracks the state of a batch operation while in state Operation.
                this.operationState = OperationState.None;

                // Also add a pending ContentId header to the URL resolver now. We ensured above
                // that a message has been created for this operation and thus the headers (incl.
                // a potential content ID header) have been read.
                if (this.contentIdToAddOnNextRead != null)
                {
                    this.payloadUriConverter.AddContentId(this.contentIdToAddOnNextRead);
                    this.contentIdToAddOnNextRead = null;
                }

                // When we are done with an operation, we have to skip ahead to the next part
                // when Read is called again. Note that if the operation stream was never requested
                // and the content of the operation has not been read, we'll skip it here.
                Debug.Assert(this.operationState == OperationState.None, "Operation state must be 'None' at the end of the operation.");
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.ChangesetStart:
                // When at the start of a changeset, skip ahead to the first operation in the
                // changeset (or the end boundary of the changeset).
                Debug.Assert(this.batchStream.ChangeSetBoundary != null, "Changeset boundary must have been set by now.");
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.ChangesetEnd:
                // When at the end of a changeset, reset the changeset boundary and the
                // changeset size and then skip to the next part.
                this.ResetChangeSetSize();
                this.batchStream.ResetChangeSetBoundary();
                this.batchReaderState = this.SkipToNextPartAndReadHeaders();
                break;

            case ODataBatchReaderState.Exception:        // fall through
            case ODataBatchReaderState.Completed:
                Debug.Assert(false, "Should have checked in VerifyCanRead that we are not in one of these states.");
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation));

            default:
                Debug.Assert(false, "Unsupported reader state " + this.State + " detected.");
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation));
            }

            return(this.batchReaderState != ODataBatchReaderState.Completed && this.batchReaderState != ODataBatchReaderState.Exception);
        }
Esempio n. 9
0
 /// <summary>Asynchronously reads the next part from the batch message payload.</summary>
 /// <returns>A task that when completed indicates whether more items were read.</returns>
 public Task <bool> ReadAsync()
 {
     this.VerifyCanRead(false);
     return(this.ReadAsynchronously().FollowOnFaultWith(t => this.State = ODataBatchReaderState.Exception));
 }