< Summary

Information
Class: Ice.CurrentExtensions
Assembly: Ice
File(s): /_/csharp/src/Ice/CurrentExtensions.cs
Tag: 91_21789722663
Line coverage
86%
Covered lines: 86
Uncovered lines: 13
Coverable lines: 99
Total lines: 280
Line coverage: 86.8%
Branch coverage
95%
Covered branches: 57
Total branches: 60
Branch coverage: 95%
Method coverage
100%
Covered methods: 7
Total methods: 7
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
checkNonIdempotent(...)50%2.5250%
createOutgoingResponse<TResult>(...)50%2.11270%
createEmptyOutgoingResponse(...)100%2.21262.5%
createOutgoingResponse(...)100%10.81080%
createOutgoingResponse(...)100%1.13150%
createOutgoingResponseCore()97.62%4242100%
startReplyStream(...)100%22100%

File(s)

/_/csharp/src/Ice/CurrentExtensions.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using Ice.Internal;
 6using System.Diagnostics;
 7
 8namespace Ice;
 9
 10/// <summary>
 11/// Provides extension methods for <see cref="Current"/>.
 12/// </summary>
 13public static class CurrentExtensions
 14{
 15    /// <summary>
 16    /// Ensures the operation mode of an incoming request is not idempotent.
 17    /// </summary>
 18    /// <param name="current">The current object of the corresponding incoming request.</param>
 19    /// <exception cref="MarshalException">Thrown when the request's operation mode is
 20    /// <see cref="OperationMode.Idempotent" /> or <see cref="OperationMode.Nonmutating" />.</exception>
 21    /// <remarks>The generated code calls this method to ensure that when an operation's mode is not idempotent
 22    /// (locally), the incoming request's operation mode is not idempotent.</remarks>
 23    public static void checkNonIdempotent(this Current current)
 24    {
 125        if (current.mode != OperationMode.Normal)
 26        {
 027            throw new MarshalException(
 028                $"Operation mode mismatch for operation '{current.operation}': received {current.mode} for non-idempoten
 29        }
 130    }
 31
 32    /// <summary>
 33    /// Creates an outgoing response with reply status <see cref="ReplyStatus.Ok"/>.
 34    /// </summary>
 35    /// <typeparam name="TResult">The type of result.</typeparam>
 36    /// <param name="current">The current object of the corresponding incoming request.</param>
 37    /// <param name="result">The result to marshal into the response payload.</param>
 38    /// <param name="marshal">The action that marshals result into an output stream.</param>
 39    /// <param name="formatType">The class format.</param>
 40    /// <returns>A new outgoing response.</returns>
 41    public static OutgoingResponse createOutgoingResponse<TResult>(
 42        this Current current,
 43        TResult result,
 44        Action<OutputStream, TResult> marshal,
 45        FormatType? formatType = null)
 46    {
 147        OutputStream ostr = current.startReplyStream();
 148        if (current.requestId != 0)
 49        {
 50            try
 51            {
 152                ostr.startEncapsulation(current.encoding, formatType);
 153                marshal(ostr, result);
 154                ostr.endEncapsulation();
 155                return new OutgoingResponse(ostr);
 56            }
 057            catch (System.Exception exception)
 58            {
 059                return current.createOutgoingResponse(exception);
 60            }
 61        }
 62        else
 63        {
 64            Debug.Fail("A one-way request cannot return a response");
 065            return new OutgoingResponse(ostr);
 66        }
 167    }
 68
 69    /// <summary>
 70    /// Creates an empty outgoing response with reply status <see cref="ReplyStatus.Ok"/>.
 71    /// </summary>
 72    /// <param name="current">The current object of the corresponding incoming request.</param>
 73    /// <returns>An outgoing response with an empty payload.</returns>
 74    public static OutgoingResponse createEmptyOutgoingResponse(this Current current)
 75    {
 176        OutputStream ostr = current.startReplyStream();
 177        if (current.requestId != 0)
 78        {
 79            try
 80            {
 181                ostr.writeEmptyEncapsulation(current.encoding);
 182            }
 083            catch (System.Exception ex)
 84            {
 085                return current.createOutgoingResponse(ex);
 86            }
 87        }
 188        return new OutgoingResponse(ostr);
 089    }
 90
 91    /// <summary>
 92    /// Creates an outgoing response with the specified payload.
 93    /// </summary>
 94    /// <param name="current">The current object of the corresponding incoming request.</param>
 95    /// <param name="ok">When <see langword="true"/>, the reply status of the response is <see cref="ReplyStatus.Ok" />;
 96    /// otherwise, it's <see cref="ReplyStatus.UserException" />.</param>
 97    /// <param name="encapsulation">The payload of the response.</param>
 98    /// <returns>A new outgoing response.</returns>
 99    public static OutgoingResponse createOutgoingResponse(this Current current, bool ok, byte[] encapsulation)
 100    {
 101        // For compatibility with the Ice 3.7 and earlier.
 1102        encapsulation ??= [];
 103
 1104        OutputStream ostr = current.startReplyStream(ok ? ReplyStatus.Ok : ReplyStatus.UserException);
 105
 1106        if (current.requestId != 0)
 107        {
 108            try
 109            {
 1110                if (encapsulation.Length > 0)
 111                {
 1112                    ostr.writeEncapsulation(encapsulation);
 113                }
 114                else
 115                {
 1116                    ostr.writeEmptyEncapsulation(current.encoding);
 117                }
 1118            }
 0119            catch (System.Exception ex)
 120            {
 0121                return current.createOutgoingResponse(ex);
 122            }
 123        }
 1124        return new OutgoingResponse(
 1125            replyStatus: ok ? ReplyStatus.Ok : ReplyStatus.UserException,
 1126            exceptionId: null,
 1127            exceptionDetails: null,
 1128            ostr);
 0129    }
 130
 131    /// <summary>
 132    /// Creates an outgoing response that marshals an exception.
 133    /// </summary>
 134    /// <param name="current">The current object of the corresponding incoming request.</param>
 135    /// <param name="exception">The exception to marshal into the response payload.</param>
 136    /// <returns>A new outgoing response.</returns>
 137    public static OutgoingResponse createOutgoingResponse(this Current current, System.Exception exception)
 138    {
 139        try
 140        {
 1141            return createOutgoingResponseCore(exception);
 142        }
 0143        catch (System.Exception ex)
 144        {
 145            // Try a second time with the marshal exception. This should not fail.
 0146            return createOutgoingResponseCore(ex);
 147        }
 148
 149        OutgoingResponse createOutgoingResponseCore(System.Exception exc)
 150        {
 151            OutputStream ostr;
 152
 1153            if (current.requestId != 0)
 154            {
 155                // The default class format doesn't matter since we always encode user exceptions in Sliced format.
 1156                ostr = new OutputStream(Protocol.currentProtocolEncoding);
 1157                ostr.writeBlob(Protocol.replyHdr);
 1158                ostr.writeInt(current.requestId);
 159            }
 160            else
 161            {
 1162                ostr = new OutputStream();
 163            }
 164
 165            ReplyStatus replyStatus;
 166            string? exceptionId;
 1167            string? dispatchExceptionMessage = null;
 168
 169            switch (exc)
 170            {
 171                case UserException ex:
 1172                    exceptionId = null;
 1173                    replyStatus = ReplyStatus.UserException;
 174
 1175                    if (current.requestId != 0)
 176                    {
 1177                        ReplyStatusHelper.write(ostr, replyStatus);
 1178                        ostr.startEncapsulation(current.encoding, FormatType.SlicedFormat);
 1179                        ostr.writeException(ex);
 1180                        ostr.endEncapsulation();
 181                    }
 1182                    break;
 183
 184                case DispatchException ex:
 1185                    exceptionId = ex.ice_id();
 1186                    replyStatus = ex.replyStatus;
 1187                    dispatchExceptionMessage = ex.Message;
 1188                    break;
 189
 190                case LocalException ex:
 1191                    exceptionId = ex.ice_id();
 1192                    replyStatus = ReplyStatus.UnknownLocalException;
 1193                    break;
 194
 195                default:
 1196                    replyStatus = ReplyStatus.UnknownException;
 1197                    exceptionId = exc.GetType().FullName ?? "System.Exception";
 198                    break;
 199            }
 200
 1201            if (replyStatus > ReplyStatus.UserException && current.requestId != 0) // two-way, so we marshal a reply
 202            {
 203                // We can't use ReplyStatusHelper to marshal a possibly unknown reply status value.
 1204                ostr.writeByte((byte)replyStatus);
 205
 1206                if (replyStatus is ReplyStatus.ObjectNotExist or
 1207                    ReplyStatus.FacetNotExist or
 1208                    ReplyStatus.OperationNotExist)
 209                {
 1210                    var rfe = exc as RequestFailedException; // can be null
 211
 1212                    Identity id = rfe?.id ?? new Identity();
 1213                    string facet = rfe?.facet ?? "";
 1214                    if (id.name.Length == 0)
 215                    {
 1216                        id = current.id;
 1217                        facet = current.facet;
 218                    }
 1219                    string operation = rfe?.operation ?? "";
 1220                    if (operation.Length == 0)
 221                    {
 1222                        operation = current.operation;
 223                    }
 224
 1225                    Identity.ice_write(ostr, id);
 226
 1227                    if (facet.Length == 0)
 228                    {
 1229                        ostr.writeStringSeq([]);
 230                    }
 231                    else
 232                    {
 1233                        ostr.writeStringSeq([facet]);
 234                    }
 1235                    ostr.writeString(operation);
 236                    // and we don't use the dispatchExceptionMessage.
 237                }
 238                else
 239                {
 240                    // If the exception is a DispatchException, we keep its message as-is; otherwise, we create a custom
 241                    // message. This message doesn't include the stack trace.
 1242                    dispatchExceptionMessage ??= $"Dispatch failed with {exceptionId}: {exc.Message}";
 1243                    ostr.writeString(dispatchExceptionMessage);
 244                }
 245            }
 246
 1247            return new OutgoingResponse(
 1248                replyStatus,
 1249                exceptionId,
 1250                replyStatus > ReplyStatus.UserException ? exc.ToString() : null,
 1251                ostr);
 252        }
 1253    }
 254
 255    /// <summary>
 256    /// Starts the output stream for a reply, with everything up to and including the reply status.
 257    /// When the request ID is 0 (one-way request), the returned output stream is empty.
 258    /// </summary>
 259    /// <param name="current">The current object of the corresponding incoming request.</param>
 260    /// <param name="replyStatus">The reply status.</param>
 261    /// <returns>The new output stream.</returns>
 262    public static OutputStream startReplyStream(this Current current, ReplyStatus replyStatus = ReplyStatus.Ok)
 263    {
 1264        if (current.requestId == 0)
 265        {
 1266            return new OutputStream();
 267        }
 268        else
 269        {
 1270            var ostr = new OutputStream(
 1271                Protocol.currentProtocolEncoding,
 1272                current.adapter.getCommunicator().instance.defaultsAndOverrides().defaultFormat);
 273
 1274            ostr.writeBlob(Protocol.replyHdr);
 1275            ostr.writeInt(current.requestId);
 1276            ReplyStatusHelper.write(ostr, replyStatus);
 1277            return ostr;
 278        }
 279    }
 280}