// **********************************************************************
//
// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
using System;
using System.Threading.Tasks;
using System.Diagnostics;
using System.ComponentModel;
namespace Ice
{
///
/// Interface for incoming requests.
///
public interface Request
{
///
/// Returns the {@link Current} object for this the request.
///
/// The Current object for this request.
Current getCurrent();
}
///
/// the base interface for servants.
///
public interface Object : ICloneable
{
///
/// Tests whether this object supports a specific Slice interface.
///
///
/// The type ID of the Slice interface to test against.
/// The Current object for the invocation.
/// True if this object has the interface
/// specified by s or derives from the interface specified by s.
bool ice_isA(string s, Current current = null);
///
/// Tests whether this object can be reached.
///
/// The Current object for the invocation.
void ice_ping(Current current = null);
///
/// Returns the Slice type IDs of the interfaces supported by this object.
///
/// The Current object for the invocation.
/// The Slice type IDs of the interfaces supported by this object, in base-to-derived
/// order. The first element of the returned array is always ::Ice::Object.
string[] ice_ids(Current current = null);
///
/// Returns the Slice type ID of the most-derived interface supported by this object.
///
/// The Current object for the invocation.
/// The Slice type ID of the most-derived interface.
string ice_id(Current current = null);
///
/// Dispatches an invocation to a servant. This method is used by dispatch interceptors to forward an invocation
/// to a servant (or to another interceptor).
///
/// The details of the invocation.
/// The task if dispatched asynchronously, null otherwise.
Task ice_dispatch(Request request);
Task iceDispatch(IceInternal.Incoming inc, Current current);
}
///
/// Base class for all Slice classes.
///
public abstract class ObjectImpl : Object
{
///
/// Instantiates an Ice object.
///
public ObjectImpl()
{
}
///
/// Returns a copy of the object. The cloned object contains field-for-field copies
/// of the state.
///
/// The cloned object.
public object Clone()
{
return MemberwiseClone();
}
private static readonly string[] _ids =
{
"::Ice::Object"
};
///
/// Tests whether this object supports a specific Slice interface.
///
/// The type ID of the Slice interface to test against.
/// The Current object for the invocation.
/// The return value is true if s is ::Ice::Object.
public virtual bool ice_isA(string s, Current current = null)
{
return s.Equals(_ids[0]);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task iceD_ice_isA(Object obj, IceInternal.Incoming inS, Current current)
{
InputStream istr = inS.startReadParams();
var id = istr.readString();
inS.endReadParams();
var ret = obj.ice_isA(id, current);
var ostr = inS.startWriteParams();
ostr.writeBool(ret);
inS.endWriteParams(ostr);
inS.setResult(ostr);
return null;
}
///
/// Tests whether this object can be reached.
/// The Current object for the invocation.
///
public virtual void ice_ping(Current current = null)
{
// Nothing to do.
}
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task iceD_ice_ping(Object obj, IceInternal.Incoming inS, Current current)
{
inS.readEmptyParams();
obj.ice_ping(current);
inS.setResult(inS.writeEmptyParams());
return null;
}
///
/// Returns the Slice type IDs of the interfaces supported by this object.
///
/// The Current object for the invocation.
/// An array whose only element is ::Ice::Object.
public virtual string[] ice_ids(Current current = null)
{
return _ids;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task iceD_ice_ids(Object obj, IceInternal.Incoming inS, Current current)
{
inS.readEmptyParams();
var ret = obj.ice_ids(current);
var ostr = inS.startWriteParams();
ostr.writeStringSeq(ret);
inS.endWriteParams(ostr);
inS.setResult(ostr);
return null;
}
///
/// Returns the Slice type ID of the most-derived interface supported by this object.
///
/// The Current object for the invocation.
/// The return value is always ::Ice::Object.
public virtual string ice_id(Current current = null)
{
return _ids[0];
}
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task iceD_ice_id(Object obj, IceInternal.Incoming inS, Current current)
{
inS.readEmptyParams();
var ret = obj.ice_id(current);
var ostr = inS.startWriteParams();
ostr.writeString(ret);
inS.endWriteParams(ostr);
inS.setResult(ostr);
return null;
}
///
/// Returns the Slice type ID of the interface supported by this object.
///
/// The return value is always ::Ice::Object.
public static string ice_staticId()
{
return _ids[0];
}
private static readonly string[] _all = new string[]
{
"ice_id", "ice_ids", "ice_isA", "ice_ping"
};
///
/// Dispatches an invocation to a servant. This method is used by dispatch interceptors to forward an invocation
/// to a servant (or to another interceptor).
///
/// The details of the invocation.
/// The task if dispatched asynchronously, null otherwise.
public virtual Task ice_dispatch(Request request)
{
var inc = (IceInternal.Incoming)request;
inc.startOver();
return iceDispatch(inc, inc.getCurrent());
}
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual Task iceDispatch(IceInternal.Incoming inc, Current current)
{
int pos = Array.BinarySearch(_all, current.operation);
if(pos < 0)
{
throw new OperationNotExistException(current.id, current.facet, current.operation);
}
switch(pos)
{
case 0:
{
return iceD_ice_id(this, inc, current);
}
case 1:
{
return iceD_ice_ids(this, inc, current);
}
case 2:
{
return iceD_ice_isA(this, inc, current);
}
case 3:
{
return iceD_ice_ping(this, inc, current);
}
}
Debug.Assert(false);
throw new OperationNotExistException(current.id, current.facet, current.operation);
}
private static string operationModeToString(OperationMode mode)
{
if(mode == OperationMode.Normal)
{
return "::Ice::Normal";
}
if(mode == OperationMode.Nonmutating)
{
return "::Ice::Nonmutating";
}
if(mode == OperationMode.Idempotent)
{
return "::Ice::Idempotent";
}
return "???";
}
public static void iceCheckMode(OperationMode expected, OperationMode received)
{
if(expected != received)
{
if(expected == OperationMode.Idempotent && received == OperationMode.Nonmutating)
{
//
// Fine: typically an old client still using the
// deprecated nonmutating keyword
//
}
else
{
MarshalException ex = new MarshalException();
ex.reason = "unexpected operation mode. expected = " + operationModeToString(expected) +
" received = " + operationModeToString(received);
throw ex;
}
}
}
}
///
/// Base class for dynamic dispatch servants. A server application
/// derives a concrete servant class from Blobject that
/// implements the Blobject.ice_invoke method.
///
public abstract class Blobject : ObjectImpl
{
///
/// Dispatch an incoming request.
///
/// The encoded in-parameters for the operation.
/// The encoded out-paramaters and return value
/// for the operation. The return value follows any out-parameters.
/// The Current object to pass to the operation.
/// If the operation completed successfully, the return value
/// is true. If the operation raises a user exception,
/// the return value is false; in this case, outParams
/// must contain the encoded user exception. If the operation raises an
/// Ice run-time exception, it must throw it directly.
public abstract bool ice_invoke(byte[] inParams, out byte[] outParams, Current current);
[EditorBrowsable(EditorBrowsableState.Never)]
public override Task iceDispatch(IceInternal.Incoming inS, Current current)
{
byte[] inEncaps = inS.readParamEncaps();
byte[] outEncaps;
bool ok = ice_invoke(inEncaps, out outEncaps, current);
inS.setResult(inS.writeParamEncaps(outEncaps, ok));
return null;
}
}
public abstract class BlobjectAsync : ObjectImpl
{
public abstract Task ice_invokeAsync(byte[] inEncaps, Current current);
[EditorBrowsable(EditorBrowsableState.Never)]
public override Task iceDispatch(IceInternal.Incoming inS, Current current)
{
byte[] inEncaps = inS.readParamEncaps();
return ice_invokeAsync(inEncaps, current).ContinueWith((Task t) =>
{
var ret = t.GetAwaiter().GetResult();
return Task.FromResult(inS.writeParamEncaps(ret.outEncaps, ret.returnValue));
}).Unwrap();
}
}
}