summaryrefslogtreecommitdiff
path: root/js/src/Ice/IncomingAsync.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/Ice/IncomingAsync.js')
-rw-r--r--js/src/Ice/IncomingAsync.js673
1 files changed, 673 insertions, 0 deletions
diff --git a/js/src/Ice/IncomingAsync.js b/js/src/Ice/IncomingAsync.js
new file mode 100644
index 00000000000..54587639ae1
--- /dev/null
+++ b/js/src/Ice/IncomingAsync.js
@@ -0,0 +1,673 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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.
+//
+// **********************************************************************
+
+(function(global){
+ require("Ice/Class");
+ require("Ice/BasicStream");
+ require("Ice/BuiltinSequences");
+ require("Ice/Connection");
+ require("Ice/Current");
+ require("Ice/Debug");
+ require("Ice/DispatchStatus");
+ require("Ice/Exception");
+ require("Ice/HashMap");
+ require("Ice/Identity");
+ require("Ice/LocalException");
+ require("Ice/Protocol");
+ require("Ice/StringUtil");
+
+ var Ice = global.Ice || {};
+
+ var BasicStream = Ice.BasicStream;
+ var Current = Ice.Current;
+ var Debug = Ice.Debug;
+ var FormatType = Ice.FormatType;
+ var HashMap = Ice.HashMap;
+ var Identity = Ice.Identity;
+ var Protocol = Ice.Protocol;
+ var StringUtil = Ice.StringUtil;
+
+ var IncomingAsync = Ice.Class({
+ __init__: function(instance, connection, adapter, response, compress, requestId)
+ {
+ this._instance = instance;
+ this._response = response;
+ this._compress = compress;
+ if(this._response)
+ {
+ this._os = new BasicStream(instance, Protocol.currentProtocolEncoding);
+ }
+ this._connection = connection;
+
+ this._current = new Current();
+ this._current.id = new Identity();
+ this._current.adapter = adapter;
+ this._current.con = this._connection;
+ this._current.requestId = requestId;
+
+ this._servant = null;
+ this._locator = null;
+ this._cookie = { value: null };
+
+ //
+ // Prepare the response if necessary.
+ //
+ if(response)
+ {
+ this._os.writeBlob(Protocol.replyHdr);
+
+ //
+ // Add the request ID.
+ //
+ this._os.writeInt(requestId);
+ }
+
+ this._is = null;
+
+ this._cb = null;
+ this._active = true;
+ },
+ __startWriteParams: function(format)
+ {
+ if(this._response)
+ {
+ Debug.assert(this._os.size == Protocol.headerSize + 4); // Reply status position.
+ Debug.assert(this._current.encoding !== null); // Encoding for reply is known.
+ this._os.writeByte(0);
+ this._os.startWriteEncaps(this._current.encoding, format);
+ }
+
+ //
+ // We still return the stream even if no response is expected. The
+ // servant code might still write some out parameters if for
+ // example a method with out parameters somehow and erroneously
+ // invoked as oneway (or if the invocation is invoked on a
+ // blobject and the blobject erroneously writes a response).
+ //
+ return this._os;
+ },
+ __endWriteParams: function(ok)
+ {
+ if(this._response)
+ {
+ var save = this._os.pos;
+ this._os.pos = Protocol.headerSize + 4; // Reply status position.
+ this._os.writeByte(ok ? Protocol.replyOK : Protocol.replyUserException);
+ this._os.pos = save;
+ this._os.endWriteEncaps();
+ }
+ },
+ __writeEmptyParams: function()
+ {
+ if(this._response)
+ {
+ Debug.assert(this._os.size === Protocol.headerSize + 4); // Reply status position.
+ Debug.assert(this._current.encoding !== null); // Encoding for reply is known.
+ this._os.writeByte(Protocol.replyOK);
+ this._os.writeEmptyEncaps(this._current.encoding);
+ }
+ },
+ __writeParamEncaps: function(v, ok)
+ {
+ if(this._response)
+ {
+ Debug.assert(this._os.size === Protocol.headerSize + 4); // Reply status position.
+ Debug.assert(this._current.encoding !== null); // Encoding for reply is known.
+ this._os.writeByte(ok ? Protocol.replyOK : Protocol.replyUserException);
+ if(v === null || v.length === 0)
+ {
+ this._os.writeEmptyEncaps(this._current.encoding);
+ }
+ else
+ {
+ this._os.writeEncaps(v);
+ }
+ }
+ },
+ __writeUserException: function(ex, format)
+ {
+ var os = this.__startWriteParams(format);
+ os.writeUserException(ex);
+ this.__endWriteParams(false);
+ },
+ __warning: function(ex)
+ {
+ Debug.assert(this._instance !== null);
+
+ var s = [];
+ s.push("dispatch exception:");
+ s.push("\nidentity: " + this._instance.identityToString(this._current.id));
+ s.push("\nfacet: " + StringUtil.escapeString(this._current.facet, ""));
+ s.push("\noperation: " + this._current.operation);
+ if(this._connection !== null)
+ {
+ var connInfo = this._connection.getInfo();
+ if(connInfo instanceof Ice.IPConnectionInfo)
+ {
+ var ipConnInfo = connInfo;
+ s.push("\nremote host: " + ipConnInfo.remoteAddress + " remote port: " + ipConnInfo.remotePort);
+ }
+ }
+ if(ex.stack)
+ {
+ s.push("\n");
+ s.push(ex.stack);
+ }
+ this._instance.initializationData().logger.warning(s.join(""));
+ },
+ __servantLocatorFinished: function()
+ {
+ Debug.assert(this._locator !== null && this._servant !== null);
+ try
+ {
+ this._locator.finished(this._current, this._servant, this._cookie.value);
+ return true;
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.UserException)
+ {
+ Debug.assert(this._connection !== null);
+
+ //
+ // The operation may have already marshaled a reply; we must overwrite that reply.
+ //
+ if(this._response)
+ {
+ this._os.resize(Protocol.headerSize + 4); // Reply status position.
+ this._os.writeByte(Protocol.replyUserException);
+ this._os.startWriteEncaps();
+ this._os.writeUserException(ex);
+ this._os.endWriteEncaps();
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+
+ this._connection = null;
+ }
+ else
+ {
+ this.__handleException(ex);
+ }
+ return false;
+ }
+ },
+ __handleException: function(ex)
+ {
+ Debug.assert(this._connection !== null);
+
+ var props = this._instance.initializationData().properties;
+ var s;
+ if(ex instanceof Ice.RequestFailedException)
+ {
+ if(ex.id === null)
+ {
+ ex.id = this._current.id;
+ }
+
+ if(ex.facet === null)
+ {
+ ex.facet = this._current.facet;
+ }
+
+ if(ex.operation === null || ex.operation.length === 0)
+ {
+ ex.operation = this._current.operation;
+ }
+
+ if(props.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 1)
+ {
+ this.__warning(ex);
+ }
+
+ if(this._response)
+ {
+ this._os.resize(Protocol.headerSize + 4); // Reply status position.
+ if(ex instanceof Ice.ObjectNotExistException)
+ {
+ this._os.writeByte(Protocol.replyObjectNotExist);
+ }
+ else if(ex instanceof Ice.FacetNotExistException)
+ {
+ this._os.writeByte(Protocol.replyFacetNotExist);
+ }
+ else if(ex instanceof Ice.OperationNotExistException)
+ {
+ this._os.writeByte(Protocol.replyOperationNotExist);
+ }
+ else
+ {
+ Debug.assert(false);
+ }
+ ex.id.__write(this._os);
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ if(ex.facet === null || ex.facet.length === 0)
+ {
+ Ice.StringSeqHelper.write(this._os, null);
+ }
+ else
+ {
+ Ice.StringSeqHelper.write(this._os, [ ex.facet ]);
+ }
+
+ this._os.writeString(ex.operation);
+
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+ }
+ else if(ex instanceof Ice.UnknownLocalException)
+ {
+ if(props.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ this.__warning(ex);
+ }
+
+ if(this._response)
+ {
+ this._os.resize(Protocol.headerSize + 4); // Reply status position.
+ this._os.writeByte(Protocol.replyUnknownLocalException);
+ this._os.writeString(ex.unknown);
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+ }
+ else if(ex instanceof Ice.UnknownUserException)
+ {
+ if(props.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ this.__warning(ex);
+ }
+
+ if(this._response)
+ {
+ this._os.resize(Protocol.headerSize + 4); // Reply status position.
+ this._os.writeByte(Protocol.replyUnknownUserException);
+ this._os.writeString(ex.unknown);
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+ }
+ else if(ex instanceof Ice.UnknownException)
+ {
+ if(props.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ this.__warning(ex);
+ }
+
+ if(this._response)
+ {
+ this._os.resize(Protocol.headerSize + 4); // Reply status position.
+ this._os.writeByte(Protocol.replyUnknownException);
+ this._os.writeString(ex.unknown);
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+ }
+ else if(ex instanceof Ice.LocalException)
+ {
+ if(props.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ this.__warning(ex);
+ }
+
+ if(this._response)
+ {
+ this._os.resize(Protocol.headerSize + 4); // Reply status position.
+ this._os.writeByte(Protocol.replyUnknownLocalException);
+ //this._os.writeString(ex.toString());
+ s = [ ex.ice_name() ];
+ if(ex.stack)
+ {
+ s.push("\n");
+ s.push(ex.stack);
+ }
+ this._os.writeString(s.join(""));
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+ }
+ else if(ex instanceof Ice.UserException)
+ {
+ if(props.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ this.__warning(ex);
+ }
+
+ if(this._response)
+ {
+ this._os.resize(Protocol.headerSize + 4); // Reply status position.
+ this._os.writeByte(Protocol.replyUnknownUserException);
+ //this._os.writeString(ex.toString());
+ s = [ ex.ice_name() ];
+ if(ex.stack)
+ {
+ s.push("\n");
+ s.push(ex.stack);
+ }
+ this._os.writeString(s.join(""));
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+ }
+ else
+ {
+ if(props.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ this.__warning(ex);
+ }
+
+ if(this._response)
+ {
+ this._os.resize(Protocol.headerSize + 4); // Reply status position.
+ this._os.writeByte(Protocol.replyUnknownException);
+ //this._os.writeString(ex.toString());
+ this._os.writeString(ex.stack ? ex.stack : "");
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+ }
+
+ this._connection = null;
+ },
+ invoke: function(servantManager, stream)
+ {
+ this._is = stream;
+
+ var start = this._is.pos;
+
+ //
+ // Read the current.
+ //
+ this._current.id.__read(this._is);
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ var facetPath = Ice.StringSeqHelper.read(this._is);
+ if(facetPath.length > 0)
+ {
+ if(facetPath.length > 1)
+ {
+ throw new Ice.MarshalException();
+ }
+ this._current.facet = facetPath[0];
+ }
+ else
+ {
+ this._current.facet = "";
+ }
+
+ this._current.operation = this._is.readString();
+ this._current.mode = Ice.OperationMode.valueOf(this._is.readByte());
+ this._current.ctx = new HashMap();
+ var sz = this._is.readSize();
+ while(sz-- > 0)
+ {
+ var first = this._is.readString();
+ var second = this._is.readString();
+ this._current.ctx.set(first, second);
+ }
+
+ //
+ // Don't put the code above into the try block below. Exceptions
+ // in the code above are considered fatal, and must propagate to
+ // the caller of this operation.
+ //
+
+ if(servantManager !== null)
+ {
+ this._servant = servantManager.findServant(this._current.id, this._current.facet);
+ if(this._servant === null)
+ {
+ this._locator = servantManager.findServantLocator(this._current.id.category);
+ if(this._locator === null && this._current.id.category.length > 0)
+ {
+ this._locator = servantManager.findServantLocator("");
+ }
+
+ if(this._locator !== null)
+ {
+ try
+ {
+ this._servant = this._locator.locate(this._current, this._cookie);
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.UserException)
+ {
+ var encoding = this._is.skipEncaps(); // Required for batch requests.
+
+ if(this._response)
+ {
+ this._os.writeByte(Protocol.replyUserException);
+ this._os.startWriteEncaps(encoding, FormatType.DefaultFormat);
+ this._os.writeUserException(ex);
+ this._os.endWriteEncaps();
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+
+ this._connection = null;
+ return;
+ }
+ else
+ {
+ this._is.skipEncaps(); // Required for batch requests.
+ this.__handleException(ex);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ try
+ {
+ if(this._servant !== null)
+ {
+ //
+ // DispatchAsync is a "pseudo dispatch status", used internally only
+ // to indicate async dispatch.
+ //
+ if(this._servant.__dispatch(this, this._current) === Ice.DispatchStatus.DispatchAsync)
+ {
+ //
+ // If this was an asynchronous dispatch, we're done here.
+ //
+ return;
+ }
+
+ if(this._locator !== null && !this.__servantLocatorFinished())
+ {
+ return;
+ }
+ }
+ else
+ {
+ //
+ // Skip the input parameters, this is required for reading
+ // the next batch request if dispatching batch requests.
+ //
+ this._is.skipEncaps();
+
+ if(servantManager !== null && servantManager.hasServant(this._current.id))
+ {
+ throw new Ice.FacetNotExistException(this._current.id, this._current.facet,
+ this._current.operation);
+ }
+ else
+ {
+ throw new Ice.ObjectNotExistException(this._current.id, this._current.facet,
+ this._current.operation);
+ }
+ }
+ }
+ catch(ex)
+ {
+ if(this._servant !== null && this._locator !== null && !this.__servantLocatorFinished())
+ {
+ return;
+ }
+ this.__handleException(ex);
+ return;
+ }
+
+ //
+ // Don't put the code below into the try block above. Exceptions
+ // in the code below are considered fatal, and must propagate to
+ // the caller of this operation.
+ //
+
+ Debug.assert(this._connection !== null);
+
+ if(this._response)
+ {
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+
+ this._connection = null;
+ },
+ startReadParams: function()
+ {
+ //
+ // Remember the encoding used by the input parameters, we'll
+ // encode the response parameters with the same encoding.
+ //
+ this._current.encoding = this._is.startReadEncaps();
+ return this._is;
+ },
+ endReadParams: function()
+ {
+ this._is.endReadEncaps();
+ },
+ readEmptyParams: function()
+ {
+ this._current.encoding = new Ice.EncodingVersion();
+ this._is.skipEmptyEncaps(this._current.encoding);
+ },
+ readParamEncaps: function()
+ {
+ this._current.encoding = new Ice.EncodingVersion();
+ return this._is.readEncaps(this._current.encoding);
+ },
+ __response: function()
+ {
+ try
+ {
+ if(this._locator !== null && !this.__servantLocatorFinished())
+ {
+ return;
+ }
+
+ Debug.assert(this._connection !== null);
+
+ if(this._response)
+ {
+ this._connection.sendResponse(this._os, this._compress);
+ }
+ else
+ {
+ this._connection.sendNoResponse();
+ }
+
+ this._connection = null;
+ }
+ catch(ex)
+ {
+ this._connection.invokeException(ex, 1);
+ }
+ },
+ __exception: function(exc)
+ {
+ try
+ {
+ if(this._locator !== null && !this.__servantLocatorFinished())
+ {
+ return;
+ }
+
+ this.__handleException(exc);
+ }
+ catch(ex)
+ {
+ this._connection.invokeException(ex, 1);
+ }
+ },
+ __validateResponse: function(ok)
+ {
+ if(!this._active)
+ {
+ return false;
+ }
+ this._active = false;
+ return true;
+ },
+ ice_exception: function(ex)
+ {
+ if(!this._active)
+ {
+ return;
+ }
+ this._active = false;
+
+ if(this._connection !== null)
+ {
+ this.__exception(ex);
+ }
+ else
+ {
+ //
+ // Response has already been sent.
+ //
+ if(this._instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ this.__warning(ex);
+ }
+ }
+ }
+ });
+
+ Ice.IncomingAsync = IncomingAsync;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));