summaryrefslogtreecommitdiff
path: root/js/src
diff options
context:
space:
mode:
Diffstat (limited to 'js/src')
-rw-r--r--js/src/Glacier2/.gitignore7
-rw-r--r--js/src/Glacier2/Glacier2.js15
-rw-r--r--js/src/Glacier2/Makefile40
-rw-r--r--js/src/Glacier2/Makefile.mak39
-rw-r--r--js/src/Glacier2/package.json5
-rw-r--r--js/src/Ice/.gitignore20
-rw-r--r--js/src/Ice/Address.js22
-rw-r--r--js/src/Ice/ArrayUtil.js130
-rw-r--r--js/src/Ice/AsyncResult.js120
-rw-r--r--js/src/Ice/AsyncResultBase.js70
-rw-r--r--js/src/Ice/AsyncStatus.js15
-rw-r--r--js/src/Ice/Base64.js276
-rw-r--r--js/src/Ice/BasicStream.js2961
-rw-r--r--js/src/Ice/BatchOutgoingAsync.js37
-rw-r--r--js/src/Ice/Buffer.js429
-rw-r--r--js/src/Ice/Class.js58
-rw-r--r--js/src/Ice/Communicator.js166
-rw-r--r--js/src/Ice/CompactIdRegistry.js15
-rw-r--r--js/src/Ice/ConnectRequestHandler.js429
-rw-r--r--js/src/Ice/ConnectionBatchOutgoingAsync.js30
-rw-r--r--js/src/Ice/ConnectionI.js2030
-rw-r--r--js/src/Ice/ConnectionMonitor.js114
-rw-r--r--js/src/Ice/ConnectionReaper.js39
-rw-r--r--js/src/Ice/ConnectionRequestHandler.js64
-rw-r--r--js/src/Ice/Debug.js28
-rw-r--r--js/src/Ice/DefaultsAndOverrides.js102
-rw-r--r--js/src/Ice/DispatchStatus.js15
-rw-r--r--js/src/Ice/EndpointFactoryManager.js146
-rw-r--r--js/src/Ice/EnumBase.js163
-rw-r--r--js/src/Ice/ExUtil.js53
-rw-r--r--js/src/Ice/Exception.js241
-rw-r--r--js/src/Ice/FormatType.js18
-rw-r--r--js/src/Ice/HashMap.js417
-rw-r--r--js/src/Ice/HashUtil.js61
-rw-r--r--js/src/Ice/Ice.js39
-rw-r--r--js/src/Ice/IdentityUtil.js228
-rw-r--r--js/src/Ice/ImplicitContextI.js145
-rw-r--r--js/src/Ice/IncomingAsync.js673
-rw-r--r--js/src/Ice/Initialize.js104
-rw-r--r--js/src/Ice/Instance.js573
-rw-r--r--js/src/Ice/LocalExceptionWrapper.js83
-rw-r--r--js/src/Ice/LocatorInfo.js608
-rw-r--r--js/src/Ice/LocatorManager.js88
-rw-r--r--js/src/Ice/LocatorTable.js114
-rw-r--r--js/src/Ice/Logger.js93
-rw-r--r--js/src/Ice/Long.js100
-rw-r--r--js/src/Ice/Makefile163
-rw-r--r--js/src/Ice/Makefile.mak167
-rw-r--r--js/src/Ice/Object.js307
-rw-r--r--js/src/Ice/ObjectAdapterFactory.js150
-rw-r--r--js/src/Ice/ObjectAdapterI.js547
-rw-r--r--js/src/Ice/ObjectFactory.js28
-rw-r--r--js/src/Ice/ObjectFactoryManager.js76
-rw-r--r--js/src/Ice/ObjectPrx.js967
-rw-r--r--js/src/Ice/OpaqueEndpointI.js446
-rw-r--r--js/src/Ice/Operation.js773
-rw-r--r--js/src/Ice/OptionalFormat.js19
-rw-r--r--js/src/Ice/OutgoingAsync.js572
-rw-r--r--js/src/Ice/OutgoingConnectionFactory.js956
-rw-r--r--js/src/Ice/ProcessLogger.js39
-rw-r--r--js/src/Ice/Promise.js297
-rw-r--r--js/src/Ice/Properties.js504
-rw-r--r--js/src/Ice/Property.js34
-rw-r--r--js/src/Ice/PropertyNames.js177
-rw-r--r--js/src/Ice/Protocol.js316
-rw-r--r--js/src/Ice/ProxyBatchOutgoingAsync.js54
-rw-r--r--js/src/Ice/ProxyFactory.js291
-rw-r--r--js/src/Ice/Reference.js2345
-rw-r--r--js/src/Ice/ReferenceMode.js30
-rw-r--r--js/src/Ice/RetryQueue.js83
-rw-r--r--js/src/Ice/RouterInfo.js229
-rw-r--r--js/src/Ice/RouterManager.js77
-rw-r--r--js/src/Ice/ServantManager.js297
-rw-r--r--js/src/Ice/SocketOperation.js23
-rw-r--r--js/src/Ice/StreamHelpers.js327
-rw-r--r--js/src/Ice/StringUtil.js490
-rw-r--r--js/src/Ice/Struct.js207
-rw-r--r--js/src/Ice/TcpEndpointFactory.js49
-rw-r--r--js/src/Ice/TcpEndpointI.js496
-rw-r--r--js/src/Ice/TcpTransceiver.js458
-rw-r--r--js/src/Ice/TimeUtil.js19
-rw-r--r--js/src/Ice/Timer.js123
-rw-r--r--js/src/Ice/TraceLevels.js66
-rw-r--r--js/src/Ice/TraceUtil.js474
-rw-r--r--js/src/Ice/UUID.js30
-rw-r--r--js/src/Ice/UnknownSlicedObject.js80
-rw-r--r--js/src/Ice/browser/.gitignore2
-rw-r--r--js/src/Ice/browser/Buffer.js419
-rw-r--r--js/src/Ice/browser/Debug.js41
-rw-r--r--js/src/Ice/browser/EndpointFactory.js51
-rw-r--r--js/src/Ice/browser/EndpointI.js543
-rw-r--r--js/src/Ice/browser/Transceiver.js418
-rw-r--r--js/src/Ice/package.json5
-rw-r--r--js/src/IceGrid/.gitignore10
-rw-r--r--js/src/IceGrid/IceGrid.js21
-rw-r--r--js/src/IceGrid/Makefile43
-rw-r--r--js/src/IceGrid/Makefile.mak42
-rw-r--r--js/src/IceGrid/package.json5
-rw-r--r--js/src/IceStorm/.gitignore2
-rw-r--r--js/src/IceStorm/Makefile35
-rw-r--r--js/src/IceStorm/Makefile.mak34
-rw-r--r--js/src/IceStorm/package.json5
-rw-r--r--js/src/Makefile33
-rw-r--r--js/src/Makefile.mak19
104 files changed, 25737 insertions, 0 deletions
diff --git a/js/src/Glacier2/.gitignore b/js/src/Glacier2/.gitignore
new file mode 100644
index 00000000000..bf696523d2d
--- /dev/null
+++ b/js/src/Glacier2/.gitignore
@@ -0,0 +1,7 @@
+PermissionsVerifierF.js
+PermissionsVerifier.js
+Router.js
+RouterF.js
+Session.js
+SSLInfo.js
+Metrics.js
diff --git a/js/src/Glacier2/Glacier2.js b/js/src/Glacier2/Glacier2.js
new file mode 100644
index 00000000000..a91f42e425a
--- /dev/null
+++ b/js/src/Glacier2/Glacier2.js
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// 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(){
+ require("Glacier2/PermissionsVerifier");
+ require("Glacier2/Router");
+ require("Glacier2/Session");
+ require("Glacier2/SSLInfo");
+}());
diff --git a/js/src/Glacier2/Makefile b/js/src/Glacier2/Makefile
new file mode 100644
index 00000000000..d61956f5b3a
--- /dev/null
+++ b/js/src/Glacier2/Makefile
@@ -0,0 +1,40 @@
+# **********************************************************************
+#
+# 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.
+#
+# **********************************************************************
+
+top_srcdir = ../..
+
+LIBNAME = Glacier2
+
+TARGETS = $(call mklibtargets,$(LIBNAME))
+
+SLICES = $(SDIR)/PermissionsVerifierF.ice \
+ $(SDIR)/PermissionsVerifier.ice \
+ $(SDIR)/Router.ice \
+ $(SDIR)/RouterF.ice \
+ $(SDIR)/Session.ice \
+ $(SDIR)/SSLInfo.ice \
+ $(SDIR)/Metrics.ice
+
+SDIR = $(slicedir)/Glacier2
+
+GEN_SRCS = $(patsubst $(SDIR)/%.ice, %.js, $(SLICES))
+
+SRCS := $(GEN_SRCS)
+INSTALL_SRCS := Glacier2.js $(GEN_SRCS)
+
+include $(top_srcdir)/config/Make.rules.js
+
+SLICE2JSFLAGS := $(SLICE2JSFLAGS) --ice -I$(slicedir)
+
+lint:: $(INSTALL_SRCS)
+ jshint $(LINTFLAGS) $(INSTALL_SRCS)
+
+install:: all
+ $(call installlib,$(DESTDIR)$(install_libdir),$(libdir),$(LIBNAME))
+ $(call installmodule,$(DESTDIR)$(install_moduledir),$(INSTALL_SRCS),$(LIBNAME))
diff --git a/js/src/Glacier2/Makefile.mak b/js/src/Glacier2/Makefile.mak
new file mode 100644
index 00000000000..482e18412ff
--- /dev/null
+++ b/js/src/Glacier2/Makefile.mak
@@ -0,0 +1,39 @@
+# **********************************************************************
+#
+# 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.
+#
+# **********************************************************************
+
+top_srcdir = ..\..
+
+LIBNAME = Glacier2
+
+GEN_SRCS = PermissionsVerifierF.js \
+ PermissionsVerifier.js \
+ Router.js \
+ RouterF.js \
+ Session.js \
+ SSLInfo.js \
+ Metrics.js
+
+SDIR = $(slicedir)\Glacier2
+
+SRCS = $(GEN_SRCS)
+INSTALL_SRCS = Glacier2.js $(GEN_SRCS)
+
+!include $(top_srcdir)\config\Make.rules.mak.js
+
+SLICE2JSFLAGS = $(SLICE2JSFLAGS) --ice -I"$(slicedir)"
+
+MODULEDIR = $(install_moduledir)\$(LIBNAME)
+
+install:: all
+ @if not exist $(MODULEDIR) \
+ @echo "Creating $(MODULEDIR)" && \
+ mkdir "$(MODULEDIR)"
+ @for %i in ( $(INSTALL_SRCS) ) do \
+ copy %i "$(MODULEDIR)"
+ copy package.json "$(MODULEDIR)"
diff --git a/js/src/Glacier2/package.json b/js/src/Glacier2/package.json
new file mode 100644
index 00000000000..f4d3062e38d
--- /dev/null
+++ b/js/src/Glacier2/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "Glacier2",
+ "version": "0.1.0",
+ "main": "Glacier2.js"
+}
diff --git a/js/src/Ice/.gitignore b/js/src/Ice/.gitignore
new file mode 100644
index 00000000000..77776474437
--- /dev/null
+++ b/js/src/Ice/.gitignore
@@ -0,0 +1,20 @@
+# Ignore generated files
+BuiltinSequences.js
+Connection.js
+Current.js
+Endpoint.js
+EndpointTypes.js
+Identity.js
+LocalException.js
+Locator.js
+Metrics.js
+Process.js
+PropertiesAdmin.js
+Router.js
+ServantLocator.js
+SliceChecksumDict.js
+Version.js
+ConnectionF.js
+EndpointF.js
+ObjectAdapterF.js
+ProcessF.js
diff --git a/js/src/Ice/Address.js b/js/src/Ice/Address.js
new file mode 100644
index 00000000000..cfeeb2149c1
--- /dev/null
+++ b/js/src/Ice/Address.js
@@ -0,0 +1,22 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+
+ var Address = function(host, port)
+ {
+ this.host = host;
+ this.port = port;
+ };
+
+ Ice.Address = Address;
+
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ArrayUtil.js b/js/src/Ice/ArrayUtil.js
new file mode 100644
index 00000000000..6389845d69b
--- /dev/null
+++ b/js/src/Ice/ArrayUtil.js
@@ -0,0 +1,130 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+ var Slice = global.Slice || {};
+ var ArrayUtil = {};
+
+ ArrayUtil.clone = function(arr)
+ {
+ if(arr === undefined)
+ {
+ return arr;
+ }
+ else if(arr === null)
+ {
+ return [];
+ }
+ else
+ {
+ return arr.slice();
+ }
+ };
+
+ ArrayUtil.equals = function(v1, v2, equalFn)
+ {
+ var i, length;
+
+ if(v1.length != v2.length)
+ {
+ return false;
+ }
+
+ if(equalFn !== undefined && equalFn !== null)
+ {
+ for(i = 0, length = v1.length; i < length; ++i)
+ {
+ if(!equalFn.call(equalFn, v1[i], v2[i]))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ for(i = 0, length = v1.length; i < length; ++i)
+ {
+ if(v1[i] != v2[i])
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
+ ArrayUtil.shuffle = function(arr)
+ {
+ for(var i = arr.length; i > 1; --i)
+ {
+ var e = arr[i - 1];
+ var rand = Math.floor(Math.random() * i);
+ arr[i - 1] = arr[rand];
+ arr[rand] = e;
+ }
+ };
+
+ ArrayUtil.indexOf = function(arr, elem, equalFn)
+ {
+ if(equalFn !== undefined && equalFn !== null)
+ {
+ for(var i = 0; i < arr.length; ++i)
+ {
+ if(equalFn.call(equalFn, arr[i], elem))
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ return arr.indexOf(elem);
+ }
+
+ return -1;
+ };
+
+ ArrayUtil.filter = function(arr, includeFn, obj)
+ {
+ obj = obj === undefined ? includeFn : obj;
+ var result = [];
+ for(var i = 0; i < arr.length; ++i)
+ {
+ if(includeFn.call(obj, arr[i], i, arr))
+ {
+ result.push(arr[i]);
+ }
+ }
+ return result;
+ };
+
+ Slice.defineSequence = function(module, name, valueHelper, fixed, elementType)
+ {
+ var helper = null;
+ Object.defineProperty(module, name,
+ {
+ get: function()
+ {
+ if(helper === null)
+ {
+ /*jshint -W061 */
+ helper = Ice.StreamHelpers.generateSeqHelper(eval(valueHelper), fixed, eval(elementType));
+ /*jshint +W061 */
+ }
+ return helper;
+ }
+ });
+ };
+
+ Ice.ArrayUtil = ArrayUtil;
+ global.Slice = Slice;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/AsyncResult.js b/js/src/Ice/AsyncResult.js
new file mode 100644
index 00000000000..1f2d5f8c6b2
--- /dev/null
+++ b/js/src/Ice/AsyncResult.js
@@ -0,0 +1,120 @@
+// **********************************************************************
+//
+// 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/AsyncResultBase");
+ require("Ice/Debug");
+ require("Ice/Promise");
+ require("Ice/Protocol");
+ require("Ice/Exception");
+ require("Ice/BasicStream");
+
+ var Ice = global.Ice || {};
+
+ var AsyncResultBase = Ice.AsyncResultBase;
+ var Debug = Ice.Debug;
+ var Promise = Ice.Promise;
+ var Protocol = Ice.Protocol;
+ var UserException = Ice.UserException;
+ var BasicStream = Ice.BasicStream;
+
+ var AsyncResult = Ice.Class(AsyncResultBase, {
+ __init__: function(communicator, op, connection, proxy, adapter, completedFn, sentFn)
+ {
+ //
+ // AsyncResult can be constructed by a sub-type's prototype, in which case the
+ // arguments are undefined.
+ //
+ AsyncResultBase.call(this, communicator, op, connection, proxy, adapter);
+ if(communicator !== undefined)
+ {
+ this._completed = completedFn;
+ this._sent = sentFn;
+ this._is = null;
+ this._os = communicator !== null ?
+ new BasicStream(this._instance, Protocol.currentProtocolEncoding, false) : null;
+ this._state = 0;
+ this._exception = null;
+ }
+ },
+ __os: function()
+ {
+ return this._os;
+ },
+ __is: function()
+ {
+ return this._is;
+ },
+ __startReadParams: function()
+ {
+ this._is.startReadEncaps();
+ return this._is;
+ },
+ __endReadParams: function()
+ {
+ this._is.endReadEncaps();
+ },
+ __readEmptyParams: function()
+ {
+ this._is.skipEmptyEncaps(null);
+ },
+ __readParamEncaps: function()
+ {
+ return this._is.readEncaps(null);
+ },
+ __throwUserException: function()
+ {
+ Debug.assert((this._state & AsyncResult.Done) !== 0);
+ if((this._state & AsyncResult.OK) === 0)
+ {
+ try
+ {
+ this._is.startReadEncaps();
+ this._is.throwException();
+ }
+ catch(ex)
+ {
+ if(ex instanceof UserException)
+ {
+ this._is.endReadEncaps();
+ }
+ throw ex;
+ }
+ }
+ },
+ __exception: function(ex)
+ {
+ this._state |= AsyncResult.Done;
+ this._exception = ex;
+ this._os.resize(0);
+ this.fail(ex, this);
+ },
+ __response: function()
+ {
+ //
+ // Note: no need to change the state here, specializations are responsible for
+ // changing the state.
+ //
+
+ if(this.proxy !== null && this.proxy.ice_isTwoway())
+ {
+ Debug.assert(this._completed !== null);
+ this._completed(this);
+ }
+ }
+ });
+
+ AsyncResult.OK = 0x1;
+ AsyncResult.Done = 0x2;
+ AsyncResult.Sent = 0x4;
+
+ Ice.AsyncResult = AsyncResult;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/AsyncResultBase.js b/js/src/Ice/AsyncResultBase.js
new file mode 100644
index 00000000000..348c715082e
--- /dev/null
+++ b/js/src/Ice/AsyncResultBase.js
@@ -0,0 +1,70 @@
+// **********************************************************************
+//
+// 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/Debug");
+ require("Ice/Promise");
+ require("Ice/Exception");
+
+ var Ice = global.Ice || {};
+
+ var Promise = Ice.Promise;
+
+ var AsyncResultBase = Ice.Class(Promise, {
+ __init__: function(communicator, op, connection, proxy, adapter)
+ {
+ //
+ // AsyncResultBase can be constructed by a sub-type's prototype, in which case the
+ // arguments are undefined.
+ //
+ Promise.call(this);
+ if(communicator !== undefined)
+ {
+ this._communicator = communicator;
+ this._instance = communicator !== null ? communicator.instance : null;
+ this._operation = op;
+ this._connection = connection;
+ this._proxy = proxy;
+ this._adapter = adapter;
+ }
+ },
+ __exception: function(ex)
+ {
+ this.fail(ex);
+ }
+ });
+
+ var prototype = AsyncResultBase.prototype;
+ var defineProperty = Object.defineProperty;
+
+ defineProperty(prototype, "communicator", {
+ get: function() { return this._communicator; }
+ });
+
+ defineProperty(prototype, "connection", {
+ get: function() { return this._connection; }
+ });
+
+ defineProperty(prototype, "proxy", {
+ get: function() { return this._proxy; }
+ });
+
+ defineProperty(prototype, "adapter", {
+ get: function() { return this._adapter; }
+ });
+
+ defineProperty(prototype, "operation", {
+ get: function() { return this._operation; }
+ });
+
+ Ice.AsyncResultBase = AsyncResultBase;
+
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/AsyncStatus.js b/js/src/Ice/AsyncStatus.js
new file mode 100644
index 00000000000..e8d3142bcf9
--- /dev/null
+++ b/js/src/Ice/AsyncStatus.js
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+ var AsyncStatus = {Queued: 0, Sent: 1};
+ Ice.AsyncStatus = AsyncStatus;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Base64.js b/js/src/Ice/Base64.js
new file mode 100644
index 00000000000..f1f9ec47964
--- /dev/null
+++ b/js/src/Ice/Base64.js
@@ -0,0 +1,276 @@
+// **********************************************************************
+//
+// 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/Buffer");
+
+ var Ice = global.Ice || {};
+
+ var Buffer = Ice.Buffer;
+
+ var Base64 = {};
+
+ var _codeA = "A".charCodeAt(0);
+ var _codea = "a".charCodeAt(0);
+ var _code0 = "0".charCodeAt(0);
+
+ Base64.encode = function(buf) // Expects native Buffer
+ {
+ if(buf === null || buf.length === 0)
+ {
+ return "";
+ }
+
+ var base64Bytes = (((buf.length * 4) / 3) + 1);
+ var newlineBytes = (((base64Bytes * 2) / 76) + 1);
+ var totalBytes = base64Bytes + newlineBytes;
+
+ var v = [];
+
+ var by1;
+ var by2;
+ var by3;
+ var by4;
+ var by5;
+ var by6;
+ var by7;
+
+ for(var i = 0; i < buf.length; i += 3)
+ {
+ by1 = buf[i] & 0xff;
+ by2 = 0;
+ by3 = 0;
+
+ if((i + 1) < buf.length)
+ {
+ by2 = buf[i + 1] & 0xff;
+ }
+
+ if((i + 2) < buf.length)
+ {
+ by3 = buf[i + 2] & 0xff;
+ }
+
+ by4 = (by1 >> 2) & 0xff;
+ by5 = (((by1 & 0x3) << 4) | (by2 >> 4)) & 0xff;
+ by6 = (((by2 & 0xf) << 2) | (by3 >> 6)) & 0xff;
+ by7 = by3 & 0x3f;
+
+ v.push(encodeChar(by4));
+ v.push(encodeChar(by5));
+
+ if((i + 1) < buf.length)
+ {
+ v.push(encodeChar(by6));
+ }
+ else
+ {
+ v.push("=");
+ }
+
+ if((i + 2) < buf.length)
+ {
+ v.push(encodeChar(by7));
+ }
+ else
+ {
+ v.push("=");
+ }
+ }
+
+ var retval = v.join("");
+ var outString = [];
+ var iter = 0;
+
+ while((retval.length - iter) > 76)
+ {
+ outString.push(retval.substring(iter, iter + 76));
+ outString.push("\r\n");
+ iter += 76;
+ }
+
+ outString.push(retval.substring(iter));
+
+ return outString.join("");
+ };
+
+ Base64.decode = function(str) // Returns native Buffer
+ {
+ var newStr = [];
+
+ for(var j = 0; j < str.length; j++)
+ {
+ var c = str.charAt(j);
+ if(Base64.isBase64(c))
+ {
+ newStr.push(c);
+ }
+ }
+
+ if(newStr.length === 0)
+ {
+ return null;
+ }
+
+ // Note: This is how we were previously computing the size of the return
+ // sequence. The method below is more efficient (and correct).
+ // size_t lines = str.size() / 78;
+ // size_t totalBytes = (lines * 76) + (((str.size() - (lines * 78)) * 3) / 4);
+
+ // Figure out how long the final sequence is going to be.
+ var totalBytes = (newStr.length * 3 / 4) + 1;
+
+ var retval = new Buffer();
+ retval.resize(totalBytes);
+
+ var by1;
+ var by2;
+ var by3;
+ var by4;
+
+ var c1;
+ var c2;
+ var c3;
+ var c4;
+
+ var off = 0;
+
+ for(var i = 0; i < newStr.length; i += 4)
+ {
+ c1 = "A";
+ c2 = "A";
+ c3 = "A";
+ c4 = "A";
+
+ c1 = newStr[i];
+
+ if((i + 1) < newStr.length)
+ {
+ c2 = newStr[i + 1];
+ }
+
+ if((i + 2) < newStr.length)
+ {
+ c3 = newStr[i + 2];
+ }
+
+ if((i + 3) < newStr.length)
+ {
+ c4 = newStr[i + 3];
+ }
+
+ by1 = decodeChar(c1) & 0xff;
+ by2 = decodeChar(c2) & 0xff;
+ by3 = decodeChar(c3) & 0xff;
+ by4 = decodeChar(c4) & 0xff;
+
+ retval.put((by1 << 2) | (by2 >> 4));
+
+ if(c3 != "=")
+ {
+ retval.put(((by2 & 0xf) << 4) | (by3 >> 2));
+ }
+
+ if(c4 != "=")
+ {
+ retval.put(((by3 & 0x3) << 6) | by4);
+ }
+ }
+
+ return retval.remaining > 0 ? retval.getArrayAt(0, retval.position) : retval.getArrayAt(0);
+ };
+
+ Base64.isBase64 = function(c)
+ {
+ if(c >= 'A' && c <= 'Z')
+ {
+ return true;
+ }
+
+ if(c >= 'a' && c <= 'z')
+ {
+ return true;
+ }
+
+ if(c >= '0' && c <= '9')
+ {
+ return true;
+ }
+
+ if(c == '+')
+ {
+ return true;
+ }
+
+ if(c == '/')
+ {
+ return true;
+ }
+
+ if(c == '=')
+ {
+ return true;
+ }
+
+ return false;
+ };
+
+ function encodeChar(uc)
+ {
+ if(uc < 26)
+ {
+ return String.fromCharCode(_codeA + uc);
+ }
+
+ if(uc < 52)
+ {
+ return String.fromCharCode(_codea + (uc - 26));
+ }
+
+ if(uc < 62)
+ {
+ return String.fromCharCode(_code0 + (uc - 52));
+ }
+
+ if(uc == 62)
+ {
+ return "+";
+ }
+
+ return "/";
+ }
+
+ function decodeChar(c)
+ {
+ if(c >= 'A' && c <= 'Z')
+ {
+ return c.charCodeAt(0) - _codeA;
+ }
+
+ if(c >= 'a' && c <= 'z')
+ {
+ return c.charCodeAt(0) - _codea + 26;
+ }
+
+ if(c >= '0' && c <= '9')
+ {
+ return c.charCodeAt(0) - _code0 + 52;
+ }
+
+ if(c == '+')
+ {
+ return 62;
+ }
+
+ return 63;
+ }
+
+ Ice.Base64 = Base64;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/BasicStream.js b/js/src/Ice/BasicStream.js
new file mode 100644
index 00000000000..db423be4c91
--- /dev/null
+++ b/js/src/Ice/BasicStream.js
@@ -0,0 +1,2961 @@
+// **********************************************************************
+//
+// 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/Debug");
+ require("Ice/ExUtil");
+ require("Ice/FormatType");
+ require("Ice/HashMap");
+ require("Ice/Object");
+ require("Ice/OptionalFormat");
+ require("Ice/Protocol");
+ require("Ice/TraceUtil");
+ require("Ice/Buffer");
+ require("Ice/Exception");
+ require("Ice/LocalException");
+ require("Ice/Version");
+ require("Ice/CompactIdRegistry");
+ require("Ice/ArrayUtil");
+ require("Ice/UnknownSlicedObject");
+
+ var Ice = global.Ice || {};
+
+ var Debug = Ice.Debug;
+ var ExUtil = Ice.ExUtil;
+ var FormatType = Ice.FormatType;
+ var HashMap = Ice.HashMap;
+ var IceObject = Ice.Object;
+ var OptionalFormat = Ice.OptionalFormat;
+ var Protocol = Ice.Protocol;
+ var TraceUtil = Ice.TraceUtil;
+ var ArrayUtil = Ice.ArrayUtil;
+ var SlicedData = Ice.SlicedData;
+
+ var SliceType = {};
+ SliceType.NoSlice = 0;
+ SliceType.ObjectSlice = 1;
+ SliceType.ExceptionSlice = 2;
+
+ var OPTIONAL_END_MARKER = 0xFF;
+ var FLAG_HAS_TYPE_ID_STRING = (1<<0);
+ var FLAG_HAS_TYPE_ID_INDEX = (1<<1);
+ var FLAG_HAS_TYPE_ID_COMPACT = (1<<1 | 1<<0);
+ var FLAG_HAS_OPTIONAL_MEMBERS = (1<<2);
+ var FLAG_HAS_INDIRECTION_TABLE = (1<<3);
+ var FLAG_HAS_SLICE_SIZE = (1<<4);
+ var FLAG_IS_LAST_SLICE = (1<<5);
+
+ var IndirectPatchEntry = function(index, patcher)
+ {
+ this.index = index;
+ this.patcher = patcher;
+ };
+
+ var Class = Ice.Class;
+
+ var EncapsDecoder = Class({
+ __init__: function(stream, encaps, sliceObjects, f)
+ {
+ this._stream = stream;
+ this._encaps = encaps;
+ this._sliceObjects = sliceObjects;
+ this._servantFactoryManager = f;
+ this._patchMap = null; // Lazy initialized, HashMap<int, Patcher[] >()
+ this._unmarshaledMap = new HashMap(); // HashMap<int, Ice.Object>()
+ this._typeIdMap = null; // Lazy initialized, HashMap<int, String>
+ this._typeIdIndex = 0;
+ this._objectList = null; // Lazy initialized. Ice.Object[]
+ },
+ readOpt: function()
+ {
+ return false;
+ },
+ readPendingObjects: function()
+ {
+ },
+ readTypeId: function(isIndex)
+ {
+ var typeId, index;
+ if(this._typeIdMap === null) // Lazy initialization
+ {
+ this._typeIdMap = new HashMap(); // Map<int, String>();
+ }
+
+ if(isIndex)
+ {
+ index = this._stream.readSize();
+ typeId = this._typeIdMap.get(index);
+ if(typeId === undefined)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ }
+ else
+ {
+ typeId = this._stream.readString();
+ this._typeIdMap.set(++this._typeIdIndex, typeId);
+ }
+ return typeId;
+ },
+ newInstance: function(typeId)
+ {
+ //
+ // Try to find a factory registered for the specific type.
+ //
+ var userFactory = this._servantFactoryManager.find(typeId);
+ var v = null;
+
+ if(userFactory !== undefined)
+ {
+ v = userFactory.create(typeId);
+ }
+
+ //
+ // If that fails, invoke the default factory if one has been
+ // registered.
+ //
+ if(v === null || v === undefined)
+ {
+ userFactory = this._servantFactoryManager.find("");
+ if(userFactory !== undefined)
+ {
+ v = userFactory.create(typeId);
+ }
+ }
+
+ //
+ // Last chance: try to instantiate the class dynamically.
+ //
+ if(v === null || v === undefined)
+ {
+ v = this._stream.createObject(typeId);
+ }
+
+ return v;
+ },
+ addPatchEntry: function(index, patcher)
+ {
+ Debug.assert(index > 0);
+ //
+ // Check if already un-marshalled the object. If that's the case,
+ // just patch the object smart pointer and we're done.
+ //
+ var obj = this._unmarshaledMap.get(index);
+ if(obj !== undefined && obj !== null)
+ {
+ patcher.call(null, obj);
+ return;
+ }
+
+ if(this._patchMap === null) // Lazy initialization
+ {
+ this._patchMap = new HashMap(); // HashMap<Integer, Patcher[] >();
+ }
+
+ //
+ // Add patch entry if the object isn't un-marshalled yet,
+ // the smart pointer will be patched when the instance is
+ // un-marshalled.
+ //
+ var l = this._patchMap.get(index);
+ if(l === undefined)
+ {
+ //
+ // We have no outstanding instances to be patched for this
+ // index, so make a new entry in the patch map.
+ //
+ l = []; // Patcher[];
+ this._patchMap.set(index, l);
+ }
+
+ //
+ // Append a patch entry for this instance.
+ //
+ l.push(patcher);
+ },
+ unmarshal: function(index, v)
+ {
+ var i, length, l;
+ //
+ // Add the object to the map of un-marshalled objects, this must
+ // be done before reading the objects (for circular references).
+ //
+ this._unmarshaledMap.set(index, v);
+
+ //
+ // Read the object.
+ //
+ v.__read(this._stream);
+ if(this._patchMap !== null)
+ {
+ //
+ // Patch all instances now that the object is un-marshalled.
+ //
+ l = this._patchMap.get(index);
+ if(l !== undefined)
+ {
+ Debug.assert(l.length > 0);
+ //
+ // Patch all pointers that refer to the instance.
+ //
+ for(i = 0, length = l.length; i < length; ++i)
+ {
+ l[i](v);
+ }
+ //
+ // Clear out the patch map for that index -- there is nothing left
+ // to patch for that index for the time being.
+ //
+ this._patchMap.delete(index);
+ }
+ }
+
+ if((this._patchMap === null || this._patchMap.size === 0) && this._objectList === null)
+ {
+ try
+ {
+ v.ice_postUnmarshal();
+ }
+ catch(ex)
+ {
+ this._stream.instance.initializationData().logger.warning("exception raised by ice_postUnmarshal:\n" +
+ ExUtil.toString(ex));
+ }
+ }
+ else
+ {
+ if(this._objectList === null) // Lazy initialization
+ {
+ this._objectList = []; // Ice.Object[]
+ }
+ this._objectList.push(v);
+
+ if(this._patchMap === null || this._patchMap.size === 0)
+ {
+ //
+ // Iterate over the object list and invoke ice_postUnmarshal on
+ // each object. We must do this after all objects have been
+ // unmarshaled in order to ensure that any object data members
+ // have been properly patched.
+ //
+ for(i = 0, length = this._objectList.length; i < length; i++)
+ {
+ try
+ {
+ this._objectList[i].ice_postUnmarshal();
+ }
+ catch(ex)
+ {
+ this._stream.instance.initializationData().logger.warning(
+ "exception raised by ice_postUnmarshal:\n" + ExUtil.toString(ex));
+ }
+ }
+ this._objectList = [];
+ }
+ }
+ }
+ });
+
+ var EncapsDecoder10 = Class(EncapsDecoder, {
+ __init__: function(stream, encaps, sliceObjects, f)
+ {
+ EncapsDecoder.call(this, stream, encaps, sliceObjects, f);
+ this._sliceType = SliceType.NoSlice;
+ },
+ readObject: function(patcher)
+ {
+ Debug.assert(patcher !== null);
+
+ //
+ // Object references are encoded as a negative integer in 1.0.
+ //
+ var index = this._stream.readInt();
+ if(index > 0)
+ {
+ throw new Ice.MarshalException("invalid object id");
+ }
+ index = -index;
+
+ if(index === 0)
+ {
+ patcher.call(null, null);
+ }
+ else
+ {
+ this.addPatchEntry(index, patcher);
+ }
+ },
+ throwException: function()
+ {
+ Debug.assert(this._sliceType === SliceType.NoSlice);
+
+ //
+ // User exception with the 1.0 encoding start with a boolean flag
+ // that indicates whether or not the exception has classes.
+ //
+ // This allows reading the pending objects even if some part of
+ // the exception was sliced.
+ //
+ var usesClasses = this._stream.readBool();
+ this._sliceType = SliceType.ExceptionSlice;
+ this._skipFirstSlice = false;
+
+ //
+ // Read the first slice header.
+ //
+ this.startSlice();
+ var mostDerivedId = this._typeId;
+ while(true)
+ {
+ var userEx = this._stream.createUserException(this._typeId);
+
+ //
+ // We found the exception.
+ //
+ if(userEx !== null)
+ {
+ userEx.__read(this._stream);
+ if(usesClasses)
+ {
+ this.readPendingObjects();
+ }
+ throw userEx;
+
+ // Never reached.
+ }
+
+ //
+ // Slice off what we don't understand.
+ //
+ this.skipSlice();
+ try
+ {
+ this.startSlice();
+ }
+ catch(ex)
+ {
+ //
+ // An oversight in the 1.0 encoding means there is no marker to indicate
+ // the last slice of an exception. As a result, we just try to read the
+ // next type ID, which raises UnmarshalOutOfBoundsException when the
+ // input buffer underflows.
+ //
+ // Set the reason member to a more helpful message.
+ //
+ if(ex instanceof Ice.UnmarshalOutOfBoundsException)
+ {
+ ex.reason = "unknown exception type `" + mostDerivedId + "'";
+ }
+ throw ex;
+ }
+ }
+ },
+ startInstance: function(sliceType)
+ {
+ Debug.assert(this._sliceType === sliceType);
+ this._skipFirstSlice = true;
+ },
+ endInstance: function(/*preserve*/)
+ {
+ var sz;
+ //
+ // Read the Ice::Object slice.
+ //
+ if(this._sliceType === SliceType.ObjectSlice)
+ {
+ this.startSlice();
+ sz = this._stream.readSize(); // For compatibility with the old AFM.
+ if(sz !== 0)
+ {
+ throw new Ice.MarshalException("invalid Object slice");
+ }
+ this.endSlice();
+ }
+
+ this._sliceType = SliceType.NoSlice;
+ return null;
+ },
+ startSlice: function()
+ {
+ var isIndex;
+ //
+ // If first slice, don't read the header, it was already read in
+ // readInstance or throwException to find the factory.
+ //
+ if(this._skipFirstSlice)
+ {
+ this._skipFirstSlice = false;
+ return this._typeId;
+ }
+
+ //
+ // For objects, first read the type ID boolean which indicates
+ // whether or not the type ID is encoded as a string or as an
+ // index. For exceptions, the type ID is always encoded as a
+ // string.
+ //
+ if(this._sliceType === SliceType.ObjectSlice) // For exceptions, the type ID is always encoded as a string
+ {
+ isIndex = this._stream.readBool();
+ this._typeId = this.readTypeId(isIndex);
+ }
+ else
+ {
+ this._typeId = this._stream.readString();
+ }
+
+ this._sliceSize = this._stream.readInt();
+ if(this._sliceSize < 4)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+
+ return this._typeId;
+ },
+ endSlice: function()
+ {
+ },
+ skipSlice: function()
+ {
+ if(this._stream.instance.traceLevels().slicing > 0)
+ {
+ var logger = this._stream.instance.initializationData().logger;
+ if(this._sliceType === SliceType.ObjectSlice)
+ {
+ TraceUtil.traceSlicing("object", this._typeId, this._stream.instance.traceLevels().slicingCat, logger);
+ }
+ else
+ {
+ TraceUtil.traceSlicing("exception", this._typeId, this._stream.instance.traceLevels().slicingCat, logger);
+ }
+ }
+ Debug.assert(this._sliceSize >= 4);
+ this._stream.skip(this._sliceSize - 4);
+ },
+ readPendingObjects: function()
+ {
+ var k, num;
+ do
+ {
+ num = this._stream.readSize();
+ for(k = num; k > 0; --k)
+ {
+ this.readInstance();
+ }
+ }
+ while(num > 0);
+
+ if(this._patchMap !== null && this._patchMap.size !== 0)
+ {
+ //
+ // If any entries remain in the patch map, the sender has sent an index for an object, but failed
+ // to supply the object.
+ //
+ throw new Ice.MarshalException("index for class received, but no instance");
+ }
+ },
+ readInstance: function()
+ {
+ var index = this._stream.readInt(),
+ mostDerivedId,
+ v = null;
+
+ if(index <= 0)
+ {
+ throw new Ice.MarshalException("invalid object id");
+ }
+
+ this._sliceType = SliceType.ObjectSlice;
+ this._skipFirstSlice = false;
+
+ //
+ // Read the first slice header.
+ //
+ this.startSlice();
+ mostDerivedId = this._typeId;
+ while(true)
+ {
+ //
+ // For the 1.0 encoding, the type ID for the base Object class
+ // marks the last slice.
+ //
+ if(this._typeId == IceObject.ice_staticId())
+ {
+ throw new Ice.NoObjectFactoryException("", mostDerivedId);
+ }
+
+ v = this.newInstance(this._typeId);
+
+ //
+ // We found a factory, we get out of this loop.
+ //
+ if(v)
+ {
+ break;
+ }
+
+ //
+ // If object slicing is disabled, stop un-marshalling.
+ //
+ if(!this._sliceObjects)
+ {
+ throw new Ice.NoObjectFactoryException("object slicing is disabled", this._typeId);
+ }
+
+ //
+ // Slice off what we don't understand.
+ //
+ this.skipSlice();
+ this.startSlice(); // Read next Slice header for next iteration.
+ }
+
+ //
+ // Un-marshal the object and add-it to the map of un-marshaled objects.
+ //
+ this.unmarshal(index, v);
+ }
+ });
+
+ var EncapsDecoder11 = Class(EncapsDecoder, {
+ __init__: function(stream, encaps, sliceObjects, f)
+ {
+ EncapsDecoder.call(this, stream, encaps, sliceObjects, f);
+ this._current = null;
+ this._objectIdIndex = 1;
+ },
+ readObject: function(patcher)
+ {
+ Debug.assert(patcher !== undefined);
+ var index = this._stream.readSize();
+
+ if(index < 0)
+ {
+ throw new Ice.MarshalException("invalid object id");
+ }
+
+ if(index === 0)
+ {
+ if(patcher !== null)
+ {
+ patcher.call(null, null);
+ }
+ }
+ else if(this._current !== null && (this._current.sliceFlags & FLAG_HAS_INDIRECTION_TABLE) !== 0)
+ {
+ //
+ // When reading an object within a slice and there's an
+ // indirect object table, always read an indirect reference
+ // that points to an object from the indirect object table
+ // marshaled at the end of the Slice.
+ //
+ // Maintain a list of indirect references. Note that the
+ // indirect index starts at 1, so we decrement it by one to
+ // derive an index into the indirection table that we'll read
+ // at the end of the slice.
+ //
+ if(patcher !== null)
+ {
+ if(this._current.indirectPatchList === null) // Lazy initialization
+ {
+ this._current.indirectPatchList = []; // IndirectPatchEntry[]
+ }
+ var e = new IndirectPatchEntry();
+ e.index = index - 1;
+ e.patcher = patcher;
+ this._current.indirectPatchList.push(e);
+ }
+ }
+ else
+ {
+ this.readInstance(index, patcher);
+ }
+ },
+ throwException: function()
+ {
+ Debug.assert(this._current === null);
+ this.push(SliceType.ExceptionSlice);
+
+ //
+ // Read the first slice header.
+ //
+ this.startSlice();
+ var mostDerivedId = this._current.typeId;
+ while(true)
+ {
+
+ var userEx = this._stream.createUserException(this._current.typeId);
+
+ //
+ // We found the exception.
+ //
+ if(userEx !== null)
+ {
+ userEx.__read(this._stream);
+ throw userEx;
+
+ // Never reached.
+ }
+
+ //
+ // Slice off what we don't understand.
+ //
+ this.skipSlice();
+
+ if((this._current.sliceFlags & FLAG_IS_LAST_SLICE) !== 0)
+ {
+ if(mostDerivedId.indexOf("::") === 0)
+ {
+ throw new Ice.UnknownUserException(mostDerivedId.substr(2));
+ }
+ throw new Ice.UnknownUserException(mostDerivedId);
+ }
+
+ this.startSlice();
+ }
+ },
+ startInstance: function(sliceType)
+ {
+ Debug.assert(sliceType !== undefined);
+ Debug.assert(this._current.sliceType !== null && this._current.sliceType === sliceType);
+ this._current.skipFirstSlice = true;
+ },
+ endInstance: function(preserve)
+ {
+ var slicedData = null;
+ if(preserve)
+ {
+ slicedData = this.readSlicedData();
+ }
+ if(this._current.slices !== null)
+ {
+ this._current.slices.length = 0; // Clear the array.
+ this._current.indirectionTables.length = 0; // Clear the array.
+ }
+ this._current = this._current.previous;
+ return slicedData;
+ },
+ startSlice: function()
+ {
+ //
+ // If first slice, don't read the header, it was already read in
+ // readInstance or throwException to find the factory.
+ //
+ if(this._current.skipFirstSlice)
+ {
+ this._current.skipFirstSlice = false;
+ return this._current.typeId;
+ }
+
+ this._current.sliceFlags = this._stream.readByte();
+
+ //
+ // Read the type ID, for object slices the type ID is encoded as a
+ // string or as an index, for exceptions it's always encoded as a
+ // string.
+ //
+ if(this._current.sliceType === SliceType.ObjectSlice)
+ {
+ if((this._current.sliceFlags & FLAG_HAS_TYPE_ID_COMPACT) === FLAG_HAS_TYPE_ID_COMPACT) // Must be checked 1st!
+ {
+ this._current.typeId = "";
+ this._current.compactId = this._stream.readSize();
+ }
+ else if((this._current.sliceFlags & (FLAG_HAS_TYPE_ID_INDEX | FLAG_HAS_TYPE_ID_STRING)) !== 0)
+ {
+ this._current.typeId = this.readTypeId((this._current.sliceFlags & FLAG_HAS_TYPE_ID_INDEX) !== 0);
+ this._current.compactId = -1;
+ }
+ else
+ {
+ // Only the most derived slice encodes the type ID for the compact format.
+ this._current.typeId = "";
+ this._current.compactId = -1;
+ }
+ }
+ else
+ {
+ this._current.typeId = this._stream.readString();
+ this._current.compactId = -1;
+ }
+
+ //
+ // Read the slice size if necessary.
+ //
+ if((this._current.sliceFlags & FLAG_HAS_SLICE_SIZE) !== 0)
+ {
+ this._current.sliceSize = this._stream.readInt();
+ if(this._current.sliceSize < 4)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ }
+ else
+ {
+ this._current.sliceSize = 0;
+ }
+ return this._current.typeId;
+ },
+ endSlice: function()
+ {
+ var e,
+ i,
+ indirectionTable = [],
+ length;
+
+ if((this._current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) !== 0)
+ {
+ this._stream.skipOpts();
+ }
+
+ //
+ // Read the indirection table if one is present and transform the
+ // indirect patch list into patch entries with direct references.
+ //
+ if((this._current.sliceFlags & FLAG_HAS_INDIRECTION_TABLE) !== 0)
+ {
+ //
+ // The table is written as a sequence<size> to conserve space.
+ //
+ length = this._stream.readAndCheckSeqSize(1);
+ for(i = 0; i < length; ++i)
+ {
+ indirectionTable[i] = this.readInstance(this._stream.readSize(), null);
+ }
+
+ //
+ // Sanity checks. If there are optional members, it's possible
+ // that not all object references were read if they are from
+ // unknown optional data members.
+ //
+ if(indirectionTable.length === 0)
+ {
+ throw new Ice.MarshalException("empty indirection table");
+ }
+ if((this._current.indirectPatchList === null || this._current.indirectPatchList.length === 0) &&
+ (this._current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) === 0)
+ {
+ throw new Ice.MarshalException("no references to indirection table");
+ }
+
+ //
+ // Convert indirect references into direct references.
+ //
+ if(this._current.indirectPatchList !== null)
+ {
+ for(i = 0, length = this._current.indirectPatchList.length; i < length; ++i)
+ {
+ e = this._current.indirectPatchList[i];
+ Debug.assert(e.index >= 0);
+ if(e.index >= indirectionTable.length)
+ {
+ throw new Ice.MarshalException("indirection out of range");
+ }
+ this.addPatchEntry(indirectionTable[e.index], e.patcher);
+ }
+ this._current.indirectPatchList.length = 0;
+ }
+ }
+ },
+ skipSlice: function()
+ {
+ if(this._stream.instance.traceLevels().slicing > 0)
+ {
+ var logger = this._stream.instance.initializationData().logger;
+ var slicingCat = this._stream.instance.traceLevels().slicingCat;
+ if(this._current.sliceType === SliceType.ExceptionSlice)
+ {
+ TraceUtil.traceSlicing("exception", this._current.typeId, slicingCat, logger);
+ }
+ else
+ {
+ TraceUtil.traceSlicing("object", this._current.typeId, slicingCat, logger);
+ }
+ }
+
+ var start = this._stream.pos;
+
+ if((this._current.sliceFlags & FLAG_HAS_SLICE_SIZE) !== 0)
+ {
+ Debug.assert(this._current.sliceSize >= 4);
+ this._stream.skip(this._current.sliceSize - 4);
+ }
+ else
+ {
+ if(this._current.sliceType === SliceType.ObjectSlice)
+ {
+ throw new Ice.NoObjectFactoryException(
+ "compact format prevents slicing (the sender should use the sliced format instead)",
+ this._current.typeId);
+ }
+
+ if(this._current.typeId.indexOf("::") === 0)
+ {
+ throw new Ice.UnknownUserException(this._current.typeId.substring(2));
+ }
+
+ throw new Ice.UnknownUserException(this._current.typeId);
+ }
+
+ //
+ // Preserve this slice.
+ //
+ var info = new Ice.SliceInfo();
+ info.typeId = this._current.typeId;
+ info.compactId = this._current.compactId;
+ info.hasOptionalMembers = (this._current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) !== 0;
+ info.isLastSlice = (this._current.sliceFlags & FLAG_IS_LAST_SLICE) !== 0;
+
+ var b = this._stream._buf;
+ var end = b.position;
+ var dataEnd = end;
+ if(info.hasOptionalMembers)
+ {
+ //
+ // Don't include the optional member end marker. It will be re-written by
+ // endSlice when the sliced data is re-written.
+ //
+ --dataEnd;
+ }
+
+ b.position = start;
+ info.bytes = b.getArray(dataEnd - start);
+ b.position = end;
+
+ if(this._current.slices === null) // Lazy initialization
+ {
+ this._current.slices = []; // Ice.SliceInfo[]
+ this._current.indirectionTables = []; // int[]
+ }
+
+ //
+ // Read the indirect object table. We read the instances or their
+ // IDs if the instance is a reference to an already un-marhsaled
+ // object.
+ //
+ // The SliceInfo object sequence is initialized only if
+ // readSlicedData is called.
+ //
+
+ if((this._current.sliceFlags & FLAG_HAS_INDIRECTION_TABLE) !== 0)
+ {
+ var length = this._stream.readAndCheckSeqSize(1);
+ var indirectionTable = [];
+ for(var i = 0; i < length; ++i)
+ {
+ indirectionTable[i] = this.readInstance(this._stream.readSize(), null);
+ }
+ this._current.indirectionTables.push(indirectionTable);
+ }
+ else
+ {
+ this._current.indirectionTables.push(null);
+ }
+ this._current.slices.push(info);
+ },
+ readOpt: function(readTag, expectedFormat)
+ {
+ if(this._current === null)
+ {
+ return this._stream.readOptImpl(readTag, expectedFormat);
+ }
+
+ if((this._current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) !== 0)
+ {
+ return this._stream.readOptImpl(readTag, expectedFormat);
+ }
+ return false;
+ },
+ readInstance: function(index, patcher)
+ {
+ Debug.assert(index > 0);
+
+ var mostDerivedId,
+ v = null;
+
+ if(index > 1)
+ {
+ if(patcher !== null)
+ {
+ this.addPatchEntry(index, patcher);
+ }
+ return index;
+ }
+
+ this.push(SliceType.ObjectSlice);
+
+ //
+ // Get the object ID before we start reading slices. If some
+ // slices are skiped, the indirect object table are still read and
+ // might read other objects.
+ //
+ index = ++this._objectIdIndex;
+
+ //
+ // Read the first slice header.
+ //
+ this.startSlice();
+ mostDerivedId = this._current.typeId;
+ while(true)
+ {
+ if(this._current.compactId >= 0)
+ {
+ //
+ // Translate a compact (numeric) type ID into a string type ID.
+ //
+ this._current.typeId = "";
+ if(this._current.typeId.length === 0)
+ {
+ this._current.typeId = this._stream.getTypeId(this._current.compactId);
+ }
+ }
+
+ if(this._current.typeId.length > 0)
+ {
+ v = this.newInstance(this._current.typeId);
+ //
+ // We found a factory, we get out of this loop.
+ //
+ if(v !== null && v !== undefined)
+ {
+ break;
+ }
+ }
+
+ //
+ // If object slicing is disabled, stop un-marshalling.
+ //
+ if(!this._sliceObjects)
+ {
+ throw new Ice.NoObjectFactoryException("object slicing is disabled", this._current.typeId);
+ }
+
+ //
+ // Slice off what we don't understand.
+ //
+ this.skipSlice();
+ //
+ // If this is the last slice, keep the object as an opaque
+ // UnknownSlicedData object.
+ //
+ if((this._current.sliceFlags & FLAG_IS_LAST_SLICE) !== 0)
+ {
+ v = new Ice.UnknownSlicedObject(mostDerivedId);
+ break;
+ }
+
+ this.startSlice(); // Read next Slice header for next iteration.
+ }
+
+ //
+ // Un-marshal the object
+ //
+ this.unmarshal(index, v);
+ if(this._current === null && this._patchMap !== null && this._patchMap.size !== 0)
+ {
+ //
+ // If any entries remain in the patch map, the sender has sent an index for an object, but failed
+ // to supply the object.
+ //
+ throw new Ice.MarshalException("index for class received, but no instance");
+ }
+
+ if(patcher !== null)
+ {
+ patcher.call(null, v);
+ }
+ return index;
+ },
+ readSlicedData: function()
+ {
+ var i, ii, table, info, j, jj;
+
+ if(this._current.slices === null) // No preserved slices.
+ {
+ return null;
+ }
+ //
+ // The _indirectionTables member holds the indirection table for each slice
+ // in _slices.
+ //
+ Debug.assert(this._current.slices.length === this._current.indirectionTables.length);
+ for(i = 0, ii = this._current.slices.length; i < ii; ++i)
+ {
+ //
+ // We use the "objects" list in SliceInfo to hold references
+ // to the target objects. Note that the objects might not have
+ // been read yet in the case of a circular reference to an
+ // enclosing object.
+ //
+ table = this._current.indirectionTables[i];
+ info = this._current.slices[i];
+ info.objects = [];
+ jj = table ? table.length : 0;
+ for(j = 0; j < jj; ++j)
+ {
+ this.addPatchEntry(table[j], sequencePatcher(info.objects, j, IceObject));
+ }
+ }
+ return new SlicedData(ArrayUtil.clone(this._current.slices));
+ },
+ push: function(sliceType)
+ {
+ if(this._current === null)
+ {
+ this._current = new EncapsDecoder11.InstanceData(null);
+ }
+ else
+ {
+ this._current = !this._current.next ? new EncapsDecoder11.InstanceData(this._current) : this._current.next;
+ }
+ this._current.sliceType = sliceType;
+ this._current.skipFirstSlice = false;
+ }
+ });
+
+ EncapsDecoder11.InstanceData = function(previous)
+ {
+ if(previous !== null)
+ {
+ previous.next = this;
+ }
+ this.previous = previous;
+ this.next = null;
+
+ // Instance attributes
+ this.sliceType = null;
+ this.skipFirstSlice = false;
+ this.slices = null; // Preserved slices. Ice.SliceInfo[]
+ this.indirectionTables = null; // int[]
+
+ // Slice attributes
+ this.sliceFlags = 0;
+ this.sliceSize = 0;
+ this.typeId = null;
+ this.compactId = 0;
+ this.indirectPatchList = null; // Lazy initialized, IndirectPatchEntry[]
+ };
+
+ var sequencePatcher = function(seq, index, T){
+ return function(v)
+ {
+ if(v !== null && !(v instanceof T))
+ {
+ ExUtil.throwUOE(T.ice_staticId(), v);
+ }
+ seq[index] = v;
+ };
+ };
+
+ var EncapsEncoder = Class({
+ __init__: function(stream, encaps)
+ {
+ this._stream = stream;
+ this._encaps = encaps;
+ this._marshaledMap = new HashMap(); // HashMap<Ice.Object, int>;
+ this._typeIdMap = null; // Lazy initialized. HashMap<String, int>
+ this._typeIdIndex = 0;
+ },
+ writeOpt: function()
+ {
+ return false;
+ },
+ writePendingObjects: function()
+ {
+ return undefined;
+ },
+ registerTypeId: function(typeId)
+ {
+ if(this._typeIdMap === null) // Lazy initialization
+ {
+ this._typeIdMap = new HashMap(); // HashMap<String, int>
+ }
+
+ var p = this._typeIdMap.get(typeId);
+ if(p !== undefined)
+ {
+ return p;
+ }
+ this._typeIdMap.set(typeId, ++this._typeIdIndex);
+ return -1;
+ }
+ });
+
+ var EncapsEncoder10 = Class(EncapsEncoder, {
+ __init__: function(stream, encaps)
+ {
+ EncapsEncoder.call(this, stream, encaps);
+ // Instance attributes
+ this._sliceType = SliceType.NoSlice;
+ this._writeSlice = 0; // Position of the slice data members
+ // Encapsulation attributes for object marshalling.
+ this._objectIdIndex = 0;
+ this._toBeMarshaledMap = new HashMap(); // HashMap<Ice.Object, Integer>();
+ },
+ writeObject: function(v)
+ {
+ Debug.assert(v !== undefined);
+ //
+ // Object references are encoded as a negative integer in 1.0.
+ //
+ if(v !== null)
+ {
+ this._stream.writeInt(-this.registerObject(v));
+ }
+ else
+ {
+ this._stream.writeInt(0);
+ }
+ },
+ writeUserException: function(v)
+ {
+ Debug.assert(v !== null && v !== undefined);
+ //
+ // User exception with the 1.0 encoding start with a boolean
+ // flag that indicates whether or not the exception uses
+ // classes.
+ //
+ // This allows reading the pending objects even if some part of
+ // the exception was sliced.
+ //
+ var usesClasses = v.__usesClasses();
+ this._stream.writeBool(usesClasses);
+ v.__write(this._stream);
+ if(usesClasses)
+ {
+ this.writePendingObjects();
+ }
+ },
+ startInstance: function(sliceType)
+ {
+ this._sliceType = sliceType;
+ },
+ endInstance: function()
+ {
+ if(this._sliceType === SliceType.ObjectSlice)
+ {
+ //
+ // Write the Object slice.
+ //
+ this.startSlice(IceObject.ice_staticId(), -1, true);
+ this._stream.writeSize(0); // For compatibility with the old AFM.
+ this.endSlice();
+ }
+ this._sliceType = SliceType.NoSlice;
+ },
+ startSlice: function(typeId)
+ {
+ //
+ // For object slices, encode a boolean to indicate how the type ID
+ // is encoded and the type ID either as a string or index. For
+ // exception slices, always encode the type ID as a string.
+ //
+ if(this._sliceType === SliceType.ObjectSlice)
+ {
+ var index = this.registerTypeId(typeId);
+ if(index < 0)
+ {
+ this._stream.writeBool(false);
+ this._stream.writeString(typeId);
+ }
+ else
+ {
+ this._stream.writeBool(true);
+ this._stream.writeSize(index);
+ }
+ }
+ else
+ {
+ this._stream.writeString(typeId);
+ }
+
+ this._stream.writeInt(0); // Placeholder for the slice length.
+
+ this._writeSlice = this._stream.pos;
+ },
+ endSlice: function()
+ {
+ //
+ // Write the slice length.
+ //
+ var sz = this._stream.pos - this._writeSlice + 4;
+ this._stream.rewriteInt(sz, this._writeSlice - 4);
+ },
+ writePendingObjects: function()
+ {
+ var self = this,
+ writeCB = function(key, value)
+ {
+ //
+ // Ask the instance to marshal itself. Any new class
+ // instances that are triggered by the classes marshaled
+ // are added to toBeMarshaledMap.
+ //
+ self._stream.writeInt(value);
+
+ try
+ {
+ key.ice_preMarshal();
+ }
+ catch(ex)
+ {
+ self._stream.instance.initializationData().logger.warning(
+ "exception raised by ice_preMarshal:\n" + ExUtil.toString(ex));
+ }
+
+ key.__write(self._stream);
+ },
+ savedMap;
+
+ while(this._toBeMarshaledMap.size > 0)
+ {
+ //
+ // Consider the to be marshalled objects as marshalled now,
+ // this is necessary to avoid adding again the "to be
+ // marshalled objects" into _toBeMarshaledMap while writing
+ // objects.
+ //
+ this._marshaledMap.merge(this._toBeMarshaledMap);
+
+ savedMap = this._toBeMarshaledMap;
+ this._toBeMarshaledMap = new HashMap(); // HashMap<Ice.Object, int>();
+ this._stream.writeSize(savedMap.size);
+ savedMap.forEach(writeCB);
+ }
+ this._stream.writeSize(0); // Zero marker indicates end of sequence of sequences of instances.
+ },
+ registerObject: function(v)
+ {
+ Debug.assert(v !== null);
+
+ //
+ // Look for this instance in the to-be-marshaled map.
+ //
+ var p = this._toBeMarshaledMap.get(v);
+ if(p !== undefined)
+ {
+ return p;
+ }
+
+ //
+ // Didn't find it, try the marshaled map next.
+ //
+ p = this._marshaledMap.get(v);
+ if(p !== undefined)
+ {
+ return p;
+ }
+
+ //
+ // We haven't seen this instance previously, create a new
+ // index, and insert it into the to-be-marshaled map.
+ //
+ this._toBeMarshaledMap.set(v, ++this._objectIdIndex);
+ return this._objectIdIndex;
+ }
+ });
+
+ var EncapsEncoder11 = Class(EncapsEncoder, {
+ __init__: function(stream, encaps)
+ {
+ EncapsEncoder.call(this, stream, encaps);
+ this._current = null;
+ this._objectIdIndex = 1;
+ },
+ writeObject: function(v)
+ {
+ Debug.assert(v !== undefined);
+ var index, idx;
+ if(v === null)
+ {
+ this._stream.writeSize(0);
+ }
+ else if(this._current !== null && this._encaps.format === FormatType.SlicedFormat)
+ {
+ if(this._current.indirectionTable === null) // Lazy initialization
+ {
+ this._current.indirectionTable = []; // Ice.Object[]
+ this._current.indirectionMap = new HashMap(); // HashMap<Ice.Object, int>
+ }
+
+ //
+ // If writting an object within a slice and using the sliced
+ // format, write an index from the object indirection
+ // table. The indirect object table is encoded at the end of
+ // each slice and is always read (even if the Slice is
+ // unknown).
+ //
+ index = this._current.indirectionMap.get(v);
+ if(index === undefined)
+ {
+ this._current.indirectionTable.push(v);
+ idx = this._current.indirectionTable.length; // Position + 1 (0 is reserved for nil)
+ this._current.indirectionMap.set(v, idx);
+ this._stream.writeSize(idx);
+ }
+ else
+ {
+ this._stream.writeSize(index);
+ }
+ }
+ else
+ {
+ this.writeInstance(v); // Write the instance or a reference if already marshaled.
+ }
+ },
+ writePendingObjects: function()
+ {
+ return undefined;
+ },
+ writeUserException: function(v)
+ {
+ Debug.assert(v !== null && v !== undefined);
+ v.__write(this._stream);
+ },
+ startInstance: function(sliceType, data)
+ {
+ if(this._current === null)
+ {
+ this._current = new EncapsEncoder11.InstanceData(null);
+ }
+ else
+ {
+ this._current = (this._current.next === null) ? new EncapsEncoder11.InstanceData(this._current) : this._current.next;
+ }
+ this._current.sliceType = sliceType;
+ this._current.firstSlice = true;
+
+ if(data !== null && data !== undefined)
+ {
+ this.writeSlicedData(data);
+ }
+ },
+ endInstance: function()
+ {
+ this._current = this._current.previous;
+ },
+ startSlice: function(typeId, compactId, last)
+ {
+ Debug.assert((this._current.indirectionTable === null || this._current.indirectionTable.length === 0) &&
+ (this._current.indirectionMap === null || this._current.indirectionMap.size === 0));
+
+ this._current.sliceFlagsPos = this._stream.pos;
+
+ this._current.sliceFlags = 0;
+ if(this._encaps.format === FormatType.SlicedFormat)
+ {
+ this._current.sliceFlags |= FLAG_HAS_SLICE_SIZE; // Encode the slice size if using the sliced format.
+ }
+ if(last)
+ {
+ this._current.sliceFlags |= FLAG_IS_LAST_SLICE; // This is the last slice.
+ }
+
+ this._stream.writeByte(0); // Placeholder for the slice flags
+
+ //
+ // For object slices, encode the flag and the type ID either as a
+ // string or index. For exception slices, always encode the type
+ // ID a string.
+ //
+ if(this._current.sliceType === SliceType.ObjectSlice)
+ {
+ //
+ // Encode the type ID (only in the first slice for the compact
+ // encoding).
+ //
+ if(this._encaps.format === FormatType.SlicedFormat || this._current.firstSlice)
+ {
+ if(compactId >= 0)
+ {
+ this._current.sliceFlags |= FLAG_HAS_TYPE_ID_COMPACT;
+ this._stream.writeSize(compactId);
+ }
+ else
+ {
+ var index = this.registerTypeId(typeId);
+ if(index < 0)
+ {
+ this._current.sliceFlags |= FLAG_HAS_TYPE_ID_STRING;
+ this._stream.writeString(typeId);
+ }
+ else
+ {
+ this._current.sliceFlags |= FLAG_HAS_TYPE_ID_INDEX;
+ this._stream.writeSize(index);
+ }
+ }
+ }
+ }
+ else
+ {
+ this._stream.writeString(typeId);
+ }
+
+ if((this._current.sliceFlags & FLAG_HAS_SLICE_SIZE) !== 0)
+ {
+ this._stream.writeInt(0); // Placeholder for the slice length.
+ }
+
+ this._current.writeSlice = this._stream.pos;
+ this._current.firstSlice = false;
+ },
+ endSlice: function()
+ {
+ var sz, i, length;
+
+ //
+ // Write the optional member end marker if some optional members
+ // were encoded. Note that the optional members are encoded before
+ // the indirection table and are included in the slice size.
+ //
+ if((this._current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) !== 0)
+ {
+ this._stream.writeByte(OPTIONAL_END_MARKER);
+ }
+
+ //
+ // Write the slice length if necessary.
+ //
+ if((this._current.sliceFlags & FLAG_HAS_SLICE_SIZE) !== 0)
+ {
+ sz = this._stream.pos - this._current.writeSlice + 4;
+ this._stream.rewriteInt(sz, this._current.writeSlice - 4);
+ }
+
+ //
+ // Only write the indirection table if it contains entries.
+ //
+ if(this._current.indirectionTable !== null && this._current.indirectionTable.length !== 0)
+ {
+ Debug.assert(this._encaps.format === FormatType.SlicedFormat);
+ this._current.sliceFlags |= FLAG_HAS_INDIRECTION_TABLE;
+
+ //
+ // Write the indirection object table.
+ //
+ this._stream.writeSize(this._current.indirectionTable.length);
+ for(i = 0, length = this._current.indirectionTable.length; i < length; ++i)
+ {
+ this.writeInstance(this._current.indirectionTable[i]);
+ }
+ this._current.indirectionTable.length = 0; // Faster way to clean array in JavaScript
+ this._current.indirectionMap.clear();
+ }
+
+ //
+ // Finally, update the slice flags.
+ //
+ this._stream.rewriteByte(this._current.sliceFlags, this._current.sliceFlagsPos);
+ },
+ writeOpt: function(tag, format)
+ {
+ if(this._current === null)
+ {
+ return this._stream.writeOptImpl(tag, format);
+ }
+
+ if(this._stream.writeOptImpl(tag, format))
+ {
+ this._current.sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS;
+ return true;
+ }
+
+ return false;
+ },
+ writeSlicedData: function(slicedData)
+ {
+ Debug.assert(slicedData !== null && slicedData !== undefined);
+
+ //
+ // We only remarshal preserved slices if we are using the sliced
+ // format. Otherwise, we ignore the preserved slices, which
+ // essentially "slices" the object into the most-derived type
+ // known by the sender.
+ //
+ if(this._encaps.format !== FormatType.SlicedFormat)
+ {
+ return;
+ }
+
+ var i, ii, info,
+ j, jj;
+
+ for(i = 0, ii = slicedData.slices.length; i < ii; ++i)
+ {
+ info = slicedData.slices[i];
+ this.startSlice(info.typeId, info.compactId, info.isLastSlice);
+
+ //
+ // Write the bytes associated with this slice.
+ //
+ this._stream.writeBlob(info.bytes);
+
+ if(info.hasOptionalMembers)
+ {
+ this._current.sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS;
+ }
+
+ //
+ // Make sure to also re-write the object indirection table.
+ //
+ if(info.objects !== null && info.objects.length > 0)
+ {
+ if(this._current.indirectionTable === null) // Lazy initialization
+ {
+ this._current.indirectionTable = []; // Ice.Object[]
+ this._current.indirectionMap = new HashMap(); // HashMap<Ice.Object, int>
+ }
+
+ for(j = 0, jj = info.objects.length; j < jj; ++j)
+ {
+ this._current.indirectionTable.push(info.objects[j]);
+ }
+ }
+
+ this.endSlice();
+ }
+ },
+ writeInstance: function(v)
+ {
+ Debug.assert(v !== null && v !== undefined);
+
+ //
+ // If the instance was already marshaled, just write it's ID.
+ //
+ var p = this._marshaledMap.get(v);
+ if(p !== undefined)
+ {
+ this._stream.writeSize(p);
+ return;
+ }
+
+ //
+ // We haven't seen this instance previously, create a new ID,
+ // insert it into the marshaled map, and write the instance.
+ //
+ this._marshaledMap.set(v, ++this._objectIdIndex);
+
+ try
+ {
+ v.ice_preMarshal();
+ }
+ catch(ex)
+ {
+ this._stream.instance.initializationData().logger.warning("exception raised by ice_preMarshal:\n" +
+ ExUtil.toString(ex));
+ }
+
+ this._stream.writeSize(1); // Object instance marker.
+ v.__write(this._stream);
+ }
+ });
+
+ EncapsEncoder11.InstanceData = function(previous)
+ {
+ Debug.assert(previous !== undefined);
+ if(previous !== null)
+ {
+ previous.next = this;
+ }
+ this.previous = previous;
+ this.next = null;
+
+ // Instance attributes
+ this.sliceType = null;
+ this.firstSlice = false;
+
+ // Slice attributes
+ this.sliceFlags = 0;
+ this.writeSlice = 0; // Position of the slice data members
+ this.sliceFlagsPos = 0; // Position of the slice flags
+ this.indirectionTable = null; // Ice.Object[]
+ this.indirectionMap = null; // HashMap<Ice.Object, int>
+ };
+
+ var ReadEncaps = Class({
+ __init__: function()
+ {
+ this.start = 0;
+ this.sz = 0;
+ this.encoding = null;
+ this.encoding_1_0 = false;
+ this.decoder = null;
+ this.next = null;
+ },
+ reset: function()
+ {
+ this.decoder = null;
+ },
+ setEncoding: function(encoding)
+ {
+ this.encoding = encoding;
+ this.encoding_1_0 = encoding.equals(Ice.Encoding_1_0);
+ }
+ });
+
+ var WriteEncaps = Class({
+ __init__: function()
+ {
+ this.start = 0;
+ this.format = FormatType.DefaultFormat;
+ this.encoding = null;
+ this.encoding_1_0 = false;
+ this.encoder = null;
+ this.next = null;
+ },
+ reset: function()
+ {
+ this.encoder = null;
+ },
+ setEncoding: function(encoding)
+ {
+ this.encoding = encoding;
+ this.encoding_1_0 = encoding.equals(Ice.Encoding_1_0);
+ }
+ });
+
+ var BasicStream = Class({
+ __init__: function(instance, encoding, unlimited, data)
+ {
+ this._instance = instance;
+ this._closure = null;
+ this._encoding = encoding;
+
+ this._readEncapsStack = null;
+ this._writeEncapsStack = null;
+ this._readEncapsCache = null;
+ this._writeEncapsCache = null;
+
+ this._sliceObjects = true;
+
+ this._messageSizeMax = this._instance.messageSizeMax(); // Cached for efficiency.
+ this._unlimited = unlimited !== undefined ? unlimited : false;
+
+ this._startSeq = -1;
+ this._sizePos = -1;
+
+ if(data !== undefined)
+ {
+ this._buf = new Ice.Buffer(data);
+ }
+ else
+ {
+ this._buf = new Ice.Buffer();
+ }
+ },
+ //
+ // This function allows this object to be reused, rather than
+ // reallocated.
+ //
+ reset: function()
+ {
+ this._buf.reset();
+ this.clear();
+ },
+ clear: function()
+ {
+ if(this._readEncapsStack !== null)
+ {
+ Debug.assert(this._readEncapsStack.next);
+ this._readEncapsStack.next = this._readEncapsCache;
+ this._readEncapsCache = this._readEncapsStack;
+ this._readEncapsCache.reset();
+ this._readEncapsStack = null;
+ }
+
+ if(this._writeEncapsStack !== null)
+ {
+ Debug.assert(this._writeEncapsStack.next);
+ this._writeEncapsStack.next = this._writeEncapsCache;
+ this._writeEncapsCache = this._writeEncapsStack;
+ this._writeEncapsCache.reset();
+ this._writeEncapsStack = null;
+ }
+ this._startSeq = -1;
+ this._sliceObjects = true;
+ },
+ swap: function(other)
+ {
+ Debug.assert(this._instance === other._instance);
+
+ var tmpBuf, tmpClosure, tmpUnlimited, tmpStartSeq, tmpMinSeqSize, tmpSizePos;
+
+ tmpBuf = other._buf;
+ other._buf = this._buf;
+ this._buf = tmpBuf;
+
+ tmpClosure = other._closure;
+ other._closure = this._closure;
+ this._closure = tmpClosure;
+
+ //
+ // Swap is never called for BasicStreams that have encapsulations being read/write. However,
+ // encapsulations might still be set in case marshalling or un-marshalling failed. We just
+ // reset the encapsulations if there are still some set.
+ //
+ this.resetEncaps();
+ other.resetEncaps();
+
+ tmpUnlimited = other._unlimited;
+ other._unlimited = this._unlimited;
+ this._unlimited = tmpUnlimited;
+
+ tmpStartSeq = other._startSeq;
+ other._startSeq = this._startSeq;
+ this._startSeq = tmpStartSeq;
+
+ tmpMinSeqSize = other._minSeqSize;
+ other._minSeqSize = this._minSeqSize;
+ this._minSeqSize = tmpMinSeqSize;
+
+ tmpSizePos = other._sizePos;
+ other._sizePos = this._sizePos;
+ this._sizePos = tmpSizePos;
+ },
+ resetEncaps: function()
+ {
+ this._readEncapsStack = null;
+ this._writeEncapsStack = null;
+ },
+ resize: function(sz)
+ {
+ //
+ // Check memory limit if stream is not unlimited.
+ //
+ if(!this._unlimited && sz > this._messageSizeMax)
+ {
+ ExUtil.throwMemoryLimitException(sz, this._messageSizeMax);
+ }
+
+ this._buf.resize(sz);
+ this._buf.position = sz;
+ },
+ prepareWrite: function()
+ {
+ this._buf.position = 0;
+ return this._buf;
+ },
+ startWriteObject: function(data)
+ {
+ Debug.assert(this._writeEncapsStack !== null && this._writeEncapsStack.encoder !== null);
+ this._writeEncapsStack.encoder.startInstance(SliceType.ObjectSlice, data);
+ },
+ endWriteObject: function()
+ {
+ Debug.assert(this._writeEncapsStack !== null && this._writeEncapsStack.encoder !== null);
+ this._writeEncapsStack.encoder.endInstance();
+ },
+ startReadObject: function()
+ {
+ Debug.assert(this._readEncapsStack !== null && this._readEncapsStack.decoder !== null);
+ this._readEncapsStack.decoder.startInstance(SliceType.ObjectSlice);
+ },
+ endReadObject: function(preserve)
+ {
+ Debug.assert(this._readEncapsStack !== null && this._readEncapsStack.decoder !== null);
+ return this._readEncapsStack.decoder.endInstance(preserve);
+ },
+ startWriteException: function(data)
+ {
+ Debug.assert(this._writeEncapsStack !== null && this._writeEncapsStack.encoder !== null);
+ this._writeEncapsStack.encoder.startInstance(SliceType.ExceptionSlice, data);
+ },
+ endWriteException: function()
+ {
+ Debug.assert(this._writeEncapsStack !== null && this._writeEncapsStack.encoder !== null);
+ this._writeEncapsStack.encoder.endInstance();
+ },
+ startReadException: function()
+ {
+ Debug.assert(this._readEncapsStack !== null && this._readEncapsStack.decoder !== null);
+ this._readEncapsStack.decoder.startInstance(SliceType.ExceptionSlice);
+ },
+ endReadException: function(preserve)
+ {
+ Debug.assert(this._readEncapsStack !== null && this._readEncapsStack.decoder !== null);
+ return this._readEncapsStack.decoder.endInstance(preserve);
+ },
+ startWriteEncaps: function(encoding, format)
+ {
+ //
+ // If no encoding version is specified, use the current write
+ // encapsulation encoding version if there's a current write
+ // encapsulation, otherwise, use the stream encoding version.
+ //
+
+ if(encoding === undefined)
+ {
+ if(this._writeEncapsStack !== null)
+ {
+ encoding = this._writeEncapsStack.encoding;
+ format = this._writeEncapsStack.format;
+ }
+ else
+ {
+ encoding = this._encoding;
+ format = FormatType.DefaultFormat;
+ }
+ }
+
+ Protocol.checkSupportedEncoding(encoding);
+
+ var curr = this._writeEncapsCache;
+ if(curr !== null)
+ {
+ curr.reset();
+ this._writeEncapsCache = this._writeEncapsCache.next;
+ }
+ else
+ {
+ curr = new WriteEncaps();
+ }
+ curr.next = this._writeEncapsStack;
+ this._writeEncapsStack = curr;
+
+ this._writeEncapsStack.format = format;
+ this._writeEncapsStack.setEncoding(encoding);
+ this._writeEncapsStack.start = this._buf.limit;
+
+ this.writeInt(0); // Placeholder for the encapsulation length.
+ this._writeEncapsStack.encoding.__write(this);
+ },
+ endWriteEncaps: function()
+ {
+ Debug.assert(this._writeEncapsStack);
+
+ // Size includes size and version.
+ var start = this._writeEncapsStack.start;
+
+ var sz = this._buf.limit - start;
+ this._buf.putIntAt(start, sz);
+
+ var curr = this._writeEncapsStack;
+ this._writeEncapsStack = curr.next;
+ curr.next = this._writeEncapsCache;
+ this._writeEncapsCache = curr;
+ this._writeEncapsCache.reset();
+ },
+ endWriteEncapsChecked: function() // Used by public stream API.
+ {
+ if(this._writeEncapsStack === null)
+ {
+ throw new Ice.EncapsulationException("not in an encapsulation");
+ }
+ this.endWriteEncaps();
+ },
+ writeEmptyEncaps: function(encoding)
+ {
+ Protocol.checkSupportedEncoding(encoding);
+ this.writeInt(6); // Size
+ encoding.__write(this);
+ },
+ writeEncaps: function(v)
+ {
+ if(v.length < 6)
+ {
+ throw new Ice.EncapsulationException();
+ }
+ this.expand(v.length);
+ this._buf.putArray(v);
+ },
+ getWriteEncoding: function()
+ {
+ return this._writeEncapsStack !== null ? this._writeEncapsStack.encoding : this._encoding;
+ },
+ startReadEncaps: function()
+ {
+ var curr = this._readEncapsCache;
+ if(curr !== null)
+ {
+ curr.reset();
+ this._readEncapsCache = this._readEncapsCache.next;
+ }
+ else
+ {
+ curr = new ReadEncaps();
+ }
+ curr.next = this._readEncapsStack;
+ this._readEncapsStack = curr;
+
+ this._readEncapsStack.start = this._buf.position;
+
+ //
+ // I don't use readSize() and writeSize() for encapsulations,
+ // because when creating an encapsulation, I must know in advance
+ // how many bytes the size information will require in the data
+ // stream. If I use an Int, it is always 4 bytes. For
+ // readSize()/writeSize(), it could be 1 or 5 bytes.
+ //
+ var sz = this.readInt();
+ if(sz < 6)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ if(sz - 4 > this._buf.remaining)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ this._readEncapsStack.sz = sz;
+
+ var encoding = new Ice.EncodingVersion();
+ encoding.__read(this);
+ Protocol.checkSupportedEncoding(encoding); // Make sure the encoding is supported.
+ this._readEncapsStack.setEncoding(encoding);
+
+ return encoding;
+ },
+ endReadEncaps: function()
+ {
+ Debug.assert(this._readEncapsStack !== null);
+
+ if(!this._readEncapsStack.encoding_1_0)
+ {
+ this.skipOpts();
+ if(this._buf.position !== this._readEncapsStack.start + this._readEncapsStack.sz)
+ {
+ throw new Ice.EncapsulationException();
+ }
+ }
+ else if(this._buf.position !== this._readEncapsStack.start + this._readEncapsStack.sz)
+ {
+ if(this._buf.position + 1 !== this._readEncapsStack.start + this._readEncapsStack.sz)
+ {
+ throw new Ice.EncapsulationException();
+ }
+
+ //
+ // Ice version < 3.3 had a bug where user exceptions with
+ // class members could be encoded with a trailing byte
+ // when dispatched with AMD. So we tolerate an extra byte
+ // in the encapsulation.
+ //
+
+ try
+ {
+ this._buf.get();
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ }
+
+ var curr = this._readEncapsStack;
+ this._readEncapsStack = curr.next;
+ curr.next = this._readEncapsCache;
+ this._readEncapsCache = curr;
+ this._readEncapsCache.reset();
+ },
+ skipEmptyEncaps: function(encoding)
+ {
+ Debug.assert(encoding !== undefined);
+ var sz = this.readInt();
+ if(sz !== 6)
+ {
+ throw new Ice.EncapsulationException();
+ }
+
+ var pos = this._buf.position;
+ if(pos + 2 > this._buf.limit)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+
+ if(encoding !== null)
+ {
+ encoding.__read(this);
+ }
+ else
+ {
+ this._buf.position = pos + 2;
+ }
+ },
+ endReadEncapsChecked: function() // Used by public stream API.
+ {
+ if(this._readEncapsStack === null)
+ {
+ throw new Ice.EncapsulationException("not in an encapsulation");
+ }
+ this.endReadEncaps();
+ },
+ readEncaps: function(encoding)
+ {
+ Debug.assert(encoding !== undefined);
+ var sz = this.readInt();
+ if(sz < 6)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+
+ if(sz - 4 > this._buf.remaining)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+
+ if(encoding !== null)
+ {
+ encoding.__read(this);
+ this._buf.position = this._buf.position - 6;
+ }
+ else
+ {
+ this._buf.position = this._buf.position - 4;
+ }
+
+ try
+ {
+ return this._buf.getArray(sz);
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ getReadEncoding: function()
+ {
+ return this._readEncapsStack !== null ? this._readEncapsStack.encoding : this._encoding;
+ },
+ getReadEncapsSize: function()
+ {
+ Debug.assert(this._readEncapsStack !== null);
+ return this._readEncapsStack.sz - 6;
+ },
+ skipEncaps: function()
+ {
+ var sz = this.readInt();
+ if(sz < 6)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ var encoding = new Ice.EncodingVersion();
+ encoding.__read(this);
+ try
+ {
+ this._buf.position = this._buf.position + sz - 6;
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ return encoding;
+ },
+ startWriteSlice: function(typeId, compactId, last)
+ {
+ Debug.assert(this._writeEncapsStack !== null && this._writeEncapsStack.encoder !== null);
+ this._writeEncapsStack.encoder.startSlice(typeId, compactId, last);
+ },
+ endWriteSlice: function()
+ {
+ Debug.assert(this._writeEncapsStack !== null && this._writeEncapsStack.encoder !== null);
+ this._writeEncapsStack.encoder.endSlice();
+ },
+ startReadSlice: function() // Returns type ID of next slice
+ {
+ Debug.assert(this._readEncapsStack !== null && this._readEncapsStack.decoder !== null);
+ return this._readEncapsStack.decoder.startSlice();
+ },
+ endReadSlice: function()
+ {
+ Debug.assert(this._readEncapsStack !== null && this._readEncapsStack.decoder !== null);
+ this._readEncapsStack.decoder.endSlice();
+ },
+ skipSlice: function()
+ {
+ Debug.assert(this._readEncapsStack !== null && this._readEncapsStack.decoder !== null);
+ this._readEncapsStack.decoder.skipSlice();
+ },
+ readPendingObjects: function()
+ {
+ if(this._readEncapsStack !== null && this._readEncapsStack.decoder !== null)
+ {
+ this._readEncapsStack.decoder.readPendingObjects();
+ }
+ else if((this._readEncapsStack !== null && this._readEncapsStack.encoding_1_0) ||
+ (this._readEncapsStack === null && this._encoding.equals(Ice.Encoding_1_0)))
+ {
+ //
+ // If using the 1.0 encoding and no objects were read, we
+ // still read an empty sequence of pending objects if
+ // requested (i.e.: if this is called).
+ //
+ // This is required by the 1.0 encoding, even if no objects
+ // are written we do marshal an empty sequence if marshaled
+ // data types use classes.
+ //
+ this.skipSize();
+ }
+ },
+ writePendingObjects: function()
+ {
+ if(this._writeEncapsStack !== null && this._writeEncapsStack.encoder !== null)
+ {
+ this._writeEncapsStack.encoder.writePendingObjects();
+ }
+ else if((this._writeEncapsStack !== null && this._writeEncapsStack.encoding_1_0) ||
+ (this._writeEncapsStack === null && this._encoding.equals(Ice.Encoding_1_0)))
+ {
+ //
+ // If using the 1.0 encoding and no objects were written, we
+ // still write an empty sequence for pending objects if
+ // requested (i.e.: if this is called).
+ //
+ // This is required by the 1.0 encoding, even if no objects
+ // are written we do marshal an empty sequence if marshaled
+ // data types use classes.
+ //
+ this.writeSize(0);
+ }
+ },
+ writeSize: function(v)
+ {
+ if(v > 254)
+ {
+ this.expand(5);
+ this._buf.put(255);
+ this._buf.putInt(v);
+ }
+ else
+ {
+ this.expand(1);
+ this._buf.put(v);
+ }
+ },
+ readSize: function()
+ {
+ try
+ {
+ var b = this._buf.get();
+ if(b === 255)
+ {
+ var v = this._buf.getInt();
+ if(v < 0)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ return v;
+ }
+ return b;
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ readAndCheckSeqSize: function(minSize)
+ {
+ var sz = this.readSize();
+
+ if(sz === 0)
+ {
+ return sz;
+ }
+
+ //
+ // The _startSeq variable points to the start of the sequence for which
+ // we expect to read at least _minSeqSize bytes from the stream.
+ //
+ // If not initialized or if we already read more data than _minSeqSize,
+ // we reset _startSeq and _minSeqSize for this sequence (possibly a
+ // top-level sequence or enclosed sequence it doesn't really matter).
+ //
+ // Otherwise, we are reading an enclosed sequence and we have to bump
+ // _minSeqSize by the minimum size that this sequence will require on
+ // the stream.
+ //
+ // The goal of this check is to ensure that when we start un-marshalling
+ // a new sequence, we check the minimal size of this new sequence against
+ // the estimated remaining buffer size. This estimatation is based on
+ // the minimum size of the enclosing sequences, it's _minSeqSize.
+ //
+ if(this._startSeq === -1 || this._buf.position > (this._startSeq + this._minSeqSize))
+ {
+ this._startSeq = this._buf.position;
+ this._minSeqSize = sz * minSize;
+ }
+ else
+ {
+ this._minSeqSize += sz * minSize;
+ }
+
+ //
+ // If there isn't enough data to read on the stream for the sequence (and
+ // possibly enclosed sequences), something is wrong with the marshalled
+ // data: it's claiming having more data that what is possible to read.
+ //
+ if(this._startSeq + this._minSeqSize > this._buf.limit)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+
+ return sz;
+ },
+ startSize: function()
+ {
+ var pos = this._buf.position;
+ this.writeInt(0); // Placeholder for 32-bit size
+ return pos;
+ },
+ endSize: function(pos)
+ {
+ Debug.assert(pos >= 0);
+ this.rewriteInt(this._buf.position - pos - 4, pos);
+ },
+ writeBlob: function(v)
+ {
+ if(v === null)
+ {
+ return;
+ }
+ this.expand(v.length);
+ this._buf.putArray(v);
+ },
+ readBlob: function(sz)
+ {
+ if(this._buf.remaining < sz)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ try
+ {
+ return this._buf.getArray(sz);
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ // Read/write format and tag for optionals
+ writeOpt: function(tag, format)
+ {
+ Debug.assert(this._writeEncapsStack !== null);
+ if(this._writeEncapsStack.encoder !== null)
+ {
+ return this._writeEncapsStack.encoder.writeOpt(tag, format);
+ }
+ return this.writeOptImpl(tag, format);
+ },
+ readOpt: function(tag, expectedFormat)
+ {
+ Debug.assert(this._readEncapsStack !== null);
+ if(this._readEncapsStack.decoder !== null)
+ {
+ return this._readEncapsStack.decoder.readOpt(tag, expectedFormat);
+ }
+ return this.readOptImpl(tag, expectedFormat);
+ },
+ writeOptValue: function(tag, format, write, v)
+ {
+ if(v !== undefined)
+ {
+ if(this.writeOpt(tag, format))
+ {
+ write.call(this, v);
+ }
+ }
+ },
+ readOptValue: function(tag, format, read)
+ {
+ if(this.readOpt(tag, format))
+ {
+ return read.call(this);
+ }
+ else
+ {
+ return undefined;
+ }
+ },
+ writeByte: function(v)
+ {
+ this.expand(1);
+ this._buf.put(v);
+ },
+ rewriteByte: function(v, dest)
+ {
+ this._buf.putAt(dest, v);
+ },
+ readByte: function()
+ {
+ try
+ {
+ return this._buf.get();
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ writeByteSeq: function(v)
+ {
+ if(v === null || v.length === 0)
+ {
+ this.writeSize(0);
+ }
+ else
+ {
+ this.writeSize(v.length);
+ this.expand(v.length);
+ this._buf.putArray(v);
+ }
+ },
+ readByteSeq: function()
+ {
+ return this._buf.getArray(this.readAndCheckSeqSize(1));
+ },
+ writeBool: function(v)
+ {
+ this.expand(1);
+ this._buf.put(v ? 1 : 0);
+ },
+ rewriteBool: function(v, dest)
+ {
+ this._buf.putAt(dest, v ? 1 : 0);
+ },
+ readBool: function()
+ {
+ try
+ {
+ return this._buf.get() === 1;
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ writeShort: function(v)
+ {
+ this.expand(2);
+ this._buf.putShort(v);
+ },
+ readShort: function()
+ {
+ try
+ {
+ return this._buf.getShort();
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ writeInt: function(v)
+ {
+ this.expand(4);
+ this._buf.putInt(v);
+ },
+ rewriteInt: function(v, dest)
+ {
+ this._buf.putIntAt(dest, v);
+ },
+ readInt: function()
+ {
+ try
+ {
+ return this._buf.getInt();
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ writeLong: function(v)
+ {
+ this.expand(8);
+ this._buf.putLong(v);
+ },
+ readLong: function()
+ {
+ try
+ {
+ return this._buf.getLong();
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ writeFloat: function(v)
+ {
+ this.expand(4);
+ this._buf.putFloat(v);
+ },
+ readFloat: function()
+ {
+ try
+ {
+ return this._buf.getFloat();
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ writeDouble: function(v)
+ {
+ this.expand(8);
+ this._buf.putDouble(v);
+ },
+ readDouble: function()
+ {
+ try
+ {
+ return this._buf.getDouble();
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ writeString: function(v)
+ {
+ if(v === null || v.length === 0)
+ {
+ this.writeSize(0);
+ }
+ else
+ {
+ this._buf.writeString(this, v);
+ }
+ },
+ readString: function()
+ {
+ var len = this.readSize();
+ if(len === 0)
+ {
+ return "";
+ }
+ //
+ // Check the buffer has enough bytes to read.
+ //
+ if(this._buf.remaining < len)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+
+ try
+ {
+ return this._buf.getString(len);
+ }
+ catch(ex)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ },
+ writeProxy: function(v)
+ {
+ this._instance.proxyFactory().proxyToStream(v, this);
+ },
+ writeOptProxy: function(tag, v)
+ {
+ if(v !== undefined)
+ {
+ if(this.writeOpt(tag, OptionalFormat.FSize))
+ {
+ var pos = this.startSize();
+ this.writeProxy(v);
+ this.endSize(pos);
+ }
+ }
+ },
+ readProxy: function(type)
+ {
+ return this._instance.proxyFactory().streamToProxy(this, type);
+ },
+ readOptProxy: function(tag, type)
+ {
+ if(this.readOpt(tag, OptionalFormat.FSize))
+ {
+ this.skip(4);
+ return this.readProxy(type);
+ }
+ else
+ {
+ return undefined;
+ }
+ },
+ writeEnum: function(v)
+ {
+ if(this.isWriteEncoding_1_0())
+ {
+ if(v.maxValue < 127)
+ {
+ this.writeByte(v.value);
+ }
+ else if(v.maxValue < 32767)
+ {
+ this.writeShort(v.value);
+ }
+ else
+ {
+ this.writeInt(v.value);
+ }
+ }
+ else
+ {
+ this.writeSize(v.value);
+ }
+ },
+ readEnum: function(T)
+ {
+ var v;
+ if(this.getReadEncoding().equals(Ice.Encoding_1_0))
+ {
+ if(T.maxValue < 127)
+ {
+ v = this.readByte();
+ }
+ else if(T.maxValue < 32767)
+ {
+ v = this.readShort();
+ }
+ else
+ {
+ v = this.readInt();
+ }
+ }
+ else
+ {
+ v = this.readSize();
+ }
+
+ var e = T.valueOf(v);
+ if(e === undefined)
+ {
+ throw new Ice.MarshalException("enumerator value " + v + " is out of range");
+ }
+ return e;
+ },
+ readOptEnum: function(tag, T)
+ {
+ if(this.readOpt(tag, OptionalFormat.Size))
+ {
+ return this.readEnum(T);
+ }
+ else
+ {
+ return undefined;
+ }
+ },
+ writeObject: function(v)
+ {
+ this.initWriteEncaps();
+ this._writeEncapsStack.encoder.writeObject(v);
+ },
+ writeOptObject: function(tag, v)
+ {
+ if(v !== undefined)
+ {
+ if(this.writeOpt(tag, OptionalFormat.Class))
+ {
+ this.writeObject(v);
+ }
+ }
+ },
+ readObject: function(patcher, T)
+ {
+ this.initReadEncaps();
+ //
+ // BUGFIX:
+ // With Chrome linux the invokation of readObject on the decoder some times
+ // calls BasicStream.readObject with the decoder object as this param.
+ // Use call instead of directly invoke the method to workaround this bug.
+ //
+ this._readEncapsStack.decoder.readObject.call(
+ this._readEncapsStack.decoder,
+ function(obj){
+ if(obj !== null && !(obj.ice_instanceof(T)))
+ {
+ ExUtil.throwUOE(T.ice_staticId(), obj);
+ }
+ patcher(obj);
+ });
+ },
+ readOptObject: function(tag, patcher, T)
+ {
+ if(this.readOpt(tag, OptionalFormat.Class))
+ {
+ this.readObject(patcher, T);
+ }
+ else
+ {
+ patcher(undefined);
+ }
+ },
+ writeUserException: function(e)
+ {
+ this.initWriteEncaps();
+ this._writeEncapsStack.encoder.writeUserException(e);
+ },
+ throwException: function()
+ {
+ this.initReadEncaps();
+ this._readEncapsStack.decoder.throwException();
+ },
+ sliceObjects: function(b)
+ {
+ this._sliceObjects = b;
+ },
+ readOptImpl: function(readTag, expectedFormat)
+ {
+ var b, v, format, tag, offset;
+
+ if(this.isReadEncoding_1_0())
+ {
+ return false; // Optional members aren't supported with the 1.0 encoding.
+ }
+
+ while(true)
+ {
+ if(this._buf.position >= this._readEncapsStack.start + this._readEncapsStack.sz)
+ {
+ return false; // End of encapsulation also indicates end of optionals.
+ }
+
+ v = this.readByte();
+
+ if(v === OPTIONAL_END_MARKER)
+ {
+ this._buf.position -= 1; // Rewind.
+ return false;
+ }
+
+ format = OptionalFormat.valueOf(v & 0x07); // First 3 bits.
+ tag = v >> 3;
+ if(tag === 30)
+ {
+ tag = this.readSize();
+ }
+
+ if(tag > readTag)
+ {
+ offset = tag < 30 ? 1 : (tag < 255 ? 2 : 6); // Rewind
+ this._buf.position -= offset;
+ return false; // No optional data members with the requested tag.
+ }
+
+ if(tag < readTag)
+ {
+ this.skipOpt(format); // Skip optional data members
+ }
+ else
+ {
+ if(format !== expectedFormat)
+ {
+ throw new Ice.MarshalException("invalid optional data member `" + tag + "': unexpected format");
+ }
+ return true;
+ }
+ }
+ },
+ writeOptImpl: function(tag, format)
+ {
+ if(this.isWriteEncoding_1_0())
+ {
+ return false; // Optional members aren't supported with the 1.0 encoding.
+ }
+
+ var v = format.value;
+ if(tag < 30)
+ {
+ v |= tag << 3;
+ this.writeByte(v);
+ }
+ else
+ {
+ v |= 0x0F0; // tag = 30
+ this.writeByte(v);
+ this.writeSize(tag);
+ }
+ return true;
+ },
+ skipOpt: function(format)
+ {
+ switch(format)
+ {
+ case OptionalFormat.F1:
+ this.skip(1);
+ break;
+ case OptionalFormat.F2:
+ this.skip(2);
+ break;
+ case OptionalFormat.F4:
+ this.skip(4);
+ break;
+ case OptionalFormat.F8:
+ this.skip(8);
+ break;
+ case OptionalFormat.Size:
+ this.skipSize();
+ break;
+ case OptionalFormat.VSize:
+ this.skip(this.readSize());
+ break;
+ case OptionalFormat.FSize:
+ this.skip(this.readInt());
+ break;
+ case OptionalFormat.Class:
+ this.readObject(null, Ice.Object);
+ break;
+ }
+ },
+ skipOpts: function()
+ {
+ var b, v, format;
+ //
+ // Skip remaining un-read optional members.
+ //
+ while(true)
+ {
+ if(this._buf.position >= this._readEncapsStack.start + this._readEncapsStack.sz)
+ {
+ return; // End of encapsulation also indicates end of optionals.
+ }
+
+ b = this.readByte();
+ v = b < 0 ? b + 256 : b;
+ if(v === OPTIONAL_END_MARKER)
+ {
+ return;
+ }
+
+ format = OptionalFormat.valueOf(v & 0x07); // Read first 3 bits.
+ if((v >> 3) === 30)
+ {
+ this.skipSize();
+ }
+ this.skipOpt(format);
+ }
+ },
+ skip: function(size)
+ {
+ if(size > this._buf.remaining)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ this._buf.position += size;
+ },
+ skipSize: function()
+ {
+ var b = this.readByte();
+ if(b === 255)
+ {
+ this.skip(4);
+ }
+ },
+ isEmpty: function()
+ {
+ return this._buf.empty();
+ },
+ expand: function(n)
+ {
+ if(!this._unlimited && this._buf && this._buf.position + n > this._messageSizeMax)
+ {
+ ExUtil.throwMemoryLimitException(this._buf.position + n, this._messageSizeMax);
+ }
+ this._buf.expand(n);
+ },
+ createObject: function(id)
+ {
+ var obj = null, Class;
+ try
+ {
+ var typeId = id.length > 2 ? id.substr(2).replace("::", ".") : "";
+ /*jshint -W061 */
+ Class = eval(typeId);
+ /*jshint +W061 */
+ if(Class !== undefined)
+ {
+ obj = new Class();
+ }
+ }
+ catch(ex)
+ {
+ throw new Ice.NoObjectFactoryException("no object factory", id, ex);
+ }
+
+ return obj;
+ },
+ getTypeId: function(compactId)
+ {
+ var typeId = Ice.CompactIdRegistry.get(compactId);
+ return typeId === undefined ? "" : typeId;
+ },
+ isReadEncoding_1_0: function()
+ {
+ return this._readEncapsStack !== null ? this._readEncapsStack.encoding_1_0 : this._encoding.equals(Ice.Encoding_1_0);
+ },
+ isWriteEncoding_1_0: function()
+ {
+ return this._writeEncapsStack ? this._writeEncapsStack.encoding_1_0 : this._encoding.equals(Ice.Encoding_1_0);
+ },
+ initReadEncaps: function()
+ {
+ if(this._readEncapsStack === null) // Lazy initialization
+ {
+ this._readEncapsStack = this._readEncapsCache;
+ if(this._readEncapsStack !== null)
+ {
+ this._readEncapsCache = this._readEncapsCache.next;
+ }
+ else
+ {
+ this._readEncapsStack = new ReadEncaps();
+ }
+ this._readEncapsStack.setEncoding(this._encoding);
+ this._readEncapsStack.sz = this._buf.limit;
+ }
+
+ if(this._readEncapsStack.decoder === null) // Lazy initialization.
+ {
+ var factoryManager = this._instance.servantFactoryManager();
+ if(this._readEncapsStack.encoding_1_0)
+ {
+ this._readEncapsStack.decoder = new EncapsDecoder10(this, this._readEncapsStack, this._sliceObjects, factoryManager);
+ }
+ else
+ {
+ this._readEncapsStack.decoder = new EncapsDecoder11(this, this._readEncapsStack, this._sliceObjects, factoryManager);
+ }
+ }
+ },
+ initWriteEncaps: function()
+ {
+ if(!this._writeEncapsStack) // Lazy initialization
+ {
+ this._writeEncapsStack = this._writeEncapsCache;
+ if(this._writeEncapsStack)
+ {
+ this._writeEncapsCache = this._writeEncapsCache.next;
+ }
+ else
+ {
+ this._writeEncapsStack = new WriteEncaps();
+ }
+ this._writeEncapsStack.setEncoding(this._encoding);
+ }
+
+ if(this._writeEncapsStack.format === FormatType.DefaultFormat)
+ {
+ this._writeEncapsStack.format = this._instance.defaultsAndOverrides().defaultFormat;
+ }
+
+ if(!this._writeEncapsStack.encoder) // Lazy initialization.
+ {
+ if(this._writeEncapsStack.encoding_1_0)
+ {
+ this._writeEncapsStack.encoder = new EncapsEncoder10(this, this._writeEncapsStack);
+ }
+ else
+ {
+ this._writeEncapsStack.encoder = new EncapsEncoder11(this, this._writeEncapsStack);
+ }
+ }
+ },
+ createUserException: function(id)
+ {
+ var userEx = null, Class;
+
+ try
+ {
+ var typeId = id.length > 2 ? id.substr(2).replace("::", ".") : "";
+ /*jshint -W061 */
+ Class = eval(typeId);
+ /*jshint +W061 */
+ if(Class !== undefined)
+ {
+ userEx = new Class();
+ }
+ }
+ catch(ex)
+ {
+ throw new Ice.MarshalException(ex);
+ }
+
+ return userEx;
+ }
+ });
+
+ var defineProperty = Object.defineProperty;
+
+ defineProperty(BasicStream.prototype, "pos", {
+ get: function() { return this._buf.position; },
+ set: function(n) { this._buf.position = n; }
+ });
+
+ defineProperty(BasicStream.prototype, "size", {
+ get: function() { return this._buf.limit; }
+ });
+
+ defineProperty(BasicStream.prototype, "instance", {
+ get: function() { return this._instance; }
+ });
+
+ defineProperty(BasicStream.prototype, "closure", {
+ get: function() { return this._type; },
+ set: function(type) { this._type = type; }
+ });
+
+ defineProperty(BasicStream.prototype, "buffer", {
+ get: function() { return this._buf; }
+ });
+
+ var defineBuiltinHelper = function(write, read, sz, format)
+ {
+ var helper = {
+ write: function(os, v) { return write.call(os, v); },
+ read: function(is) { return read.call(is); },
+ writeOpt: function(os, tag, v) { os.writeOptValue(tag, format, write, v); },
+ readOpt: function(is, tag) { return is.readOptValue(tag, format, read); },
+ };
+ defineProperty(helper, "minWireSize", {
+ get: function() { return sz; }
+ });
+ return helper;
+ };
+
+ var stream = BasicStream.prototype;
+ Ice.ByteHelper = defineBuiltinHelper(stream.writeByte, stream.readByte, 1, Ice.OptionalFormat.F1);
+ Ice.BoolHelper = defineBuiltinHelper(stream.writeBool, stream.readBool, 1, Ice.OptionalFormat.F1);
+ Ice.ShortHelper = defineBuiltinHelper(stream.writeShort, stream.readShort, 2, Ice.OptionalFormat.F2);
+ Ice.IntHelper = defineBuiltinHelper(stream.writeInt, stream.readInt, 4, Ice.OptionalFormat.F4);
+ Ice.LongHelper = defineBuiltinHelper(stream.writeLong, stream.readLong, 8, Ice.OptionalFormat.F8);
+ Ice.FloatHelper = defineBuiltinHelper(stream.writeFloat, stream.readFloat, 4, Ice.OptionalFormat.F4);
+ Ice.DoubleHelper = defineBuiltinHelper(stream.writeDouble, stream.readDouble, 8, Ice.OptionalFormat.F8);
+ Ice.StringHelper = defineBuiltinHelper(stream.writeString, stream.readString, 1, Ice.OptionalFormat.VSize);
+
+ Ice.ObjectHelper = {
+ write: function(os, v)
+ {
+ os.writeObject(v);
+ },
+ read: function(is)
+ {
+ var o;
+ is.readObject(function(v) { o = v; }, Ice.Object);
+ return o;
+ },
+ writeOpt: function(os, tag, v)
+ {
+ os.writeOptValue(tag, Ice.OptionalFormat.Class, stream.writeObject, v);
+ },
+ readOpt: function(is, tag)
+ {
+ var o;
+ is.readOptObject(tag, function(v) { o = v; }, Ice.Object);
+ return o;
+ },
+ };
+
+ defineProperty(Ice.ObjectHelper, "minWireSize", {
+ get: function() { return 1; }
+ });
+
+ Ice.BasicStream = BasicStream;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/BatchOutgoingAsync.js b/js/src/Ice/BatchOutgoingAsync.js
new file mode 100644
index 00000000000..ccebcad9ba5
--- /dev/null
+++ b/js/src/Ice/BatchOutgoingAsync.js
@@ -0,0 +1,37 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_FOR_ACTIONSCRIPT_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+(function(global){
+ require("Ice/Class");
+ require("Ice/AsyncResult");
+
+ var Ice = global.Ice || {};
+
+ var AsyncResult = Ice.AsyncResult;
+
+ var BatchOutgoingAsync = Ice.Class(AsyncResult, {
+ __init__: function(communicator, operation)
+ {
+ AsyncResult.call(this, communicator, operation, null, null, null, null);
+ },
+ __sent: function(connection)
+ {
+ this._state |= AsyncResult.Done | AsyncResult.OK | AsyncResult.Sent;
+ this._os.resize(0);
+ this.succeed(this);
+ },
+ __finishedEx: function(exc, sent)
+ {
+ this.__exception(exc);
+ }
+ });
+
+ Ice.BatchOutgoingAsync = BatchOutgoingAsync;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Buffer.js b/js/src/Ice/Buffer.js
new file mode 100644
index 00000000000..71c4f614bc6
--- /dev/null
+++ b/js/src/Ice/Buffer.js
@@ -0,0 +1,429 @@
+// **********************************************************************
+//
+// 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.
+//
+// **********************************************************************
+
+//
+// Ice.Buffer implementation to be used by Node.js, it uses node Buffer
+// as the store.
+//
+
+//
+// Define Node.Buffer as an alias to NodeJS global Buffer type,
+// that allow us to refer to Ice.Buffer as Buffer in this file.
+//
+(function(global){
+ var Node = { Buffer: global.Buffer };
+
+ require("Ice/Long");
+ require("Ice/Class");
+
+ var Ice = global.Ice || {};
+ var Long = Ice.Long;
+
+ var __BufferOverflowException__ = "BufferOverflowException";
+ var __BufferUnderflowException__ = "BufferUnderflowException";
+ var __IndexOutOfBoundsException__ = "IndexOutOfBoundsException";
+
+ var Buffer = Ice.Class({
+ __init__: function(buffer)
+ {
+ if(buffer !== undefined)
+ {
+ this.b = buffer;
+ }
+ else
+ {
+ this.b = null;
+ }
+ this._position = 0;
+ this._limit = 0;
+ this._shrinkCounter = 0;
+ },
+ empty: function()
+ {
+ return this._limit === 0;
+ },
+ resize: function(n)
+ {
+ if(n === 0)
+ {
+ this.clear();
+ }
+ else if(n > this.capacity)
+ {
+ this.reserve(n);
+ }
+ this._limit = n;
+ },
+ clear: function()
+ {
+ this.b = null;
+ this._position = 0;
+ this._limit = 0;
+ },
+ //
+ // Call expand(n) to add room for n additional bytes. Note that expand()
+ // examines the current position of the buffer first; we don't want to
+ // expand the buffer if the caller is writing to a location that is
+ // already in the buffer.
+ //
+ expand: function(n)
+ {
+ var sz = this.capacity === 0 ? n : this._position + n;
+ if(sz > this._limit)
+ {
+ this.resize(sz);
+ }
+ },
+ reset: function()
+ {
+ if(this._limit > 0 && this._limit * 2 < this.capacity)
+ {
+ //
+ // If the current buffer size is smaller than the
+ // buffer capacity, we shrink the buffer memory to the
+ // current size. This is to avoid holding on to too much
+ // memory if it's not needed anymore.
+ //
+ if(++this._shrinkCounter > 2)
+ {
+ this.reserve(this._limit);
+ this._shrinkCounter = 0;
+ }
+ }
+ else
+ {
+ this._shrinkCounter = 0;
+ }
+ this._limit = 0;
+ this._position = 0;
+ },
+ reserve: function(n)
+ {
+ var b, capacity;
+ if(n > this.capacity)
+ {
+ capacity = Math.max(n, 2 * this.capacity);
+ capacity = Math.max(1024, capacity);
+ if(this.b === null)
+ {
+ this.b = new Node.Buffer(capacity);
+ }
+ else
+ {
+ b = new Node.Buffer(capacity);
+ this.b.copy(b);
+ this.b = b;
+ }
+ }
+ else if(n < this.capacity)
+ {
+ this.b = this.b.slice(0, this.capacity);
+ }
+ else
+ {
+ return;
+ }
+ },
+ put: function(v)
+ {
+ if(this._position === this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.b.writeUInt8(v, this._position, true);
+ this._position++;
+ },
+ putAt: function(i, v)
+ {
+ if(i >= this._limit)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ this.b.writeUInt8(v, i, true);
+ },
+ putArray: function(v)
+ {
+ //Expects a Nodejs Buffer
+ if(this._position + v.length > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ v.copy(this.b, this._position);
+ this._position += v.length;
+ },
+ putShort: function(v)
+ {
+ if(this._position + 2 > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.b.writeInt16LE(v, this._position, true);
+ this._position += 2;
+ },
+ putShortAt: function(i, v)
+ {
+ if(i + 2 > this._limit || i < 0)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ this.b.writeInt16LE(v, i, true);
+ },
+ putInt: function(v)
+ {
+ if(this._position + 4 > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.b.writeInt32LE(v, this._position, true);
+ this._position += 4;
+ },
+ putIntAt: function(i, v)
+ {
+ if(i + 4 > this._limit || i < 0)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ this.b.writeInt32LE(v, i, true);
+ },
+ putFloat: function(v)
+ {
+ if(this._position + 4 > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.b.writeFloatLE(v, this._position, true);
+ this._position += 4;
+ },
+ putFloatAt: function(i, v)
+ {
+ if(i + 4 > this._limit || i < 0)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ this.b.writeFloatLE(v, i, true);
+ },
+ putDouble: function(v)
+ {
+ if(this._position + 8 > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.b.writeDoubleLE(v, this._position, true);
+ this._position += 8;
+ },
+ putDoubleAt: function(i, v)
+ {
+ if(i + 8 > this._limit || i < 0)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ this.b.writeDoubleLE(v, i, true);
+ },
+ putLong: function(v)
+ {
+ if(this._position + 8 > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.b.writeUInt32LE(v.low, this._position, true);
+ this._position += 4;
+ this.b.writeUInt32LE(v.high, this._position, true);
+ this._position += 4;
+ },
+ putLongAt: function(i, v)
+ {
+ if(i + 8 > this._limit || i < 0)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ this.b.writeUInt32LE(v.low, i, true);
+ this.b.writeUInt32LE(v.high, i + 4, true);
+ },
+ writeString: function(stream, v)
+ {
+ var sz = Node.Buffer.byteLength(v);
+ stream.writeSize(sz);
+ stream.expand(sz);
+ this.putString(v, sz);
+ },
+ putString: function(v, sz)
+ {
+ if(this._position + sz > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ var bytes = this.b.write(v, this._position);
+ //
+ // Check all bytes were written
+ //
+ if(bytes < sz)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ this._position += sz;
+ },
+ get: function()
+ {
+ if(this._position >= this._limit)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var v = this.b.readUInt8(this._position, true);
+ this._position++;
+ return v;
+ },
+ getAt: function(i)
+ {
+ if(i < 0 || i >= this._limit)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ return this.b.readUInt8(i, true);
+ },
+ getArray: function(length)
+ {
+ if(this._position + length > this._limit)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var buffer = new Node.Buffer(length);
+ this.b.slice(this._position, this._position + length).copy(buffer);
+ this._position += length;
+ return buffer;
+ },
+ getArrayAt: function(position, length)
+ {
+ if(position + length > this._limit)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var buffer = new Node.Buffer(length);
+ length = length === undefined ? (this.b.length - position) : length;
+ this.b.slice(position, position + length).copy(buffer);
+ return buffer;
+ },
+ getShort: function()
+ {
+ var v;
+ if(this._limit - this._position < 2)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ v = this.b.readInt16LE(this._position, true);
+ this._position += 2;
+ return v;
+ },
+ getInt: function()
+ {
+ var v;
+ if(this._limit - this._position < 4)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ v = this.b.readInt32LE(this._position, true);
+ this._position += 4;
+ return v;
+ },
+ getFloat: function()
+ {
+ if(this._limit - this._position < 4)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var v = this.b.readFloatLE(this._position, true);
+ this._position += 4;
+ return v;
+ },
+ getDouble: function()
+ {
+ if(this._limit - this._position < 8)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var v = this.b.readDoubleLE(this._position, true);
+ this._position += 8;
+ return v;
+ },
+ getLong: function()
+ {
+ if(this._limit - this._position < 8)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var v = new Long();
+ v.low = this.b.readUInt32LE(this._position, true);
+ this._position += 4;
+ v.high = this.b.readUInt32LE(this._position, true);
+ this._position += 4;
+ return v;
+ },
+ getString: function(length)
+ {
+ if(this._position + length > this._limit)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var s =this.b.toString("utf8", this._position, this._position + length);
+ this._position += length;
+ return s;
+ }
+ });
+
+ var prototype = Buffer.prototype;
+
+ Object.defineProperty(prototype, "position", {
+ get: function() { return this._position; },
+ set: function(position){
+ if(position >= 0 && position <= this._limit)
+ {
+ this._position = position;
+ }
+ }
+ });
+
+ Object.defineProperty(prototype, "limit", {
+ get: function() { return this._limit; },
+ set: function(limit){
+ if(limit <= this.capacity)
+ {
+ this._limit = limit;
+ if(this._position > limit)
+ {
+ this._position = limit;
+ }
+ }
+ }
+ });
+
+ Object.defineProperty(prototype, "capacity", {
+ get: function() { return this.b === null ? 0 : this.b.length; }
+ });
+
+ Object.defineProperty(prototype, "remaining", {
+ get: function() { return this._limit - this._position; }
+ });
+
+ //
+ // Create a native buffer from an array of bytes.
+ //
+ Buffer.createNative = function(data)
+ {
+ if(data === undefined)
+ {
+ return new Node.Buffer(0);
+ }
+ else
+ {
+ return new Node.Buffer(data);
+ }
+ };
+
+ Ice.Buffer = Buffer;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Class.js b/js/src/Ice/Class.js
new file mode 100644
index 00000000000..1e1778fb71f
--- /dev/null
+++ b/js/src/Ice/Class.js
@@ -0,0 +1,58 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+
+ var Class = function()
+ {
+ var base;
+ var desc;
+ var constructor;
+
+ if(arguments.length == 1)
+ {
+ desc = arguments[0];
+ }
+ else if(arguments.length == 2)
+ {
+ base = arguments[0];
+ desc = arguments[1];
+ }
+
+ if(desc !== undefined)
+ {
+ constructor = desc.__init__;
+ if(constructor)
+ {
+ delete desc.__init__;
+ }
+ }
+
+ var o = constructor || function(){};
+
+ if(base !== undefined)
+ {
+ o.prototype = new base();
+ o.prototype.constructor = o;
+ }
+
+ if(desc !== undefined)
+ {
+ for(var key in desc)
+ {
+ o.prototype[key] = desc[key];
+ }
+ }
+ return o;
+ };
+
+ Ice.Class = Class;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Communicator.js b/js/src/Ice/Communicator.js
new file mode 100644
index 00000000000..b2427221eb1
--- /dev/null
+++ b/js/src/Ice/Communicator.js
@@ -0,0 +1,166 @@
+// **********************************************************************
+//
+// 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/Instance");
+ require("Ice/Promise");
+ require("Ice/UUID");
+ require("Ice/AsyncResultBase");
+
+ var Ice = global.Ice || {};
+
+ var Instance = Ice.Instance;
+ var Promise = Ice.Promise;
+ var UUID = Ice.UUID;
+
+ //
+ // Ice.Communicator
+ //
+ var Communicator = Ice.Class({
+ __init__: function(initData)
+ {
+ this._instance = new Instance(initData);
+ },
+ //
+ // Certain initialization tasks need to be completed after the
+ // constructor.
+ //
+ finishSetup: function(promise)
+ {
+ this._instance.finishSetup(this, promise);
+ },
+ destroy: function()
+ {
+ return this._instance.destroy();
+ },
+ shutdown: function()
+ {
+ this._instance.objectAdapterFactory().shutdown();
+ },
+ waitForShutdown: function()
+ {
+ return this._instance.objectAdapterFactory().waitForShutdown();
+ },
+ isShutdown: function()
+ {
+ return this._instance.objectAdapterFactory().isShutdown();
+ },
+ stringToProxy: function(s)
+ {
+ return this._instance.proxyFactory().stringToProxy(s);
+ },
+ proxyToString: function(proxy)
+ {
+ return this._instance.proxyFactory().proxyToString(proxy);
+ },
+ propertyToProxy: function(s)
+ {
+ return this._instance.proxyFactory().propertyToProxy(s);
+ },
+ proxyToProperty: function(proxy, prefix)
+ {
+ return this._instance.proxyFactory().proxyToProperty(proxy, prefix);
+ },
+ stringToIdentity: function(s)
+ {
+ return this._instance.stringToIdentity(s);
+ },
+ identityToString: function(ident)
+ {
+ return this._instance.identityToString(ident);
+ },
+ createObjectAdapter: function(name)
+ {
+ var promise = new Ice.AsyncResultBase(this, "createObjectAdapter", this, null, null);
+ this._instance.objectAdapterFactory().createObjectAdapter(name, null, promise);
+ return promise;
+ },
+ createObjectAdapterWithEndpoints: function(name, endpoints)
+ {
+ if(name.length === 0)
+ {
+ name = UUID.generateUUID();
+ }
+
+ this.getProperties().setProperty(name + ".Endpoints", endpoints);
+ var promise = new Ice.AsyncResultBase(this, "createObjectAdapterWithEndpoints", this, null, null);
+ this._instance.objectAdapterFactory().createObjectAdapter(name, null, promise);
+ return promise;
+ },
+ createObjectAdapterWithRouter: function(name, router)
+ {
+ if(name.length === 0)
+ {
+ name = UUID.generateUUID();
+ }
+
+ var promise = new Ice.AsyncResultBase(this, "createObjectAdapterWithRouter", this, null, null);
+
+ //
+ // We set the proxy properties here, although we still use the proxy supplied.
+ //
+ var properties = this.proxyToProperty(router, name + ".Router");
+ for(var e = properties.entries; e !== null; e = e.next)
+ {
+ this.getProperties().setProperty(e.key, e.value);
+ }
+
+ this._instance.objectAdapterFactory().createObjectAdapter(name, router, promise);
+ return promise;
+ },
+ addObjectFactory: function(factory, id)
+ {
+ this._instance.servantFactoryManager().add(factory, id);
+ },
+ findObjectFactory: function(id)
+ {
+ return this._instance.servantFactoryManager().find(id);
+ },
+ getImplicitContext: function()
+ {
+ return this._instance.getImplicitContext();
+ },
+ getProperties: function()
+ {
+ return this._instance.initializationData().properties;
+ },
+ getLogger: function()
+ {
+ return this._instance.initializationData().logger;
+ },
+ getDefaultRouter: function()
+ {
+ return this._instance.referenceFactory().getDefaultRouter();
+ },
+ setDefaultRouter: function(router)
+ {
+ this._instance.setDefaultRouter(router);
+ },
+ getDefaultLocator: function()
+ {
+ return this._instance.referenceFactory().getDefaultLocator();
+ },
+ setDefaultLocator: function(locator)
+ {
+ this._instance.setDefaultLocator(locator);
+ },
+ flushBatchRequests: function()
+ {
+ return this._instance.outgoingConnectionFactory().flushAsyncBatchRequests();
+ }
+ });
+
+ Object.defineProperty(Communicator.prototype, "instance", {
+ get: function() { return this._instance; }
+ });
+
+ Ice.Communicator = Communicator;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/CompactIdRegistry.js b/js/src/Ice/CompactIdRegistry.js
new file mode 100644
index 00000000000..b3f46caadf3
--- /dev/null
+++ b/js/src/Ice/CompactIdRegistry.js
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// 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/HashMap");
+ var Ice = global.Ice || {};
+ Ice.CompactIdRegistry = new Ice.HashMap();
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ConnectRequestHandler.js b/js/src/Ice/ConnectRequestHandler.js
new file mode 100644
index 00000000000..c6053f3945a
--- /dev/null
+++ b/js/src/Ice/ConnectRequestHandler.js
@@ -0,0 +1,429 @@
+// **********************************************************************
+//
+// 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/AsyncResult");
+ require("Ice/AsyncStatus");
+ require("Ice/BasicStream");
+ require("Ice/BatchOutgoingAsync");
+ require("Ice/ConnectionRequestHandler");
+ require("Ice/Debug");
+ require("Ice/ExUtil");
+ require("Ice/LocalExceptionWrapper");
+ require("Ice/OutgoingAsync");
+ require("Ice/Protocol");
+ require("Ice/ReferenceMode");
+ require("Ice/Exception");
+ require("Ice/Promise");
+
+ var Ice = global.Ice || {};
+
+ var AsyncResult = Ice.AsyncResult;
+ var AsyncStatus = Ice.AsyncStatus;
+ var BasicStream = Ice.BasicStream;
+ var BatchOutgoingAsync = Ice.BatchOutgoingAsync;
+ var ConnectionRequestHandler = Ice.ConnectionRequestHandler;
+ var Debug = Ice.Debug;
+ var ExUtil = Ice.ExUtil;
+ var LocalExceptionWrapper = Ice.LocalExceptionWrapper;
+ var OutgoingAsync = Ice.OutgoingAsync;
+ var Protocol = Ice.Protocol;
+ var ReferenceMode = Ice.ReferenceMode;
+ var LocalException = Ice.LocalException;
+ var Promise = Ice.Promise;
+
+ var ConnectRequestHandler = Ice.Class({
+ __init__: function(ref, proxy)
+ {
+ this._reference = ref;
+ this._response = ref.getMode() === ReferenceMode.ModeTwoway;
+ this._proxy = proxy;
+ this._batchAutoFlush = ref.getInstance().initializationData().properties.getPropertyAsIntWithDefault(
+ "Ice.BatchAutoFlush", 1) > 0 ? true : false;
+ this._initialized = false;
+ this._flushing = false;
+ this._batchRequestInProgress = false;
+ this._batchRequestsSize = Protocol.requestBatchHdr.length;
+ this._batchStream =
+ new BasicStream(ref.getInstance(), Protocol.currentProtocolEncoding, this._batchAutoFlush);
+ this._updateRequestHandler = false;
+
+ this._connection = null;
+ this._compress = false;
+ this._exception = null;
+ this._requests = [];
+ this._updateRequestHandler = false;
+ this._pendingPromises = [];
+ },
+ connect: function()
+ {
+ var self = this;
+ this._reference.getConnection().then(
+ function(connection, compress)
+ {
+ self.setConnection(connection, compress);
+ }).exception(
+ function(ex)
+ {
+ self.setException(ex);
+ });
+
+ if(this.initialized())
+ {
+ Debug.assert(this._connection !== null);
+ return new ConnectionRequestHandler(this._reference, this._connection, this._compress);
+ }
+ else
+ {
+ // The proxy request handler will be updated when the connection is set.
+ this._updateRequestHandler = true;
+ return this;
+ }
+ },
+ prepareBatchRequest: function(os)
+ {
+ if(!this.initialized())
+ {
+ this._batchRequestInProgress = true;
+ this._batchStream.swap(os);
+ return;
+ }
+
+ this._connection.prepareBatchRequest(os);
+ },
+ finishBatchRequest: function(os)
+ {
+ if(!this.initialized())
+ {
+ Debug.assert(this._batchRequestInProgress);
+ this._batchRequestInProgress = false;
+
+ this._batchStream.swap(os);
+
+ if(!this._batchAutoFlush &&
+ this._batchStream.size + this._batchRequestsSize > this._reference.getInstance().messageSizeMax())
+ {
+ ExUtil.throwMemoryLimitException(this._batchStream.size + this._batchRequestsSize,
+ this._reference.getInstance().messageSizeMax());
+ }
+
+ this._requests.push(new Request(this._batchStream));
+ return;
+ }
+ this._connection.finishBatchRequest(os, this._compress);
+ },
+ abortBatchRequest: function()
+ {
+ if(!this.initialized())
+ {
+ Debug.assert(this._batchRequestInProgress);
+ this._batchRequestInProgress = false;
+
+ var dummy = new BasicStream(this._reference.getInstance(), Protocol.currentProtocolEncoding,
+ this._batchAutoFlush);
+ this._batchStream.swap(dummy);
+ this._batchRequestsSize = Protocol.requestBatchHdr.length;
+
+ return;
+ }
+ this._connection.abortBatchRequest();
+ },
+ sendAsyncRequest: function(out)
+ {
+ if(!this.initialized())
+ {
+ this._requests.push(new Request(out));
+ return AsyncStatus.Queued;
+ }
+ return this._connection.sendAsyncRequest(out, this._compress, this._response);
+ },
+ flushAsyncBatchRequests: function(out)
+ {
+ if(!this.initialized())
+ {
+ this._requests.push(new Request(out));
+ return AsyncStatus.Queued;
+ }
+ return this._connection.flushAsyncBatchRequests(out);
+ },
+ getReference: function()
+ {
+ return this._reference;
+ },
+ getConnection: function()
+ {
+ if(this._exception !== null)
+ {
+ throw this._exception;
+ }
+ else
+ {
+ return this._connection;
+ }
+ },
+ onConnection: function(r)
+ {
+ //
+ // Called by ObjectPrx.ice_getConnection
+ //
+
+ if(this._exception !== null)
+ {
+ r.__exception(this._exception);
+ }
+ else if(this._connection !== null)
+ {
+ Debug.assert(this._initialized);
+ r.succeed(this._connection, r);
+ }
+ else
+ {
+ this._pendingPromises.push(r);
+ }
+ },
+ //
+ // Implementation of Reference_GetConnectionCallback
+ //
+
+ setConnection: function(connection, compress)
+ {
+ Debug.assert(this._exception === null && this._connection === null);
+ Debug.assert(this._updateRequestHandler || this._requests.length === 0);
+
+ this._connection = connection;
+ this._compress = compress;
+
+ //
+ // If this proxy is for a non-local object, and we are using a router, then
+ // add this proxy to the router info object.
+ //
+ var ri = this._reference.getRouterInfo();
+ if(ri !== null)
+ {
+ var self = this;
+ var promise = ri.addProxy(this._proxy).then(
+ function()
+ {
+ //
+ // The proxy was added to the router info, we're now ready to send the
+ // queued requests.
+ //
+ self.flushRequests();
+ }).exception(
+ function(ex)
+ {
+ self.setException(ex);
+ });
+
+ if(!promise.completed())
+ {
+ return; // The request handler will be initialized once addProxy completes.
+ }
+ }
+
+ //
+ // We can now send the queued requests.
+ //
+ this.flushRequests();
+ },
+ setException: function(ex)
+ {
+ Debug.assert(!this._initialized && this._exception === null);
+ Debug.assert(this._updateRequestHandler || this._requests.length === 0);
+
+ this._exception = ex;
+ this._proxy = null; // Break cyclic reference count.
+
+ //
+ // If some requests were queued, we notify them of the failure.
+ //
+ if(this._requests.length > 0)
+ {
+ this.flushRequestsWithException(ex);
+ }
+
+ for(var i = 0; i < this._pendingPromises.length; ++i)
+ {
+ this._pendingPromises[i].fail(ex);
+ }
+ this._pendingPromises = [];
+ },
+ initialized: function()
+ {
+ if(this._initialized)
+ {
+ Debug.assert(this._connection !== null);
+ return true;
+ }
+ else
+ {
+ if(this._exception !== null)
+ {
+ throw this._exception;
+ }
+ else
+ {
+ return this._initialized;
+ }
+ }
+ },
+ flushRequests: function()
+ {
+ Debug.assert(this._connection !== null && !this._initialized);
+
+ //
+ // We set the _flushing flag to true to prevent any additional queuing. Callers
+ // might block for a little while as the queued requests are being sent but this
+ // shouldn't be an issue as the request sends are non-blocking.
+ //
+ this._flushing = true;
+
+ try
+ {
+ while(this._requests.length > 0)
+ {
+ var request = this._requests[0];
+ if(request.out !== null)
+ {
+ this._connection.sendAsyncRequest(request.out, this._compress, this._response);
+ }
+ else if(request.batchOut !== null)
+ {
+ this._connection.flushAsyncBatchRequests(request.batchOut);
+ }
+ else
+ {
+ var os = new BasicStream(request.os.instance, Protocol.currentProtocolEncoding);
+ this._connection.prepareBatchRequest(os);
+ try
+ {
+ request.os.pos = 0;
+ os.writeBlob(request.os.readBlob(request.os.size));
+ }
+ catch(ex)
+ {
+ this._connection.abortBatchRequest();
+ throw ex;
+ }
+ this._connection.finishBatchRequest(os, this._compress);
+ }
+ this._requests.shift();
+ }
+ }
+ catch(ex)
+ {
+ if(ex instanceof LocalExceptionWrapper)
+ {
+ Debug.assert(this._exception === null && this._requests.length > 0);
+ this._exception = ex.inner;
+ this.flushRequestsWithExceptionWrapper(ex);
+ }
+ else if(ex instanceof LocalException)
+ {
+ Debug.assert(this._exception === null && this._requests.length > 0);
+ this._exception = ex;
+ this.flushRequestsWithException(ex);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ //
+ // We've finished sending the queued requests and the request handler now send
+ // the requests over the connection directly. It's time to substitute the
+ // request handler of the proxy with the more efficient connection request
+ // handler which does not have any synchronization. This also breaks the cyclic
+ // reference count with the proxy.
+ //
+ // NOTE: _updateRequestHandler is immutable once _flushing = true
+ //
+ if(this._updateRequestHandler && this._exception === null)
+ {
+ this._proxy.__setRequestHandler(
+ new ConnectionRequestHandler(this._reference, this._connection, this._compress));
+ }
+
+ Debug.assert(!this._initialized);
+ if(this._exception === null)
+ {
+ this._initialized = true;
+ this._flushing = false;
+ }
+ this._proxy = null; // Break cyclic reference count.
+
+ var p;
+ for(var i = 0; i < this._pendingPromises.length; ++i)
+ {
+ p = this._pendingPromises[i];
+ p.succeed(this._connection, p);
+ }
+ this._pendingPromises = [];
+ },
+ flushRequestsWithException: function(ex)
+ {
+ for(var i = 0; i < this._requests.length; ++i)
+ {
+ var request = this._requests[i];
+ if(request.out !== null)
+ {
+ request.out.__finishedEx(ex, false);
+ }
+ else if(request.batchOut !== null)
+ {
+ request.batchOut.__finishedEx(ex, false);
+ }
+ }
+ this._requests = [];
+ },
+ flushRequestsWithExceptionWrapper: function(ex)
+ {
+ for(var i = 0; i < this._requests.length; ++i)
+ {
+ var request = this._requests[i];
+ if(request.out !== null)
+ {
+ request.out.__finishedWrapper(ex);
+ }
+ else if(request.batchOut !== null)
+ {
+ request.batchOut.__finishedEx(ex.inner, false);
+ }
+ }
+ this._requests = [];
+ }
+ });
+
+ Ice.ConnectRequestHandler = ConnectRequestHandler;
+ global.Ice = Ice;
+
+ var Request = function(arg)
+ {
+ this.os = null;
+ this.out = null;
+ this.batchOut = null;
+
+ if(arg instanceof BasicStream)
+ {
+ this.os = new BasicStream(arg.instance, Protocol.currentProtocolEncoding);
+ this.os.swap(arg);
+ }
+ else if(arg instanceof OutgoingAsync)
+ {
+ this.out = arg;
+ }
+ else
+ {
+ Debug.assert(arg instanceof BatchOutgoingAsync);
+ this.batchOut = arg;
+ }
+ };
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ConnectionBatchOutgoingAsync.js b/js/src/Ice/ConnectionBatchOutgoingAsync.js
new file mode 100644
index 00000000000..f4f4d801544
--- /dev/null
+++ b/js/src/Ice/ConnectionBatchOutgoingAsync.js
@@ -0,0 +1,30 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_FOR_ACTIONSCRIPT_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+(function(global){
+ require("Ice/Class");
+ require("Ice/BatchOutgoingAsync");
+
+ var Ice = global.Ice || {};
+
+ var BatchOutgoingAsync = Ice.BatchOutgoingAsync;
+
+ Ice.ConnectionBatchOutgoingAsync = Ice.Class(BatchOutgoingAsync, {
+ __init__: function(con, communicator, operation)
+ {
+ BatchOutgoingAsync.call(this, communicator, operation);
+ this._connection = con;
+ },
+ __send: function()
+ {
+ this._connection.flushAsyncBatchRequests(this);
+ }
+ });
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ConnectionI.js b/js/src/Ice/ConnectionI.js
new file mode 100644
index 00000000000..f08d9474bd3
--- /dev/null
+++ b/js/src/Ice/ConnectionI.js
@@ -0,0 +1,2030 @@
+// **********************************************************************
+//
+// 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/AsyncStatus");
+ require("Ice/AsyncResultBase");
+ require("Ice/BasicStream");
+ require("Ice/ConnectionBatchOutgoingAsync");
+ require("Ice/Debug");
+ require("Ice/ExUtil");
+ require("Ice/HashMap");
+ require("Ice/IncomingAsync");
+ require("Ice/LocalExceptionWrapper");
+ require("Ice/Promise");
+ require("Ice/Protocol");
+ require("Ice/SocketOperation");
+ require("Ice/Timer");
+ require("Ice/TraceUtil");
+ require("Ice/Version");
+ require("Ice/Exception");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var AsyncStatus = Ice.AsyncStatus;
+ var AsyncResultBase = Ice.AsyncResultBase;
+ var BasicStream = Ice.BasicStream;
+ var ConnectionBatchOutgoingAsync = Ice.ConnectionBatchOutgoingAsync;
+ var Debug = Ice.Debug;
+ var ExUtil = Ice.ExUtil;
+ var HashMap = Ice.HashMap;
+ var IncomingAsync = Ice.IncomingAsync;
+ var LocalExceptionWrapper = Ice.LocalExceptionWrapper;
+ var Promise = Ice.Promise;
+ var Protocol = Ice.Protocol;
+ var SocketOperation = Ice.SocketOperation;
+ var Timer = Ice.Timer;
+ var TraceUtil = Ice.TraceUtil;
+ var ProtocolVersion = Ice.ProtocolVersion;
+ var EncodingVersion = Ice.EncodingVersion;
+
+ var StateNotInitialized = 0;
+ var StateNotValidated = 1;
+ var StateActive = 2;
+ var StateHolding = 3;
+ var StateClosing = 4;
+ var StateClosed = 5;
+ var StateFinished = 6;
+
+ var MessageInfo = function(instance)
+ {
+ this.stream = new BasicStream(instance, Protocol.currentProtocolEncoding, false);
+
+ this.invokeNum = 0;
+ this.requestId = 0;
+ this.compress = false;
+ this.servantManager = null;
+ this.adapter = null;
+ this.outAsync = null;
+ };
+
+ var Class = Ice.Class;
+
+ var ConnectionI = Class({
+ __init__: function(communicator, instance, reaper, transceiver, endpoint, incoming, adapter)
+ {
+ this._communicator = communicator;
+ this._instance = instance;
+ this._reaper = reaper;
+ this._transceiver = transceiver;
+ this._desc = transceiver.toString();
+ this._type = transceiver.type();
+ this._endpoint = endpoint;
+ this._incoming = incoming;
+ this._adapter = adapter;
+ var initData = instance.initializationData();
+ this._logger = initData.logger; // Cached for better performance.
+ this._traceLevels = instance.traceLevels(); // Cached for better performance.
+ this._timer = instance.timer();
+ this._writeTimeoutId = 0;
+ this._writeTimeoutScheduled = false;
+ this._readTimeoutId = 0;
+ this._readTimeoutScheduled = false;
+
+ this._hasMoreData = { value: false };
+
+ this._warn = initData.properties.getPropertyAsInt("Ice.Warn.Connections") > 0;
+ this._warnUdp = instance.initializationData().properties.getPropertyAsInt("Ice.Warn.Datagrams") > 0;
+ this._acmAbsoluteTimeoutMillis = 0;
+
+ this._nextRequestId = 1;
+ this._batchAutoFlush = initData.properties.getPropertyAsIntWithDefault("Ice.BatchAutoFlush", 1) > 0 ? true : false;
+ this._batchStream = new BasicStream(instance, Protocol.currentProtocolEncoding, this._batchAutoFlush);
+ this._batchStreamInUse = false;
+ this._batchRequestNum = 0;
+ this._batchRequestCompress = false;
+ this._batchMarker = 0;
+
+ this._sendStreams = [];
+
+ this._readStream = new BasicStream(instance, Protocol.currentProtocolEncoding);
+ this._readHeader = false;
+ this._writeStream = new BasicStream(instance, Protocol.currentProtocolEncoding);
+
+ this._readStreamPos = -1;
+ this._writeStreamPos = -1;
+
+ this._dispatchCount = 0;
+
+ this._state = StateNotInitialized;
+ this._shutdownInitiated = false;
+ this._validated = false;
+
+ this._readProtocol = new ProtocolVersion();
+ this._readProtocolEncoding = new EncodingVersion();
+
+ this._asyncRequests = new HashMap(); // Map<int, OutgoingAsync>
+
+ this._exception = null;
+
+ this._startPromise = null;
+ this._closePromises = [];
+ this._holdPromises = [];
+ this._finishedPromises = [];
+
+ if(this._adapter !== null)
+ {
+ this._servantManager = this._adapter.getServantManager();
+ }
+ else
+ {
+ this._servantManager = null;
+ }
+
+ if(this._endpoint.datagram())
+ {
+ this._acmTimeout = 0;
+ }
+ else
+ {
+ if(this._adapter !== null)
+ {
+ this._acmTimeout = this._adapter.getACM();
+ }
+ else
+ {
+ this._acmTimeout = this._instance.clientACM();
+ }
+ }
+ },
+ start: function()
+ {
+ Debug.assert(this._startPromise === null);
+
+ try
+ {
+ // The connection might already be closed if the communicator was destroyed.
+ if(this._state >= StateClosed)
+ {
+ Debug.assert(this._exception !== null);
+ return new Promise().fail(this._exception);
+ }
+
+ this._startPromise = new Promise();
+ var self = this;
+ this._transceiver.setCallbacks(
+ function() { self.message(SocketOperation.Write); }, // connected callback
+ function() { self.message(SocketOperation.Read); }, // read callback
+ function() { self.message(SocketOperation.Write); } // write callback
+ );
+ this.initialize();
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.exception(ex);
+ }
+ return new Promise().fail(ex);
+ }
+
+ return this._startPromise;
+ },
+ activate: function()
+ {
+ if(this._state <= StateNotValidated)
+ {
+ return;
+ }
+
+ if(this._acmTimeout > 0)
+ {
+ this._acmAbsoluteTimeoutMillis = Date.now() + this._acmTimeout * 1000;
+ }
+
+ this.setState(StateActive);
+ },
+ hold: function()
+ {
+ if(this._state <= StateNotValidated)
+ {
+ return;
+ }
+
+ this.setState(StateHolding);
+ },
+ destroy: function(reason)
+ {
+ switch(reason)
+ {
+ case ConnectionI.ObjectAdapterDeactivated:
+ {
+ this.setStateEx(StateClosing, new Ice.ObjectAdapterDeactivatedException());
+ break;
+ }
+
+ case ConnectionI.CommunicatorDestroyed:
+ {
+ this.setStateEx(StateClosing, new Ice.CommunicatorDestroyedException());
+ break;
+ }
+ }
+ },
+ close: function(force)
+ {
+ var __r = new AsyncResultBase(this._communicator, "close", this, null, null);
+
+ if(force)
+ {
+ this.setStateEx(StateClosed, new Ice.ForcedCloseConnectionException());
+ __r.succeed(__r);
+ }
+ else
+ {
+ //
+ // If we do a graceful shutdown, then we wait until all
+ // outstanding requests have been completed. Otherwise,
+ // the CloseConnectionException will cause all outstanding
+ // requests to be retried, regardless of whether the
+ // server has processed them or not.
+ //
+ this._closePromises.push(__r);
+ this.checkClose();
+ }
+
+ return __r;
+ },
+ checkClose: function()
+ {
+ //
+ // If close(false) has been called, then we need to check if all
+ // requests have completed and we can transition to StateClosing.
+ // We also complete outstanding promises.
+ //
+ if(this._asyncRequests.size === 0 && this._closePromises.length > 0)
+ {
+ this.setStateEx(StateClosing, new Ice.CloseConnectionException());
+ for(var i = 0; i < this._closePromises.length; ++i)
+ {
+ this._closePromises[i].succeed(this._closePromises[i]);
+ }
+ this._closePromises = [];
+ }
+ },
+ isActiveOrHolding: function()
+ {
+ return this._state > StateNotValidated && this._state < StateClosing;
+ },
+ isFinished: function()
+ {
+ if(this._state !== StateFinished || this._dispatchCount !== 0)
+ {
+ return false;
+ }
+
+ Debug.assert(this._state === StateFinished);
+ return true;
+ },
+ throwException: function()
+ {
+ if(this._exception !== null)
+ {
+ Debug.assert(this._state >= StateClosing);
+ throw this._exception;
+ }
+ },
+ waitUntilHolding: function()
+ {
+ var promise = new Promise();
+ this._holdPromises.push(promise);
+ this.checkState();
+ return promise;
+ },
+ waitUntilFinished: function()
+ {
+ var promise = new Promise();
+ this._finishedPromises.push(promise);
+ this.checkState();
+ return promise;
+ },
+ monitor: function(now)
+ {
+ if(this._state !== StateActive)
+ {
+ return;
+ }
+
+ //
+ // Active connection management for idle connections.
+ //
+ if(this._acmTimeout <= 0 ||
+ this._asyncRequests.size > 0 || this._dispatchCount > 0 ||
+ this._readStream.size > Protocol.headerSize || !this._writeStream.isEmpty() ||
+ !this._batchStream.isEmpty())
+ {
+ return;
+ }
+
+ if(now >= this._acmAbsoluteTimeoutMillis)
+ {
+ this.setStateEx(StateClosing, new Ice.ConnectionTimeoutException());
+ }
+ },
+ sendAsyncRequest: function(out, compress, response)
+ {
+ var requestId = 0;
+ var os = out.__os();
+
+ if(this._exception !== null)
+ {
+ //
+ // If the connection is closed before we even have a chance
+ // to send our request, we always try to send the request
+ // again.
+ //
+ throw new LocalExceptionWrapper(this._exception, true);
+ }
+
+ Debug.assert(this._state > StateNotValidated);
+ Debug.assert(this._state < StateClosing);
+
+ //
+ // Ensure the message isn't bigger than what we can send with the
+ // transport.
+ //
+ this._transceiver.checkSendSize(os, this._instance.messageSizeMax());
+
+ if(response)
+ {
+ //
+ // Create a new unique request ID.
+ //
+ requestId = this._nextRequestId++;
+ if(requestId <= 0)
+ {
+ this._nextRequestId = 1;
+ requestId = this._nextRequestId++;
+ }
+
+ //
+ // Fill in the request ID.
+ //
+ os.pos = Protocol.headerSize;
+ os.writeInt(requestId);
+ }
+
+ var status;
+ try
+ {
+ status = this.sendMessage(OutgoingMessage.create(out, out.__os(), compress, requestId));
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.setStateEx(StateClosed, ex);
+ Debug.assert(this._exception !== null);
+ throw this._exception;
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ if(response)
+ {
+ //
+ // Add to the async requests map.
+ //
+ this._asyncRequests.set(requestId, out);
+ }
+
+ return status;
+ },
+ prepareBatchRequest: function(os)
+ {
+ if(this._exception !== null)
+ {
+ //
+ // If there were no batch requests queued when the connection failed, we can safely
+ // retry with a new connection. Otherwise, we must throw to notify the caller that
+ // some previous batch requests were not sent.
+ //
+ if(this._batchStream.isEmpty())
+ {
+ throw new LocalExceptionWrapper(this._exception, true);
+ }
+ else
+ {
+ throw this._exception;
+ }
+ }
+
+ Debug.assert(this._state > StateNotValidated);
+ Debug.assert(this._state < StateClosing);
+
+ if(this._batchStream.isEmpty())
+ {
+ try
+ {
+ this._batchStream.writeBlob(Protocol.requestBatchHdr);
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.setStateEx(StateClosed, ex);
+ }
+ throw ex;
+ }
+ }
+
+ this._batchStreamInUse = true;
+ this._batchMarker = this._batchStream.size;
+ this._batchStream.swap(os);
+
+ //
+ // The batch stream now belongs to the caller, until
+ // finishBatchRequest() or abortBatchRequest() is called.
+ //
+ },
+ finishBatchRequest: function(os, compress)
+ {
+ try
+ {
+ //
+ // Get the batch stream back.
+ //
+ this._batchStream.swap(os);
+
+ if(this._exception !== null)
+ {
+ throw this._exception;
+ }
+
+ var flush = false;
+ if(this._batchAutoFlush)
+ {
+ //
+ // Throw memory limit exception if the first message added causes us to go over
+ // limit. Otherwise put aside the marshalled message that caused limit to be
+ // exceeded and rollback stream to the marker.
+ try
+ {
+ this._transceiver.checkSendSize(this._batchStream.buffer, this._instance.messageSizeMax());
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ if(this._batchRequestNum > 0)
+ {
+ flush = true;
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ }
+
+ if(flush)
+ {
+ //
+ // Temporarily save the last request.
+ //
+ var sz = this._batchStream.size - this._batchMarker;
+ this._batchStream.pos = this._batchMarker;
+ var lastRequest = this._batchStream.readBlob(sz);
+ this._batchStream.resize(this._batchMarker, false);
+
+ try
+ {
+ //
+ // Fill in the number of requests in the batch.
+ //
+ this._batchStream.pos = Protocol.headerSize;
+ this._batchStream.writeInt(this._batchRequestNum);
+
+ this.sendMessage(OutgoingMessage.createForStream(this._batchStream, this._batchRequestCompress,
+ true));
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.setStateEx(StateClosed, ex);
+ Debug.assert(this._exception !== null);
+ throw this._exception;
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ //
+ // Reset the batch stream.
+ //
+ this._batchStream =
+ new BasicStream(this._instance, Protocol.currentProtocolEncoding, this._batchAutoFlush);
+ this._batchRequestNum = 0;
+ this._batchRequestCompress = false;
+ this._batchMarker = 0;
+
+ //
+ // Check again if the last request doesn't exceed the maximum message size.
+ //
+ if(Protocol.requestBatchHdr.length + lastRequest.length > this._instance.messageSizeMax())
+ {
+ ExUtil.throwMemoryLimitException(
+ Protocol.requestBatchHdr.length + lastRequest.length,
+ this._instance.messageSizeMax());
+ }
+
+ //
+ // Start a new batch with the last message that caused us to go over the limit.
+ //
+ this._batchStream.writeBlob(Protocol.requestBatchHdr);
+ this._batchStream.writeBlob(lastRequest);
+ }
+
+ //
+ // Increment the number of requests in the batch.
+ //
+ ++this._batchRequestNum;
+
+ //
+ // We compress the whole batch if there is at least one compressed
+ // message.
+ //
+ if(compress)
+ {
+ this._batchRequestCompress = true;
+ }
+
+ //
+ // The batch stream is not in use anymore.
+ //
+ Debug.assert(this._batchStreamInUse);
+ this._batchStreamInUse = false;
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.abortBatchRequest();
+ }
+ throw ex;
+ }
+ },
+ abortBatchRequest: function()
+ {
+ this._batchStream = new BasicStream(this._instance, Protocol.currentProtocolEncoding, this._batchAutoFlush);
+ this._batchRequestNum = 0;
+ this._batchRequestCompress = false;
+ this._batchMarker = 0;
+
+ Debug.assert(this._batchStreamInUse);
+ this._batchStreamInUse = false;
+ },
+ flushBatchRequests: function()
+ {
+ var result = new ConnectionBatchOutgoingAsync(this, this._communicator, "flushBatchRequests");
+ try
+ {
+ result.__send();
+ }
+ catch(ex)
+ {
+ result.__exception(ex);
+ }
+ return result;
+ },
+ flushAsyncBatchRequests: function(outAsync)
+ {
+ if(this._exception !== null)
+ {
+ throw this._exception;
+ }
+
+ var status;
+ if(this._batchRequestNum === 0)
+ {
+ outAsync.__sent(this);
+ return AsyncStatus.Sent;
+ }
+
+ //
+ // Fill in the number of requests in the batch.
+ //
+ this._batchStream.pos = Protocol.headerSize;
+ this._batchStream.writeInt(this._batchRequestNum);
+
+ this._batchStream.swap(outAsync.__os());
+
+ try
+ {
+ status = this.sendMessage(OutgoingMessage.create(outAsync, outAsync.__os(), this._batchRequestCompress,
+ 0));
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.setStateEx(StateClosed, ex);
+ Debug.assert(this._exception !== null);
+ throw this._exception;
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ //
+ // Reset the batch stream.
+ //
+ this._batchStream = new BasicStream(this._instance, Protocol.currentProtocolEncoding, this._batchAutoFlush);
+ this._batchRequestNum = 0;
+ this._batchRequestCompress = false;
+ this._batchMarker = 0;
+ return status;
+ },
+ sendResponse: function(os, compressFlag)
+ {
+ Debug.assert(this._state > StateNotValidated);
+
+ try
+ {
+ if(--this._dispatchCount === 0)
+ {
+ if(this._state === StateFinished)
+ {
+ this._reaper.add(this);
+ }
+ this.checkState();
+ }
+
+ if(this._state >= StateClosed)
+ {
+ Debug.assert(this._exception !== null);
+ throw this._exception;
+ }
+
+ this.sendMessage(OutgoingMessage.createForStream(os, compressFlag !== 0, true));
+
+ if(this._state === StateClosing && this._dispatchCount === 0)
+ {
+ this.initiateShutdown();
+ }
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.setStateEx(StateClosed, ex);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ },
+ sendNoResponse: function()
+ {
+ Debug.assert(this._state > StateNotValidated);
+ try
+ {
+ if(--this._dispatchCount === 0)
+ {
+ if(this._state === StateFinished)
+ {
+ this._reaper.add(this);
+ }
+ this.checkState();
+ }
+
+ if(this._state >= StateClosed)
+ {
+ Debug.assert(this._exception !== null);
+ throw this._exception;
+ }
+
+ if(this._state === StateClosing && this._dispatchCount === 0)
+ {
+ this.initiateShutdown();
+ }
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.setStateEx(StateClosed, ex);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ },
+ endpoint: function()
+ {
+ return this._endpoint;
+ },
+ setAdapter: function(adapter)
+ {
+ if(this._state <= StateNotValidated || this._state >= StateClosing)
+ {
+ return;
+ }
+ Debug.assert(this._state < StateClosing);
+
+ this._adapter = adapter;
+
+ if(this._adapter !== null)
+ {
+ this._servantManager = this._adapter.getServantManager();
+ if(this._servantManager === null)
+ {
+ this._adapter = null;
+ }
+ }
+ else
+ {
+ this._servantManager = null;
+ }
+ },
+ getAdapter: function()
+ {
+ return this._adapter;
+ },
+ getEndpoint: function()
+ {
+ return this._endpoint;
+ },
+ createProxy: function(ident)
+ {
+ //
+ // Create a reference and return a reverse proxy for this
+ // reference.
+ //
+ return this._instance.proxyFactory().referenceToProxy(
+ this._instance.referenceFactory().createFixed(ident, this));
+ },
+ message: function(operation)
+ {
+ if(this._state >= StateClosed)
+ {
+ return;
+ }
+
+ this.unscheduleTimeout(operation);
+ //
+ // Keep reading until no more data is available.
+ //
+ this._hasMoreData.value = (operation & SocketOperation.Read) !== 0;
+ do
+ {
+ var info = null;
+
+ try
+ {
+ if((operation & SocketOperation.Write) !== 0 && this._writeStream.buffer.remaining > 0)
+ {
+ if(!this._transceiver.write(this._writeStream.buffer))
+ {
+ Debug.assert(!this._writeStream.isEmpty());
+ this.scheduleTimeout(SocketOperation.Write, this._endpoint.timeout());
+ return;
+ }
+ Debug.assert(this._writeStream.buffer.remaining === 0);
+ }
+ if((operation & SocketOperation.Read) !== 0 && !this._readStream.isEmpty())
+ {
+ if(this._readHeader) // Read header if necessary.
+ {
+ if(!this._transceiver.read(this._readStream.buffer, this._hasMoreData))
+ {
+ //
+ // We didn't get enough data to complete the header.
+ //
+ return;
+ }
+
+ Debug.assert(this._readStream.buffer.remaining === 0);
+ this._readHeader = false;
+
+ var pos = this._readStream.pos;
+ if(pos < Protocol.headerSize)
+ {
+ //
+ // This situation is possible for small UDP packets.
+ //
+ throw new Ice.IllegalMessageSizeException();
+ }
+
+ this._readStream.pos = 0;
+ var magic0 = this._readStream.readByte();
+ var magic1 = this._readStream.readByte();
+ var magic2 = this._readStream.readByte();
+ var magic3 = this._readStream.readByte();
+ if(magic0 !== Protocol.magic[0] || magic1 !== Protocol.magic[1] ||
+ magic2 !== Protocol.magic[2] || magic3 !== Protocol.magic[3])
+ {
+ var bme = new Ice.BadMagicException();
+ bme.badMagic = Ice.Buffer.createNative([magic0, magic1, magic2, magic3]);
+ throw bme;
+ }
+
+ this._readProtocol.__read(this._readStream);
+ Protocol.checkSupportedProtocol(this._readProtocol);
+
+ this._readProtocolEncoding.__read(this._readStream);
+ Protocol.checkSupportedProtocolEncoding(this._readProtocolEncoding);
+
+ this._readStream.readByte(); // messageType
+ this._readStream.readByte(); // compress
+ var size = this._readStream.readInt();
+ if(size < Protocol.headerSize)
+ {
+ throw new Ice.IllegalMessageSizeException();
+ }
+ if(size > this._instance.messageSizeMax())
+ {
+ ExUtil.throwMemoryLimitException(size, this._instance.messageSizeMax());
+ }
+ if(size > this._readStream.size)
+ {
+ this._readStream.resize(size);
+ }
+ this._readStream.pos = pos;
+ }
+
+ if(this._readStream.pos != this._readStream.size)
+ {
+ if(this._endpoint.datagram())
+ {
+ throw new Ice.DatagramLimitException(); // The message was truncated.
+ }
+ else
+ {
+ if(!this._transceiver.read(this._readStream.buffer, this._hasMoreData))
+ {
+ Debug.assert(!this._readStream.isEmpty());
+ this.scheduleTimeout(SocketOperation.Read, this._endpoint.timeout());
+ return;
+ }
+ Debug.assert(this._readStream.buffer.remaining === 0);
+ }
+ }
+ }
+
+ if(this._state <= StateNotValidated)
+ {
+ if(this._state === StateNotInitialized && !this.initialize())
+ {
+ return;
+ }
+
+ if(this._state <= StateNotValidated && !this.validate())
+ {
+ return;
+ }
+
+ this._transceiver.unregister();
+
+ //
+ // We start out in holding state.
+ //
+ this.setState(StateHolding);
+ }
+ else
+ {
+ Debug.assert(this._state <= StateClosing);
+
+ //
+ // We parse messages first, if we receive a close
+ // connection message we won't send more messages.
+ //
+ if((operation & SocketOperation.Read) !== 0)
+ {
+ info = this.parseMessage();
+ }
+
+ if((operation & SocketOperation.Write) !== 0)
+ {
+ this.sendNextMessage();
+ }
+
+ //
+ // We increment the dispatch count to prevent the
+ // communicator destruction during the callback.
+ //
+ if(info !== null && info.outAsync !== null)
+ {
+ ++this._dispatchCount;
+ }
+ }
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.DatagramLimitException) // Expected.
+ {
+ if(this._warnUdp)
+ {
+ this._logger.warning("maximum datagram size of " + this._readStream.pos + " exceeded");
+ }
+ this._readStream.resize(Protocol.headerSize);
+ this._readStream.pos = 0;
+ this._readHeader = true;
+ return;
+ }
+ else if(ex instanceof Ice.SocketException)
+ {
+ this.setStateEx(StateClosed, ex);
+ return;
+ }
+ else if(ex instanceof Ice.LocalException)
+ {
+ if(this._endpoint.datagram())
+ {
+ if(this._warn)
+ {
+ this._logger.warning("datagram connection exception:\n" + ex + '\n' + this._desc);
+ }
+ this._readStream.resize(Protocol.headerSize);
+ this._readStream.pos = 0;
+ this._readHeader = true;
+ }
+ else
+ {
+ this.setStateEx(StateClosed, ex);
+ }
+ return;
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ if(this._acmTimeout > 0)
+ {
+ this._acmAbsoluteTimeoutMillis = Date.now() + this._acmTimeout * 1000;
+ }
+
+ this.dispatch(info);
+ }
+ while(this._hasMoreData.value);
+ },
+ dispatch: function(info)
+ {
+ //
+ // Notify the factory that the connection establishment and
+ // validation has completed.
+ //
+ if(this._startPromise !== null)
+ {
+ this._startPromise.succeed();
+ this._startPromise = null;
+ }
+
+ if(info !== null)
+ {
+ if(info.outAsync !== null)
+ {
+ info.outAsync.__finished(info.stream);
+ }
+
+ if(info.invokeNum > 0)
+ {
+ this.invokeAll(info.stream, info.invokeNum, info.requestId, info.compress, info.servantManager,
+ info.adapter);
+ }
+ }
+
+ //
+ // Decrease dispatch count.
+ //
+ if(info !== null && info.outAsync !== null)
+ {
+ if(--this._dispatchCount === 0)
+ {
+ if(this._state === StateClosing && !this._shutdownInitiated)
+ {
+ try
+ {
+ this.initiateShutdown();
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.setStateEx(StateClosed, ex);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ }
+ else if(this._state === StateFinished)
+ {
+ this._reaper.add(this);
+ }
+ this.checkState();
+ }
+ }
+ },
+ finish: function()
+ {
+ Debug.assert(this._state === StateClosed);
+ this.unscheduleTimeout(SocketOperation.Read | SocketOperation.Write | SocketOperation.Connect);
+
+ if(this._startPromise !== null)
+ {
+ this._startPromise.fail(this._exception);
+ this._startPromise = null;
+ }
+
+ if(this._sendStreams.length > 0)
+ {
+ if(!this._writeStream.isEmpty())
+ {
+ //
+ // Return the stream to the outgoing call. This is important for
+ // retriable AMI calls which are not marshalled again.
+ //
+ var message = this._sendStreams[0];
+ this._writeStream.swap(message.stream);
+ }
+
+ //
+ // NOTE: for twoway requests which are not sent, finished can be called twice: the
+ // first time because the outgoing is in the _sendStreams set and the second time
+ // because it's either in the _requests/_asyncRequests set. This is fine, only the
+ // first call should be taken into account by the implementation of finished.
+ //
+ for(var i = 0; i < this._sendStreams.length; ++i)
+ {
+ var p = this._sendStreams[i];
+ if(p.requestId > 0)
+ {
+ this._asyncRequests.delete(p.requestId);
+ }
+ p.finished(this._exception);
+ }
+ this._sendStreams = [];
+ }
+
+ for(var e = this._asyncRequests.entries; e !== null; e = e.next)
+ {
+ e.value.__finishedEx(this._exception, true);
+ }
+ this._asyncRequests.clear();
+
+ //
+ // This must be done last as this will cause waitUntilFinished() to return (and communicator
+ // objects such as the timer might be destroyed too).
+ //
+ if(this._dispatchCount === 0)
+ {
+ this._reaper.add(this);
+ }
+ this.setState(StateFinished);
+ },
+ toString: function()
+ {
+ return this._desc;
+ },
+ timedOut: function(event)
+ {
+ if(this._state <= StateNotValidated)
+ {
+ this.setStateEx(StateClosed, new Ice.ConnectTimeoutException());
+ }
+ else if(this._state < StateClosing)
+ {
+ this.setStateEx(StateClosed, new Ice.TimeoutException());
+ }
+ else if(this._state === StateClosing)
+ {
+ this.setStateEx(StateClosed, new Ice.CloseTimeoutException());
+ }
+ },
+ type: function()
+ {
+ return this._type;
+ },
+ timeout: function()
+ {
+ return this._endpoint.timeout();
+ },
+ getInfo: function()
+ {
+ if(this._state >= StateClosed)
+ {
+ throw this._exception;
+ }
+ var info = this._transceiver.getInfo();
+ info.adapterName = this._adapter !== null ? this._adapter.getName() : "";
+ info.incoming = this._incoming;
+ return info;
+ },
+ exception: function(ex)
+ {
+ this.setStateEx(StateClosed, ex);
+ },
+ invokeException: function(ex, invokeNum)
+ {
+ //
+ // Fatal exception while invoking a request. Since sendResponse/sendNoResponse isn't
+ // called in case of a fatal exception we decrement this._dispatchCount here.
+ //
+
+ this.setStateEx(StateClosed, ex);
+
+ if(invokeNum > 0)
+ {
+ Debug.assert(this._dispatchCount > 0);
+ this._dispatchCount -= invokeNum;
+ Debug.assert(this._dispatchCount >= 0);
+ if(this._dispatchCount === 0)
+ {
+ if(this._state === StateFinished)
+ {
+ this._reaper.add(this);
+ }
+ this.checkState();
+ }
+ }
+ },
+ setStateEx: function(state, ex)
+ {
+ Debug.assert(ex instanceof Ice.LocalException);
+
+ //
+ // If setState() is called with an exception, then only closed
+ // and closing states are permissible.
+ //
+ Debug.assert(state >= StateClosing);
+
+ if(this._state === state) // Don't switch twice.
+ {
+ return;
+ }
+
+ if(this._exception === null)
+ {
+ this._exception = ex;
+
+ //
+ // We don't warn if we are not validated.
+ //
+ if(this._warn && this._validated)
+ {
+ //
+ // Don't warn about certain expected exceptions.
+ //
+ if(!(this._exception instanceof Ice.CloseConnectionException ||
+ this._exception instanceof Ice.ForcedCloseConnectionException ||
+ this._exception instanceof Ice.ConnectionTimeoutException ||
+ this._exception instanceof Ice.CommunicatorDestroyedException ||
+ this._exception instanceof Ice.ObjectAdapterDeactivatedException ||
+ (this._exception instanceof Ice.ConnectionLostException && this._state === StateClosing)))
+ {
+ this.warning("connection exception", this._exception);
+ }
+ }
+ }
+
+ //
+ // We must set the new state before we notify requests of any
+ // exceptions. Otherwise new requests may retry on a
+ // connection that is not yet marked as closed or closing.
+ //
+ this.setState(state);
+ },
+ setState: function(state)
+ {
+ //
+ // We don't want to send close connection messages if the endpoint
+ // only supports oneway transmission from client to server.
+ //
+ if(this._endpoint.datagram() && state === StateClosing)
+ {
+ state = StateClosed;
+ }
+
+ //
+ // Skip graceful shutdown if we are destroyed before validation.
+ //
+ if(this._state <= StateNotValidated && state === StateClosing)
+ {
+ state = StateClosed;
+ }
+
+ if(this._state === state) // Don't switch twice.
+ {
+ return;
+ }
+
+ try
+ {
+ switch(state)
+ {
+ case StateNotInitialized:
+ {
+ Debug.assert(false);
+ break;
+ }
+
+ case StateNotValidated:
+ {
+ if(this._state !== StateNotInitialized)
+ {
+ Debug.assert(this._state === StateClosed);
+ return;
+ }
+ //
+ // Register to receive validation message.
+ //
+ if(!this._endpoint.datagram() && !this._incoming)
+ {
+ //
+ // Once validation is complete, a new connection starts out in the
+ // Holding state. We only want to register the transceiver now if we
+ // need to receive data in order to validate the connection.
+ //
+ this._transceiver.register();
+ }
+ break;
+ }
+
+ case StateActive:
+ {
+ //
+ // Can only switch from holding or not validated to
+ // active.
+ //
+ if(this._state !== StateHolding && this._state !== StateNotValidated)
+ {
+ return;
+ }
+ this._transceiver.register();
+ break;
+ }
+
+ case StateHolding:
+ {
+ //
+ // Can only switch from active or not validated to
+ // holding.
+ //
+ if(this._state !== StateActive && this._state !== StateNotValidated)
+ {
+ return;
+ }
+ if(this._state === StateActive)
+ {
+ this._transceiver.unregister();
+ }
+ break;
+ }
+
+ case StateClosing:
+ {
+ //
+ // Can't change back from closed.
+ //
+ if(this._state >= StateClosed)
+ {
+ return;
+ }
+ if(this._state === StateHolding)
+ {
+ // We need to continue to read in closing state.
+ this._transceiver.register();
+ }
+ break;
+ }
+
+ case StateClosed:
+ {
+ if(this._state === StateFinished)
+ {
+ return;
+ }
+ this._transceiver.unregister();
+ break;
+ }
+
+ case StateFinished:
+ {
+ Debug.assert(this._state === StateClosed);
+ this._transceiver.close();
+ this._communicator = null;
+ break;
+ }
+ }
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ var msg = "unexpected connection exception:\n " + this._desc + "\n" + ExUtil.toString(ex);
+ this._instance.initializationData().logger.error(msg);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ //
+ // We only register with the connection monitor if our new state
+ // is StateActive. Otherwise we unregister with the connection
+ // monitor, but only if we were registered before, i.e., if our
+ // old state was StateActive.
+ //
+ if(this._acmTimeout > 0)
+ {
+ if(state === StateActive)
+ {
+ this._instance.connectionMonitor().add(this);
+ }
+ else if(this._state === StateActive)
+ {
+ this._instance.connectionMonitor().remove(this);
+ }
+ }
+
+ this._state = state;
+
+ if(this._state === StateClosing && this._dispatchCount === 0)
+ {
+ try
+ {
+ this.initiateShutdown();
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.setStateEx(StateClosed, ex);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ }
+ else if(this._state === StateClosed)
+ {
+ this.finish();
+ }
+
+ this.checkState();
+ },
+ initiateShutdown: function()
+ {
+ Debug.assert(this._state === StateClosing);
+ Debug.assert(this._dispatchCount === 0);
+ Debug.assert(!this._shutdownInitiated);
+
+ if(!this._endpoint.datagram())
+ {
+ //
+ // Before we shut down, we send a close connection
+ // message.
+ //
+ var os = new BasicStream(this._instance, Protocol.currentProtocolEncoding, false);
+ os.writeBlob(Protocol.magic);
+ Protocol.currentProtocol.__write(os);
+ Protocol.currentProtocolEncoding.__write(os);
+ os.writeByte(Protocol.closeConnectionMsg);
+ os.writeByte(0); // compression status: always report 0 for CloseConnection.
+ os.writeInt(Protocol.headerSize); // Message size.
+
+ var status = this.sendMessage(OutgoingMessage.createForStream(os, false, false));
+ if((status & AsyncStatus.Sent) > 0)
+ {
+ //
+ // Schedule the close timeout to wait for the peer to close the connection.
+ //
+ this.scheduleTimeout(SocketOperation.Write, this.closeTimeout());
+ }
+
+ //
+ // The CloseConnection message should be sufficient. Closing the write
+ // end of the socket is probably an artifact of how things were done
+ // in IIOP. In fact, shutting down the write end of the socket causes
+ // problems on Windows by preventing the peer from using the socket.
+ // For example, the peer is no longer able to continue writing a large
+ // message after the socket is shutdown.
+ //
+ //this._transceiver.shutdownWrite();
+ }
+ },
+ initialize: function()
+ {
+ var s = this._transceiver.initialize(this._readStream.buffer, this._writeStream.buffer);
+ if(s != SocketOperation.None)
+ {
+ this.scheduleTimeout(s, this.connectTimeout());
+ return false;
+ }
+
+ //
+ // Update the connection description once the transceiver is initialized.
+ //
+ this._desc = this._transceiver.toString();
+ this.setState(StateNotValidated);
+ return true;
+ },
+ validate: function()
+ {
+ if(!this._endpoint.datagram()) // Datagram connections are always implicitly validated.
+ {
+ if(this._adapter !== null) // The server side has the active role for connection validation.
+ {
+ if(this._writeStream.size === 0)
+ {
+ this._writeStream.writeBlob(Protocol.magic);
+ Protocol.currentProtocol.__write(this._writeStream);
+ Protocol.currentProtocolEncoding.__write(this._writeStream);
+ this._writeStream.writeByte(Protocol.validateConnectionMsg);
+ this._writeStream.writeByte(0); // Compression status (always zero for validate connection).
+ this._writeStream.writeInt(Protocol.headerSize); // Message size.
+ TraceUtil.traceSend(this._writeStream, this._logger, this._traceLevels);
+ this._writeStream.prepareWrite();
+ }
+
+ if(this._writeStream.pos != this._writeStream.size &&
+ !this._transceiver.write(this._writeStream.buffer))
+ {
+ this.scheduleTimeout(SocketOperation.Write, this.connectTimeout());
+ return false;
+ }
+ }
+ else // The client side has the passive role for connection validation.
+ {
+ if(this._readStream.size === 0)
+ {
+ this._readStream.resize(Protocol.headerSize);
+ this._readStream.pos = 0;
+ }
+
+ if(this._readStream.pos !== this._readStream.size &&
+ !this._transceiver.read(this._readStream.buffer, this._hasMoreData))
+ {
+ this.scheduleTimeout(SocketOperation.Read, this.connectTimeout());
+ return false;
+ }
+
+ Debug.assert(this._readStream.pos === Protocol.headerSize);
+ this._readStream.pos = 0;
+ var m = this._readStream.readBlob(4);
+ if(m[0] !== Protocol.magic[0] || m[1] !== Protocol.magic[1] ||
+ m[2] !== Protocol.magic[2] || m[3] !== Protocol.magic[3])
+ {
+ var bme = new Ice.BadMagicException();
+ bme.badMagic = m;
+ throw bme;
+ }
+
+ this._readProtocol.__read(this._readStream);
+ Protocol.checkSupportedProtocol(this._readProtocol);
+
+ this._readProtocolEncoding.__read(this._readStream);
+ Protocol.checkSupportedProtocolEncoding(this._readProtocolEncoding);
+
+ var messageType = this._readStream.readByte();
+ if(messageType !== Protocol.validateConnectionMsg)
+ {
+ throw new Ice.ConnectionNotValidatedException();
+ }
+ this._readStream.readByte(); // Ignore compression status for validate connection.
+ var size = this._readStream.readInt();
+ if(size !== Protocol.headerSize)
+ {
+ throw new Ice.IllegalMessageSizeException();
+ }
+ TraceUtil.traceRecv(this._readStream, this._logger, this._traceLevels);
+ this._validated = true;
+ }
+ }
+
+ this._writeStream.resize(0);
+ this._writeStream.pos = 0;
+
+ this._readStream.resize(Protocol.headerSize);
+ this._readHeader = true;
+ this._readStream.pos = 0;
+
+ return true;
+ },
+ sendNextMessage: function()
+ {
+ if(this._sendStreams.length === 0)
+ {
+ return;
+ }
+
+ Debug.assert(!this._writeStream.isEmpty() && this._writeStream.pos === this._writeStream.size);
+ try
+ {
+ while(true)
+ {
+ //
+ // Notify the message that it was sent.
+ //
+ var message = this._sendStreams.shift();
+ this._writeStream.swap(message.stream);
+ message.sent(this);
+
+ //
+ // If there's nothing left to send, we're done.
+ //
+ if(this._sendStreams.length === 0)
+ {
+ break;
+ }
+
+ //
+ // If we are in the closed state, don't continue sending.
+ //
+ // The connection can be in the closed state if parseMessage
+ // (called before sendNextMessage by message()) closes the
+ // connection.
+ //
+ if(this._state >= StateClosed)
+ {
+ return;
+ }
+
+ //
+ // Otherwise, prepare the next message stream for writing.
+ //
+ message = this._sendStreams[0];
+ Debug.assert(!message.prepared);
+ var stream = message.stream;
+
+ stream.pos = 10;
+ stream.writeInt(stream.size);
+ stream.prepareWrite();
+ message.prepared = true;
+
+ if(message.outAsync !== null)
+ {
+ TraceUtil.trace("sending asynchronous request", stream, this._logger, this._traceLevels);
+ }
+ else
+ {
+ TraceUtil.traceSend(stream, this._logger, this._traceLevels);
+ }
+ this._writeStream.swap(message.stream);
+
+ //
+ // Send the message.
+ //
+ if(this._writeStream.pos != this._writeStream.size &&
+ !this._transceiver.write(this._writeStream.buffer))
+ {
+ Debug.assert(!this._writeStream.isEmpty());
+ this.scheduleTimeout(SocketOperation.Write, this._endpoint.timeout());
+ return;
+ }
+ }
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.setState(StateClosed, ex);
+ return;
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ Debug.assert(this._writeStream.isEmpty());
+
+ //
+ // If all the messages were sent and we are in the closing state, we schedule
+ // the close timeout to wait for the peer to close the connection.
+ //
+ if(this._state === StateClosing)
+ {
+ this.scheduleTimeout(SocketOperation.Write, this.closeTimeout());
+ }
+ },
+ sendMessage: function(message)
+ {
+ if(this._sendStreams.length > 0)
+ {
+ message.doAdopt();
+ this._sendStreams.push(message);
+ return AsyncStatus.Queued;
+ }
+ Debug.assert(this._state < StateClosed);
+
+ Debug.assert(!message.prepared);
+
+ var stream = message.stream;
+ stream.pos = 10;
+ stream.writeInt(stream.size);
+ stream.prepareWrite();
+ message.prepared = true;
+
+ TraceUtil.trace("sending asynchronous request", message.stream, this._logger, this._traceLevels);
+
+ if(this._transceiver.write(message.stream.buffer))
+ {
+ //
+ // Entire buffer was written immediately.
+ //
+ message.sent(this);
+ if(this._acmTimeout > 0)
+ {
+ this._acmAbsoluteTimeoutMillis = Date.now() + this._acmTimeout * 1000;
+ }
+ return AsyncStatus.Sent;
+ }
+ message.doAdopt();
+
+ this._writeStream.swap(message.stream);
+ this._sendStreams.push(message);
+ this.scheduleTimeout(SocketOperation.Write, this._endpoint.timeout());
+
+ return AsyncStatus.Queued;
+ },
+ parseMessage: function()
+ {
+ Debug.assert(this._state > StateNotValidated && this._state < StateClosed);
+
+ var info = new MessageInfo(this._instance);
+
+ this._readStream.swap(info.stream);
+ this._readStream.resize(Protocol.headerSize);
+ this._readStream.pos = 0;
+ this._readHeader = true;
+
+ //
+ // Connection is validated on first message. This is only used by
+ // setState() to check wether or not we can print a connection
+ // warning (a client might close the connection forcefully if the
+ // connection isn't validated).
+ //
+ this._validated = true;
+
+ Debug.assert(info.stream.pos === info.stream.size);
+
+ try
+ {
+ //
+ // We don't need to check magic and version here. This has already
+ // been done by the caller.
+ //
+ info.stream.pos = 8;
+ var messageType = info.stream.readByte();
+ info.compress = info.stream.readByte();
+ if(info.compress === 2)
+ {
+ var ex = new Ice.FeatureNotSupportedException();
+ ex.unsupportedFeature = "Cannot uncompress compressed message";
+ throw ex;
+ }
+ info.stream.pos = Protocol.headerSize;
+
+ switch(messageType)
+ {
+ case Protocol.closeConnectionMsg:
+ {
+ TraceUtil.traceRecv(info.stream, this._logger, this._traceLevels);
+ if(this._endpoint.datagram())
+ {
+ if(this._warn)
+ {
+ this._logger.warning("ignoring close connection message for datagram connection:\n" +
+ this._desc);
+ }
+ }
+ else
+ {
+ this.setStateEx(StateClosed, new Ice.CloseConnectionException());
+ }
+ break;
+ }
+
+ case Protocol.requestMsg:
+ {
+ if(this._state === StateClosing)
+ {
+ TraceUtil.trace("received request during closing\n" +
+ "(ignored by server, client will retry)",
+ info.stream, this._logger, this._traceLevels);
+ }
+ else
+ {
+ TraceUtil.traceRecv(info.stream, this._logger, this._traceLevels);
+ info.requestId = info.stream.readInt();
+ info.invokeNum = 1;
+ info.servantManager = this._servantManager;
+ info.adapter = this._adapter;
+ ++this._dispatchCount;
+ }
+ break;
+ }
+
+ case Protocol.requestBatchMsg:
+ {
+ if(this._state === StateClosing)
+ {
+ TraceUtil.trace("received batch request during closing\n" +
+ "(ignored by server, client will retry)",
+ info.stream, this._logger, this._traceLevels);
+ }
+ else
+ {
+ TraceUtil.traceRecv(info.stream, this._logger, this._traceLevels);
+ info.invokeNum = info.stream.readInt();
+ if(info.invokeNum < 0)
+ {
+ info.invokeNum = 0;
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ info.servantManager = this._servantManager;
+ info.adapter = this._adapter;
+ this._dispatchCount += info.invokeNum;
+ }
+ break;
+ }
+
+ case Protocol.replyMsg:
+ {
+ TraceUtil.traceRecv(info.stream, this._logger, this._traceLevels);
+ info.requestId = info.stream.readInt();
+ info.outAsync = this._asyncRequests.get(info.requestId);
+ this._asyncRequests.delete(info.requestId);
+ if(info.outAsync === undefined)
+ {
+ throw new Ice.UnknownRequestIdException();
+ }
+ this.checkClose();
+ break;
+ }
+
+ case Protocol.validateConnectionMsg:
+ {
+ TraceUtil.traceRecv(info.stream, this._logger, this._traceLevels);
+ if(this._warn)
+ {
+ this._logger.warning("ignoring unexpected validate connection message:\n" + this._desc);
+ }
+ break;
+ }
+
+ default:
+ {
+ TraceUtil.trace("received unknown message\n(invalid, closing connection)",
+ info.stream, this._logger, this._traceLevels);
+ throw new Ice.UnknownMessageException();
+ }
+ }
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ if(this._endpoint.datagram())
+ {
+ if(this._warn)
+ {
+ this._logger.warning("datagram connection exception:\n" + ex + '\n' + this._desc);
+ }
+ }
+ else
+ {
+ this.setStateEx(StateClosed, ex);
+ }
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ return info;
+ },
+ invokeAll: function(stream, invokeNum, requestId, compress, servantManager, adapter)
+ {
+ var inc = null;
+ try
+ {
+ while(invokeNum > 0)
+ {
+ //
+ // Prepare the invocation.
+ //
+ var response = !this._endpoint.datagram() && requestId !== 0;
+ inc = new IncomingAsync(this._instance, this, adapter, response, compress, requestId);
+
+ //
+ // Dispatch the invocation.
+ //
+ inc.invoke(servantManager, stream);
+
+ --invokeNum;
+ inc = null;
+ }
+
+ stream.clear();
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.invokeException(ex, invokeNum);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ },
+ scheduleTimeout: function(op, timeout)
+ {
+ if(timeout < 0)
+ {
+ return;
+ }
+
+ var self = this;
+ if((op & SocketOperation.Read) !== 0)
+ {
+ this._readTimeoutId = this._timer.schedule(function() { self.timedOut(); }, timeout);
+ this._readTimeoutScheduled = true;
+ }
+ if((op & (SocketOperation.Write | SocketOperation.Connect)) !== 0)
+ {
+ this._writeTimeoutId = this._timer.schedule(function() { self.timedOut(); }, timeout);
+ this._writeTimeoutScheduled = true;
+ }
+ },
+ unscheduleTimeout: function(op)
+ {
+ if((op & SocketOperation.Read) !== 0 && this._readTimeoutScheduled)
+ {
+ this._timer.cancel(this._readTimeoutId);
+ this._readTimeoutScheduled = false;
+ }
+ if((op & (SocketOperation.Write | SocketOperation.Connect)) !== 0 && this._writeTimeoutScheduled)
+ {
+ this._timer.cancel(this._writeTimeoutId);
+ this._writeTimeoutScheduled = false;
+ }
+ },
+ connectTimeout: function()
+ {
+ var defaultsAndOverrides = this._instance.defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideConnectTimeout)
+ {
+ return defaultsAndOverrides.overrideConnectTimeoutValue;
+ }
+ else
+ {
+ return this._endpoint.timeout();
+ }
+ },
+ closeTimeout: function()
+ {
+ var defaultsAndOverrides = this._instance.defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideCloseTimeout)
+ {
+ return defaultsAndOverrides.overrideCloseTimeoutValue;
+ }
+ else
+ {
+ return this._endpoint.timeout();
+ }
+ },
+ warning: function(msg, ex)
+ {
+ this._logger.warning(msg + ":\n" + this._desc + "\n" + ExUtil.toString(ex));
+ },
+ checkState: function()
+ {
+ if(this._state < StateHolding || this._dispatchCount > 0)
+ {
+ return;
+ }
+
+ var i;
+ if(this._holdPromises.length > 0)
+ {
+ for(i = 0; i < this._holdPromises.length; ++i)
+ {
+ this._holdPromises[i].succeed();
+ }
+ this._holdPromises = [];
+ }
+
+ //
+ // We aren't finished until the state is finished and all
+ // outstanding requests are completed. Otherwise we couldn't
+ // guarantee that there are no outstanding calls when deactivate()
+ // is called on the servant locators.
+ //
+ if(this._state === StateFinished && this._finishedPromises.length > 0)
+ {
+ //
+ // Clear the OA. See bug 1673 for the details of why this is necessary.
+ //
+ this._adapter = null;
+
+ for(i = 0; i < this._finishedPromises.length; ++i)
+ {
+ this._finishedPromises[i].succeed();
+ }
+ this._finishedPromises = [];
+ }
+ }
+ });
+
+ // DestructionReason.
+ ConnectionI.ObjectAdapterDeactivated = 0;
+ ConnectionI.CommunicatorDestroyed = 1;
+
+ Ice.ConnectionI = ConnectionI;
+ global.Ice = Ice;
+
+ var OutgoingMessage = Class({
+ __init__: function()
+ {
+ this.stream = null;
+ this.outAsync = null;
+ this.compress = false;
+ this.requestId = 0;
+ this.prepared = false;
+ this.isSent = false;
+ },
+ doAdopt: function()
+ {
+ if(this.adopt)
+ {
+ var stream = new BasicStream(this.stream.instance, Protocol.currentProtocolEncoding);
+ stream.swap(this.stream);
+ this.stream = stream;
+ this.adopt = false;
+ }
+ },
+ sent: function(connection)
+ {
+ this.isSent = true; // The message is sent.
+
+ if(this.outAsync !== null)
+ {
+ this.outAsync.__sent(connection);
+ }
+ },
+ finished: function(ex)
+ {
+ if(this.outAsync !== null)
+ {
+ this.outAsync.__finishedEx(ex, this.isSent);
+ }
+ }
+ });
+
+ OutgoingMessage.createForStream = function(stream, compress, adopt)
+ {
+ var m = new OutgoingMessage();
+ m.stream = stream;
+ m.compress = compress;
+ m.adopt = adopt;
+ m.isSent = false;
+ m.requestId = 0;
+ m.outAsync = null;
+ return m;
+ };
+
+ OutgoingMessage.create = function(out, stream, compress, requestId)
+ {
+ var m = new OutgoingMessage();
+ m.stream = stream;
+ m.compress = compress;
+ m.outAsync = out;
+ m.requestId = requestId;
+ m.isSent = false;
+ m.adopt = false;
+ return m;
+ };
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ConnectionMonitor.js b/js/src/Ice/ConnectionMonitor.js
new file mode 100644
index 00000000000..dffe8f945a8
--- /dev/null
+++ b/js/src/Ice/ConnectionMonitor.js
@@ -0,0 +1,114 @@
+// **********************************************************************
+//
+// 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/Debug");
+ require("Ice/ExUtil");
+
+ var Ice = global.Ice || {};
+
+ var Debug = Ice.Debug;
+ var ExUtil = Ice.ExUtil;
+
+ var ConnectionMonitor = Ice.Class({
+ __init__: function(instance, interval)
+ {
+ this._instance = instance;
+ this._interval = interval;
+ this._scheduledInterval = 0;
+ this._timerToken = -1;
+ this._connections = [];
+ },
+ destroy: function()
+ {
+ Debug.assert(this._instance !== null);
+ this._instance.timer().cancel(this._timerToken);
+ this._instance = null;
+ this._connections = null;
+ },
+ checkIntervalForACM: function(acmTimeout)
+ {
+ if(acmTimeout <= 0)
+ {
+ return;
+ }
+
+ //
+ // If Ice.MonitorConnections isn't set (_interval == 0), the given ACM is used
+ // to determine the check interval: 1/10 of the ACM timeout with a minmal value
+ // of 5 seconds and a maximum value of 5 minutes.
+ //
+ // Note: if Ice.MonitorConnections is set, the timer is scheduled only if ACM
+ // is configured for the communicator or some object adapters.
+ //
+ var interval;
+ if(this._interval === 0)
+ {
+ interval = Math.floor(Math.min(300, Math.max(5, acmTimeout / 10)));
+ }
+ else if(this._scheduledInterval === this._interval)
+ {
+ return; // Nothing to do, the timer is already scheduled.
+ }
+ else
+ {
+ interval = this._interval;
+ }
+
+ //
+ // If no timer is scheduled yet or if the given ACM requires a smaller interval,
+ // we re-schedule the timer.
+ //
+ if(this._scheduledInterval === 0 || this._scheduledInterval > interval)
+ {
+ this._scheduledInterval = interval;
+ this._instance.timer().cancel(this._timerToken);
+ var self = this;
+ this._timerToken = this._instance.timer().scheduleRepeated(
+ function() { self.runTimerTask(); }, interval * 1000);
+ }
+ },
+ add: function(connection)
+ {
+ Debug.assert(this._instance !== null);
+ this._connections.push(connection);
+ },
+ remove: function(connection)
+ {
+ Debug.assert(this._instance !== null);
+ var pos = this._connections.indexOf(connection);
+ Debug.assert(pos !== -1);
+ this._connections.splice(pos, 1);
+ },
+ runTimerTask: function()
+ {
+ var now = Date.now();
+ for(var i = 0; i < this._connections.length; ++i)
+ {
+ try
+ {
+ this._connections[i].monitor(now);
+ }
+ catch(ex)
+ {
+ if(this._instance === null)
+ {
+ return;
+ }
+ var msg = "exception in connection monitor:\n" + ExUtil.toString(ex);
+ this._instance.initializationData().logger.error(msg);
+ }
+ }
+ }
+ });
+
+ Ice.ConnectionMonitor = ConnectionMonitor;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ConnectionReaper.js b/js/src/Ice/ConnectionReaper.js
new file mode 100644
index 00000000000..af8faa2ef26
--- /dev/null
+++ b/js/src/Ice/ConnectionReaper.js
@@ -0,0 +1,39 @@
+// **********************************************************************
+//
+// 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");
+
+ var Ice = global.Ice || {};
+
+ var ConnectionReaper = Ice.Class({
+ __init__: function()
+ {
+ this._connections = [];
+ },
+ add: function(connection)
+ {
+ this._connections.push(connection);
+ },
+ swapConnections: function()
+ {
+ if(this._connections.length === 0)
+ {
+ return null;
+ }
+ var connections = this._connections;
+ this._connections = [];
+ return connections;
+ }
+ });
+
+ Ice.ConnectionReaper = ConnectionReaper;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ConnectionRequestHandler.js b/js/src/Ice/ConnectionRequestHandler.js
new file mode 100644
index 00000000000..8027022d0c8
--- /dev/null
+++ b/js/src/Ice/ConnectionRequestHandler.js
@@ -0,0 +1,64 @@
+// **********************************************************************
+//
+// 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/Promise");
+ require("Ice/Class");
+ require("Ice/ReferenceMode");
+
+ var Ice = global.Ice || {};
+
+ var Promise = Ice.Promise;
+ var ReferenceMode = Ice.ReferenceMode;
+
+ var ConnectionRequestHandler = Ice.Class({
+ __init__: function(ref, connection, compress)
+ {
+ this._reference = ref;
+ this._response = ref.getMode() == ReferenceMode.ModeTwoway;
+ this._connection = connection;
+ this._compress = compress;
+ },
+ prepareBatchRequest: function(out)
+ {
+ this._connection.prepareBatchRequest(out);
+ },
+ finishBatchRequest: function(out)
+ {
+ this._connection.finishBatchRequest(out, this._compress);
+ },
+ abortBatchRequest: function()
+ {
+ this._connection.abortBatchRequest();
+ },
+ sendAsyncRequest: function(out)
+ {
+ return this._connection.sendAsyncRequest(out, this._compress, this._response);
+ },
+ flushAsyncBatchRequests: function(out)
+ {
+ return this._connection.flushAsyncBatchRequests(out);
+ },
+ getReference: function()
+ {
+ return this._reference;
+ },
+ getConnection: function()
+ {
+ return this._connection;
+ },
+ onConnection: function(r)
+ {
+ r.succeed(this._connection, r);
+ }
+ });
+
+ Ice.ConnectionRequestHandler = ConnectionRequestHandler;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Debug.js b/js/src/Ice/Debug.js
new file mode 100644
index 00000000000..01ea0a27282
--- /dev/null
+++ b/js/src/Ice/Debug.js
@@ -0,0 +1,28 @@
+// **********************************************************************
+//
+// 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){
+
+ var Ice = global.Ice || {};
+
+ var Debug = {
+ assert: function(b, msg)
+ {
+ if(!b)
+ {
+ console.log(msg === undefined ? "assertion failed" : msg);
+ console.log(Error().stack);
+ process.exit(1);
+ }
+ }
+ };
+
+ Ice.Debug = Debug;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/DefaultsAndOverrides.js b/js/src/Ice/DefaultsAndOverrides.js
new file mode 100644
index 00000000000..94da3a723c7
--- /dev/null
+++ b/js/src/Ice/DefaultsAndOverrides.js
@@ -0,0 +1,102 @@
+// **********************************************************************
+//
+// 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/FormatType");
+ require("Ice/EndpointTypes");
+ require("Ice/Protocol");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var FormatType = Ice.FormatType;
+ var EndpointSelectionType = Ice.EndpointSelectionType;
+ var Protocol = Ice.Protocol;
+
+ var DefaultsAndOverrides = function(properties)
+ {
+ var value;
+
+ this.defaultProtocol = properties.getPropertyWithDefault("Ice.Default.Protocol",
+ Ice.TcpEndpointFactory !== undefined ? "tcp" : "ws");
+
+ value = properties.getProperty("Ice.Default.Host");
+ this.defaultHost = value.length > 0 ? value : null;
+
+ value = properties.getProperty("Ice.Override.Timeout");
+ if(value.length > 0)
+ {
+ this.overrideTimeout = true;
+ this.overrideTimeoutValue = properties.getPropertyAsInt("Ice.Override.Timeout");
+ }
+ else
+ {
+ this.overrideTimeout = false;
+ this.overrideTimeoutValue = -1;
+ }
+
+ value = properties.getProperty("Ice.Override.ConnectTimeout");
+ if(value.length > 0)
+ {
+ this.overrideConnectTimeout = true;
+ this.overrideConnectTimeoutValue = properties.getPropertyAsInt("Ice.Override.ConnectTimeout");
+ }
+ else
+ {
+ this.overrideConnectTimeout = false;
+ this.overrideConnectTimeoutValue = -1;
+ }
+
+ value = properties.getProperty("Ice.Override.CloseTimeout");
+ if(value.length > 0)
+ {
+ this.overrideCloseTimeout = true;
+ this.overrideCloseTimeoutValue = properties.getPropertyAsInt("Ice.Override.CloseTimeout");
+ }
+ else
+ {
+ this.overrideCloseTimeout = false;
+ this.overrideCloseTimeoutValue = -1;
+ }
+
+ this.overrideCompress = false;
+ this.overrideSecure = false;
+
+ value = properties.getPropertyWithDefault("Ice.Default.EndpointSelection", "Random");
+ if(value === "Random")
+ {
+ this.defaultEndpointSelection = EndpointSelectionType.Random;
+ }
+ else if(value === "Ordered")
+ {
+ this.defaultEndpointSelection = EndpointSelectionType.Ordered;
+ }
+ else
+ {
+ var ex = new Ice.EndpointSelectionTypeParseException();
+ ex.str = "illegal value `" + value + "'; expected `Random' or `Ordered'";
+ throw ex;
+ }
+
+ this.defaultLocatorCacheTimeout = properties.getPropertyAsIntWithDefault("Ice.Default.LocatorCacheTimeout", -1);
+
+ this.defaultPreferSecure = properties.getPropertyAsIntWithDefault("Ice.Default.PreferSecure", 0) > 0;
+
+ value = properties.getPropertyWithDefault("Ice.Default.EncodingVersion",
+ Ice.encodingVersionToString(Protocol.currentEncoding));
+ this.defaultEncoding = Ice.stringToEncodingVersion(value);
+ Protocol.checkSupportedEncoding(this.defaultEncoding);
+
+ var slicedFormat = properties.getPropertyAsIntWithDefault("Ice.Default.SlicedFormat", 0) > 0;
+ this.defaultFormat = slicedFormat ? FormatType.SlicedFormat : FormatType.CompactFormat;
+ };
+
+ Ice.DefaultsAndOverrides = DefaultsAndOverrides;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/DispatchStatus.js b/js/src/Ice/DispatchStatus.js
new file mode 100644
index 00000000000..3a20e36aae4
--- /dev/null
+++ b/js/src/Ice/DispatchStatus.js
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+ var DispatchStatus = {DispatchOK: 0, DispatchUserException: 1, DispatchAsync: 2};
+ Ice.DispatchStatus = DispatchStatus;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/EndpointFactoryManager.js b/js/src/Ice/EndpointFactoryManager.js
new file mode 100644
index 00000000000..881c9cd998c
--- /dev/null
+++ b/js/src/Ice/EndpointFactoryManager.js
@@ -0,0 +1,146 @@
+// **********************************************************************
+//
+// 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/Debug");
+ require("Ice/OpaqueEndpointI");
+ require("Ice/Protocol");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ //
+ // Local aliases.
+ //
+ var Debug = Ice.Debug;
+ var BasicStream = Ice.BasicStream;
+ var EndpointParseException = Ice.EndpointParseException;
+ var OpaqueEndpointI = Ice.OpaqueEndpointI;
+ var Protocol = Ice.Protocol;
+
+ var EndpointFactoryManager = Ice.Class({
+ __init__: function(instance)
+ {
+ this._instance = instance;
+ this._factories = [];
+ },
+ add: function(factory)
+ {
+ for(var i = 0; i < this._factories.length; ++i)
+ {
+ Debug.assert(this._factories[i].type() != factory.type());
+ }
+
+ this._factories.push(factory);
+ },
+ get: function(type)
+ {
+ for(var i = 0; i < this._factories.length; ++i)
+ {
+ if(this._factories[i].type() === type)
+ {
+ return this._factories[i];
+ }
+ }
+ return null;
+ },
+ create: function(str, oaEndpoint)
+ {
+ var s = str.trim();
+ if(s.length === 0)
+ {
+ throw new EndpointParseException("value has no non-whitespace characters");
+ }
+
+ var protocol;
+ var rest = "";
+ var i, length;
+ var pos = s.search(/[ \t\n\r]+/);
+ if(pos === -1)
+ {
+ protocol = s;
+ }
+ else
+ {
+ protocol = s.substring(0, pos);
+ if(pos < s.length)
+ {
+ rest = s.substring(pos);
+ }
+ }
+
+ if(protocol === "default")
+ {
+ protocol = this._instance.defaultsAndOverrides().defaultProtocol;
+ }
+
+ for(i = 0, length = this._factories.length; i < length; ++i)
+ {
+ if(this._factories[i].protocol() === protocol)
+ {
+ return this._factories[i].create(rest, oaEndpoint);
+ }
+ }
+
+ //
+ // If the stringified endpoint is opaque, create an unknown endpoint,
+ // then see whether the type matches one of the known endpoints.
+ //
+ if(protocol === "opaque")
+ {
+ var ue = OpaqueEndpointI.fromString(rest);
+ for(i = 0, length = this._factories.length; i < length; ++i)
+ {
+ if(this._factories[i].type() == ue.type())
+ {
+ //
+ // Make a temporary stream, write the opaque endpoint data into the stream,
+ // and ask the factory to read the endpoint data from that stream to create
+ // the actual endpoint.
+ //
+ var bs = new BasicStream(this._instance, Protocol.currentProtocolEncoding, true);
+ ue.streamWrite(bs);
+ bs.pos = 0;
+ bs.readShort(); // type
+ return this._factories[i].read(bs);
+ }
+ }
+ return ue; // Endpoint is opaque, but we don't have a factory for its type.
+ }
+
+ return null;
+ },
+ read: function(s)
+ {
+ var type = s.readShort();
+
+ for(var i = 0; i < this._factories.length; ++i)
+ {
+ if(this._factories[i].type() == type)
+ {
+ return this._factories[i].read(s);
+ }
+ }
+ return OpaqueEndpointI.fromStream(type, s);
+ },
+ destroy: function()
+ {
+ for(var i = 0; i < this._factories.length; ++i)
+ {
+ this._factories[i].destroy();
+ }
+ this._factories = [];
+ }
+ });
+
+ Ice.EndpointFactoryManager = EndpointFactoryManager;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/EnumBase.js b/js/src/Ice/EnumBase.js
new file mode 100644
index 00000000000..a387219e81c
--- /dev/null
+++ b/js/src/Ice/EnumBase.js
@@ -0,0 +1,163 @@
+// **********************************************************************
+//
+// 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");
+
+ var Slice = global.Slice || {};
+ var Ice = global.Ice || {};
+ //
+ // Ice.EnumBase
+ //
+ var EnumBase = Ice.Class({
+ __init__: function(name, value)
+ {
+ this._name = name;
+ this._value = value;
+ },
+ equals: function(rhs)
+ {
+ if(this === rhs)
+ {
+ return true;
+ }
+
+ var proto = Object.getPrototypeOf(this);
+ if(!(rhs instanceof proto.constructor))
+ {
+ return false;
+ }
+
+ return this._value == rhs._value;
+ },
+ hashCode: function()
+ {
+ return this._value;
+ },
+ toString: function()
+ {
+ return this._name;
+ }
+ });
+
+ var prototype = EnumBase.prototype;
+
+ Object.defineProperty(prototype, 'name', {
+ enumerable: true,
+ get: function() { return this._name; }
+ });
+
+ Object.defineProperty(prototype, 'value', {
+ enumerable: true,
+ get: function() { return this._value; }
+ });
+
+ var EnumHelper = Ice.Class({
+ __init__: function(enumType)
+ {
+ this._enumType = enumType;
+ },
+ write: function(os, v)
+ {
+ this._enumType.__write(os, v);
+ },
+ writeOpt: function(os, tag, v)
+ {
+ this._enumType.__writeOpt(os, tag, v);
+ },
+ read: function(is)
+ {
+ return this._enumType.__read(is);
+ },
+ readOpt: function(is, tag)
+ {
+ return this._enumType.__readOpt(is, tag);
+ }
+ });
+
+ Ice.EnumHelper = EnumHelper;
+
+ var write = function(os, v)
+ {
+ os.writeEnum(v);
+ };
+ var writeOpt = function(os, tag, v)
+ {
+ os.writeOptValue(tag, Ice.OptionalFormat.Size, Ice.BasicStream.prototype.writeEnum, v);
+ };
+
+ Slice.defineEnum = function(enumerators)
+ {
+ var type = function(n, v)
+ {
+ EnumBase.call(this, n, v);
+ };
+
+ type.prototype = new EnumBase();
+ type.prototype.constructor = type;
+
+ var enums = [];
+ var maxValue = 0;
+ for(var e in enumerators)
+ {
+ var value = enumerators[e];
+ var enumerator = new type(e, value);
+ enums[value] = enumerator;
+ Object.defineProperty(type, e, {
+ enumerable: true,
+ value: enumerator
+ });
+ if(value > maxValue)
+ {
+ maxValue = value;
+ }
+ }
+
+ Object.defineProperty(type, "minWireSize", {
+ get: function(){ return 1; }
+ });
+
+ type.__write = write;
+ type.__read = function(is)
+ {
+ return is.readEnum(type);
+ };
+ type.__writeOpt = writeOpt;
+ type.__readOpt = function(is, tag)
+ {
+ return is.readOptEnum(tag, type);
+ };
+
+ type.__helper = new EnumHelper(type);
+
+ Object.defineProperty(type, 'valueOf', {
+ value: function(v) {
+ if(v === undefined)
+ {
+ return type;
+ }
+ return enums[v]; }
+ });
+
+ Object.defineProperty(type, 'maxValue', {
+ value: maxValue
+ });
+
+ Object.defineProperty(type.prototype, 'maxValue', {
+ value: maxValue
+ });
+
+ return type;
+ };
+
+ Ice.EnumBase = EnumBase;
+
+ global.Slice = Slice;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ExUtil.js b/js/src/Ice/ExUtil.js
new file mode 100644
index 00000000000..c2fc0f0669d
--- /dev/null
+++ b/js/src/Ice/ExUtil.js
@@ -0,0 +1,53 @@
+// **********************************************************************
+//
+// 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){
+ //
+ // Exception utilities
+ //
+
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ //
+ // Local aliases.
+ //
+ var UnexpectedObjectException = Ice.UnexpectedObjectException;
+ var MemoryLimitException = Ice.MemoryLimitException;
+ var ExUtil = {};
+
+ ExUtil.toString = function(ex)
+ {
+ if(!ex.stack)
+ {
+ return ex.toString();
+ }
+ else
+ {
+ return ex.stack;
+ }
+ };
+
+ ExUtil.throwUOE = function(expectedType, v)
+ {
+ var type = v.ice_id();
+ throw new UnexpectedObjectException("expected element of type `" + expectedType + "' but received '" +
+ type, type, expectedType);
+ };
+
+ ExUtil.throwMemoryLimitException = function(requested, maximum)
+ {
+ throw new MemoryLimitException("requested " + requested + " bytes, maximum allowed is " + maximum +
+ " bytes (see Ice.MessageSizeMax)");
+ };
+
+ Ice.ExUtil = ExUtil;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Exception.js b/js/src/Ice/Exception.js
new file mode 100644
index 00000000000..032ace3339d
--- /dev/null
+++ b/js/src/Ice/Exception.js
@@ -0,0 +1,241 @@
+// **********************************************************************
+//
+// 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");
+
+ var Slice = global.Slice || {};
+ var Ice = global.Ice || {};
+
+ var Class = Ice.Class;
+
+ //
+ // Ice.Exception
+ //
+ var Exception = Class(Error, {
+ __init__: function(cause)
+ {
+ this.ice_cause = cause;
+ },
+ ice_name: function()
+ {
+ return "Ice::Exception";
+ },
+ toString: function()
+ {
+ var s = this.ice_name();
+ for(var key in this)
+ {
+ if(key == "stack" || key.indexOf("_") === 0)
+ {
+ continue;
+ }
+
+ var value = this[key];
+ if(typeof value == "function")
+ {
+ continue;
+ }
+
+ s += "\n " + key + ": \"" + value + "\"";
+ }
+ return s;
+ }
+ });
+
+ Exception.captureStackTrace = function(object)
+ {
+ var stack = new Error().stack;
+
+ var formattedStack;
+
+ //
+ // In IE 10 and greater the stack will be filled once the Error is throw
+ // we don't need to do anything.
+ //
+ if(stack !== undefined)
+ {
+
+ var name = object.ice_name ? object.ice_name().replace("::", ".") : "";
+ Object.defineProperty(object, "stack", {
+ get: function(){
+ return stack;
+ }
+ });
+ }
+ };
+
+ Ice.Exception = Exception;
+
+ //
+ // Ice.LocalException
+ //
+ var LocalException = Class(Exception, {
+ __init__: function(cause)
+ {
+ Exception.call(this, cause);
+ Exception.captureStackTrace(this);
+ },
+ ice_name: function()
+ {
+ return "Ice::LocalException";
+ }
+ });
+
+ Ice.LocalException = LocalException;
+
+ Slice.defineLocalException = function(constructor, base, name)
+ {
+ var ex = constructor;
+ ex.prototype = new base();
+ ex.prototype.constructor = ex;
+ ex.prototype.ice_name = function()
+ {
+ return name;
+ };
+ return ex;
+ };
+
+ //
+ // Ice.UserException
+ //
+ var UserException = Class(Exception, {
+ __init__: function(cause)
+ {
+ Exception.call(this, cause);
+ Exception.captureStackTrace(this);
+ },
+ ice_name: function()
+ {
+ return "Ice::UserException";
+ },
+ __write: function(os)
+ {
+ os.startWriteException(null);
+ __writeImpl(this, os, this.__mostDerivedType());
+ os.endWriteException();
+ },
+ __read: function(is)
+ {
+ is.startReadException();
+ __readImpl(this, is, this.__mostDerivedType());
+ is.endReadException(false);
+ },
+ __usesClasses: function()
+ {
+ return false;
+ }
+ });
+ Ice.UserException = UserException;
+
+ //
+ // Private methods
+ //
+
+ var __writeImpl = function(obj, os, type)
+ {
+ //
+ // The __writeImpl method is a recursive method that goes down the
+ // class hierarchy to marshal each slice of the class using the
+ // generated __writeMemberImpl method.
+ //
+
+ if(type === undefined || type === UserException)
+ {
+ return; // Don't marshal anything for Ice.UserException
+ }
+
+ os.startWriteSlice(type.__id, -1, type.__parent === UserException);
+ if(type.prototype.__writeMemberImpl)
+ {
+ type.prototype.__writeMemberImpl.call(obj, os);
+ }
+ os.endWriteSlice();
+ __writeImpl(obj, os, type.__parent);
+ };
+
+ var __readImpl = function(obj, is, type)
+ {
+ //
+ // The __readImpl method is a recursive method that goes down the
+ // class hierarchy to marshal each slice of the class using the
+ // generated __readMemberImpl method.
+ //
+
+ if(type === undefined || type === UserException)
+ {
+ return; // Don't marshal anything for UserException
+ }
+
+ is.startReadSlice();
+ if(type.prototype.__readMemberImpl)
+ {
+ type.prototype.__readMemberImpl.call(obj, is);
+ }
+ is.endReadSlice();
+ __readImpl(obj, is, type.__parent);
+ };
+
+ var __writePreserved = function(os)
+ {
+ //
+ // For Slice exceptions which are marked "preserved", the implementation of this method
+ // replaces the Ice.Object.prototype.__write method.
+ //
+ os.startWriteException(this.__slicedData);
+ __writeImpl(this, os, this.__mostDerivedType());
+ os.endWriteException();
+ };
+
+ var __readPreserved = function(is)
+ {
+ //
+ // For Slice exceptions which are marked "preserved", the implementation of this method
+ // replaces the Ice.Object.prototype.__read method.
+ //
+ is.startReadException();
+ __readImpl(this, is, this.__mostDerivedType());
+ this.__slicedData = is.endReadException(true);
+ };
+
+ Slice.defineUserException = function(constructor, base, name, writeImpl, readImpl, preserved, usesClasses)
+ {
+ var ex = constructor;
+ ex.__parent = base;
+ ex.prototype = new base();
+ ex.__id = "::" + name;
+ ex.prototype.ice_name = function()
+ {
+ return name;
+ };
+
+ ex.prototype.constructor = ex;
+ ex.prototype.__mostDerivedType = function() { return ex; };
+ if(preserved)
+ {
+ ex.prototype.__write = __writePreserved;
+ ex.prototype.__read = __readPreserved;
+ }
+ ex.prototype.__writeMemberImpl = writeImpl;
+ ex.prototype.__readMemberImpl = readImpl;
+
+ if(usesClasses)
+ {
+ ex.prototype.__usesClasses = function()
+ {
+ return true;
+ };
+ }
+
+ return ex;
+ };
+
+ global.Slice = Slice;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/FormatType.js b/js/src/Ice/FormatType.js
new file mode 100644
index 00000000000..0cc2820e780
--- /dev/null
+++ b/js/src/Ice/FormatType.js
@@ -0,0 +1,18 @@
+// **********************************************************************
+//
+// 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/EnumBase");
+
+ var Ice = global.Ice || {};
+
+ Ice.FormatType = Slice.defineEnum({'DefaultFormat':0, 'CompactFormat':1, 'SlicedFormat':2});
+
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/HashMap.js b/js/src/Ice/HashMap.js
new file mode 100644
index 00000000000..aa09448c85b
--- /dev/null
+++ b/js/src/Ice/HashMap.js
@@ -0,0 +1,417 @@
+// **********************************************************************
+//
+// 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/StringUtil");
+
+ var Slice = global.Slice || {};
+ var Ice = global.Ice || {};
+
+ var StringUtil = Ice.StringUtil;
+
+ function setInternal(map, key, value, hash, index)
+ {
+ //
+ // Search for an entry with the same key.
+ //
+ for(var e = map._table[index]; e !== null; e = e._nextInBucket)
+ {
+ if(e._hash === hash && map.keysEqual(key, e._key))
+ {
+ //
+ // Found a match, update the value.
+ //
+ e._value = value;
+ return undefined;
+ }
+ }
+
+ //
+ // No match found, add a new entry.
+ //
+ map.add(key, value, hash, index);
+ return undefined;
+ }
+
+ var HashMap = Ice.Class({
+ __init__: function(h)
+ {
+ this._size = 0;
+ this._head = null;
+ this._initialCapacity = 32;
+ this._loadFactor = 0.75;
+ this._table = [];
+ this._keyComparator = function(k1, k2) { return k1 === k2; };
+ this._valueComparator = function(k1, k2) { return k1 === k2; };
+
+ var i, length;
+ if(h === undefined || h === null || h._size === 0)
+ {
+ this._threshold = this._initialCapacity * this._loadFactor;
+ for(i = 0; i < this._initialCapacity; i++)
+ {
+ this._table[i] = null;
+ }
+ }
+ else
+ {
+ this._threshold = h._threshold;
+ this._keyComparator = h._keyComparator;
+ this._valueComparator = h._valueComparator;
+ length = h._table.length;
+ this._table.length = length;
+ for(i = 0; i < length; i++)
+ {
+ this._table[i] = null;
+ }
+ this.merge(h);
+ }
+ },
+ set: function(key, value)
+ {
+ var hash = this.computeHash(key);
+
+ var index = this.hashIndex(hash, this._table.length);
+
+ return setInternal(this, key, value, hash, index);
+ },
+ get: function(key)
+ {
+ var e = this.findEntry(key, this.computeHash(key));
+ return e !== undefined ? e._value : undefined;
+ },
+ has: function(key)
+ {
+ return this.findEntry(key, this.computeHash(key)) !== undefined;
+ },
+ delete: function(key)
+ {
+ var hash = this.computeHash(key);
+
+ var index = this.hashIndex(hash, this._table.length);
+
+ //
+ // Search for an entry with the same key.
+ //
+ var prev = null;
+ for(var e = this._table[index]; e !== null; e = e._nextInBucket)
+ {
+ if(e._hash === hash && this.keysEqual(key, e._key))
+ {
+ //
+ // Found a match.
+ //
+ this._size--;
+
+ //
+ // Remove from bucket.
+ //
+ if(prev !== null)
+ {
+ prev._nextInBucket = e._nextInBucket;
+ }
+ else
+ {
+ this._table[index] = e._nextInBucket;
+ }
+
+ //
+ // Unlink the entry.
+ //
+ if(e._prev !== null)
+ {
+ e._prev._next = e._next;
+ }
+ if(e._next !== null)
+ {
+ e._next._prev = e._prev;
+ }
+
+ if(this._head === e)
+ {
+ this._head = e._next;
+ }
+
+ return e._value;
+ }
+
+ prev = e;
+ }
+
+ return undefined;
+ },
+ clear: function()
+ {
+ for(var i = 0; i < this._table.length; ++i)
+ {
+ this._table[i] = null;
+ }
+ this._head = null;
+ this._size = 0;
+ },
+ forEach: function(fn, obj)
+ {
+ obj = obj === undefined ? fn : obj;
+ for(var e = this._head; e !== null; e = e._next)
+ {
+ fn.call(obj, e._key, e._value);
+ }
+ },
+ equals: function(other)
+ {
+ if(other === null || !(other instanceof HashMap) || this._size !== other._size)
+ {
+ return false;
+ }
+
+ for(var e = this._head; e !== null; e = e._next)
+ {
+ var oe = other.findEntry(e._key, e._hash);
+ if(oe === undefined || !this.valuesEqual(e._value, oe._value))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ },
+ clone: function()
+ {
+ return new HashMap(this);
+ },
+ merge: function(from)
+ {
+ for(var e = from._head; e !== null; e = e._next)
+ {
+ setInternal(this, e._key, e._value, e._hash, this.hashIndex(e._hash, this._table.length));
+ }
+ },
+ add: function(key, value, hash, index)
+ {
+ //
+ // Create a new table entry.
+ //
+ /*
+ var e =
+ {
+ key: key,
+ value: value,
+ prev: null,
+ next: null,
+ _hash: hash
+ }
+ */
+ var e = Object.create(null, {
+ "key": {
+ enumerable: true,
+ get: function() { return this._key; }
+ },
+ "value": {
+ enumerable: true,
+ get: function() { return this._value; }
+ },
+ "next": {
+ enumerable: true,
+ get: function() { return this._next; }
+ },
+ "_key": {
+ enumerable: false,
+ writable: true,
+ value: key
+ },
+ "_value": {
+ enumerable: false,
+ writable: true,
+ value: value
+ },
+ "_prev": {
+ enumerable: false,
+ writable: true,
+ value: null
+ },
+ "_next": {
+ enumerable: false,
+ writable: true,
+ value: null
+ },
+ "_nextInBucket": {
+ enumerable: false,
+ writable: true,
+ value: null
+ },
+ "_hash": {
+ enumerable: false,
+ writable: true,
+ value: hash
+ }
+ });
+ e._nextInBucket = this._table[index];
+ this._table[index] = e;
+
+ e._next = this._head;
+ if(this._head !== null)
+ {
+ this._head._prev = e;
+ }
+ this._head = e;
+
+ this._size++;
+ if(this._size >= this._threshold)
+ {
+ this.resize(this._table.length * 2);
+ }
+ },
+ resize: function(capacity)
+ {
+ var oldTable = this._table;
+
+ var newTable = [];
+ for(var i = 0; i < capacity; i++)
+ {
+ newTable[i] = null;
+ }
+
+ //
+ // Re-assign all entries to buckets.
+ //
+ for(var e = this._head; e !== null; e = e._next)
+ {
+ var index = this.hashIndex(e._hash, capacity);
+ e._nextInBucket = newTable[index];
+ newTable[index] = e;
+ }
+
+ this._table = newTable;
+ this._threshold = (capacity * this._loadFactor);
+ },
+ findEntry: function(key, hash)
+ {
+ var index = this.hashIndex(hash, this._table.length);
+
+ //
+ // Search for an entry with the same key.
+ //
+ for(var e = this._table[index]; e !== null; e = e._nextInBucket)
+ {
+ if(e._hash === hash && this.keysEqual(key, e._key))
+ {
+ return e;
+ }
+ }
+
+ return undefined;
+ },
+ hashIndex: function(hash, len)
+ {
+ return hash & (len - 1);
+ },
+ computeHash: function(v)
+ {
+ if(typeof(v.hashCode) === "function")
+ {
+ return v.hashCode();
+ }
+
+ var hash = 0;
+ var type = typeof(v);
+ if(type === "string" || v instanceof String)
+ {
+ hash = StringUtil.hashCode(v);
+ }
+ else if(type === "number" || v instanceof Number)
+ {
+ hash = v.toFixed(0);
+ }
+ else if(type === "boolean" || v instanceof Boolean)
+ {
+ hash = v ? 1 : 0;
+ }
+ else if(v !== null)
+ {
+ throw "cannot compute hash for value of type " + type;
+ }
+ return hash;
+ },
+ keysEqual: function(k1, k2)
+ {
+ return this._keyComparator.call(this._keyComparator, k1, k2);
+ },
+ valuesEqual: function(v1, v2)
+ {
+ return this._valueComparator.call(this._valueComparator, v1, v2);
+ }
+ });
+
+ var prototype = HashMap.prototype;
+
+ Object.defineProperty(prototype, "size", {
+ get: function() { return this._size; }
+ });
+
+ Object.defineProperty(prototype, "entries", {
+ get: function() { return this._head; }
+ });
+
+ Object.defineProperty(prototype, "keyComparator", {
+ get: function() { return this._keyComparator; },
+ set: function(fn) { this._keyComparator = fn; }
+ });
+
+ Object.defineProperty(prototype, "valueComparator", {
+ get: function() { return this._valueComparator; },
+ set: function(fn) { this._valueComparator = fn; }
+ });
+
+ Object.defineProperty(HashMap, "compareEquals", {
+ get: function() { return function(o1, o2) { return o1.equals(o2); }; }
+ });
+
+ Slice.defineDictionary = function(module, name, helperName, keyHelper, valueHelper, fixed, useEquals, valueType)
+ {
+ if(useEquals)
+ {
+ //
+ // Define a constructor function for a dictionary whose key type requires
+ // comparison using an equals() method instead of the native comparison
+ // operators.
+ //
+ module[name] = function(h)
+ {
+ var r = new HashMap(h);
+ r.keyComparator = HashMap.compareEquals;
+ return r;
+ };
+ }
+ else
+ {
+ module[name] = HashMap;
+ }
+
+ var helper = null;
+ Object.defineProperty(module, helperName,
+ {
+ get: function()
+ {
+ if(helper === null)
+ {
+ /*jshint -W061 */
+ helper = Ice.StreamHelpers.generateDictHelper(eval(keyHelper), eval(valueHelper), fixed,
+ eval(valueType), module[name]);
+ /*jshint +W061 */
+ }
+ return helper;
+ }
+ });
+ };
+
+ Ice.HashMap = HashMap;
+ global.Slice = Slice;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/HashUtil.js b/js/src/Ice/HashUtil.js
new file mode 100644
index 00000000000..7fe2f3f0c8a
--- /dev/null
+++ b/js/src/Ice/HashUtil.js
@@ -0,0 +1,61 @@
+// **********************************************************************
+//
+// 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/StringUtil");
+
+ var Ice = global.Ice || {};
+
+ var StringUtil = Ice.StringUtil;
+
+ var HashUtil = {};
+
+ HashUtil.addBoolean = function(h, b)
+ {
+ return ((h << 5) + h) ^ (b ? 0 : 1);
+ };
+
+ HashUtil.addString = function(h, str)
+ {
+ if(str !== undefined && str !== null)
+ {
+ h = ((h << 5) + h) ^ StringUtil.hashCode(str);
+ }
+ return h;
+ };
+
+ HashUtil.addNumber = function(h, num)
+ {
+ return ((h << 5) + h) ^ num;
+ };
+
+ HashUtil.addHashable = function(h, obj)
+ {
+ if(obj !== undefined && obj !== null)
+ {
+ h = ((h << 5) + h) ^ obj.hashCode();
+ }
+ return h;
+ };
+
+ HashUtil.addArray = function(h, arr, hashCode)
+ {
+ if(arr !== undefined && arr !== null)
+ {
+ for(var i = 0; i < arr.length; ++i)
+ {
+ h = hashCode(h, arr[i]);
+ }
+ }
+ return h;
+ };
+
+ Ice.HashUtil = HashUtil;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Ice.js b/js/src/Ice/Ice.js
new file mode 100644
index 00000000000..d7ec2f807bd
--- /dev/null
+++ b/js/src/Ice/Ice.js
@@ -0,0 +1,39 @@
+// **********************************************************************
+//
+// 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(){
+ require("Ice/TcpEndpointFactory"); // Must be loaded before Communicator and Instance
+ require("Ice/Initialize");
+ require("Ice/Communicator");
+ require("Ice/HashMap");
+ require("Ice/Object");
+ require("Ice/Long");
+ require("Ice/Logger");
+ require("Ice/ObjectPrx");
+ require("Ice/Metrics");
+ require("Ice/Properties");
+ require("Ice/IdentityUtil");
+ require("Ice/ProcessLogger");
+ require("Ice/Protocol");
+ require("Ice/Identity");
+ require("Ice/Exception");
+ require("Ice/LocalException");
+ require("Ice/BuiltinSequences");
+ require("Ice/StreamHelpers");
+ require("Ice/Promise");
+ require("Ice/EndpointTypes");
+ require("Ice/Locator");
+ require("Ice/Router");
+ require("Ice/Version");
+ require("Ice/ObjectFactory");
+ require("Ice/Buffer");
+ require("Ice/ArrayUtil");
+ require("Ice/UnknownSlicedObject");
+ require("Ice/Process");
+}());
diff --git a/js/src/Ice/IdentityUtil.js b/js/src/Ice/IdentityUtil.js
new file mode 100644
index 00000000000..660e9043eef
--- /dev/null
+++ b/js/src/Ice/IdentityUtil.js
@@ -0,0 +1,228 @@
+// **********************************************************************
+//
+// 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/ExUtil");
+ require("Ice/StringUtil");
+ require("Ice/Identity");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var ExUtil = Ice.ExUtil;
+ var StringUtil = Ice.StringUtil;
+ var Identity = Ice.Identity;
+ var IdentityParseException = Ice.IdentityParseException;
+
+ Ice = global.Ice || {};
+ /**
+ * Converts a string to an object identity.
+ *
+ * @param s The string to convert.
+ *
+ * @return The converted object identity.
+ **/
+ Ice.stringToIdentity = function(s)
+ {
+ var ident = new Identity();
+
+ //
+ // Find unescaped separator.
+ //
+ var slash = -1;
+ var pos = 0;
+ while((pos = s.indexOf('/', pos)) !== -1)
+ {
+ if(pos === 0 || s.charAt(pos - 1) != '\\')
+ {
+ if(slash == -1)
+ {
+ slash = pos;
+ }
+ else
+ {
+ //
+ // Extra unescaped slash found.
+ //
+ var ex = new IdentityParseException();
+ ex.str = "unescaped backslash in identity `" + s + "'";
+ throw ex;
+ }
+ }
+ pos++;
+ }
+
+ if(slash == -1)
+ {
+ ident.category = "";
+ try
+ {
+ ident.name = StringUtil.unescapeString(s);
+ }
+ catch(e)
+ {
+ var ex = new IdentityParseException();
+ ex.str = "invalid identity name `" + s + "': " + ExUtil.toString(e);
+ throw ex;
+ }
+ }
+ else
+ {
+ try
+ {
+ ident.category = StringUtil.unescapeString(s, 0, slash);
+ }
+ catch(e)
+ {
+ var ex = new IdentityParseException();
+ ex.str = "invalid category in identity `" + s + "': " + ExUtil.toString(e);
+ throw ex;
+ }
+ if(slash + 1 < s.length)
+ {
+ try
+ {
+ ident.name = StringUtil.unescapeString(s, slash + 1, s.length);
+ }
+ catch(e)
+ {
+ var ex = new IdentityParseException();
+ ex.str = "invalid name in identity `" + s + "': " + ExUtil.toString(e);
+ throw ex;
+ }
+ }
+ else
+ {
+ ident.name = "";
+ }
+ }
+
+ return ident;
+ };
+
+ /**
+ * Converts an object identity to a string.
+ *
+ * @param ident The object identity to convert.
+ *
+ * @return The string representation of the object identity.
+ **/
+ Ice.identityToString = function(ident)
+ {
+ if(ident.category === null || ident.category.length === 0)
+ {
+ return StringUtil.escapeString(ident.name, "/");
+ }
+ else
+ {
+ return StringUtil.escapeString(ident.category, "/") + '/' + StringUtil.escapeString(ident.name, "/");
+ }
+ };
+
+ /**
+ * Compares the object identities of two proxies.
+ *
+ * @param lhs A proxy.
+ * @param rhs A proxy.
+ * @return -1 if the identity in <code>lhs</code> compares
+ * less than the identity in <code>rhs</code>; 0 if the identities
+ * compare equal; 1, otherwise.
+ *
+ * @see ProxyIdentityKey
+ * @see ProxyIdentityAndFacetKey
+ * @see ProxyIdentityAndFacetCompare
+ **/
+ Ice.proxyIdentityCompare = function(lhs, rhs)
+ {
+ if(lhs === rhs)
+ {
+ return 0;
+ }
+ else if(lhs === null && rhs !== null)
+ {
+ return -1;
+ }
+ else if(lhs !== null && rhs === null)
+ {
+ return 1;
+ }
+ else
+ {
+ var lhsIdentity = lhs.ice_getIdentity();
+ var rhsIdentity = rhs.ice_getIdentity();
+ var n;
+ if((n = lhsIdentity.name.localeCompare(rhsIdentity.name)) !== 0)
+ {
+ return n;
+ }
+ return lhsIdentity.category.localeCompare(rhsIdentity.category);
+ }
+ };
+
+ /**
+ * Compares the object identities and facets of two proxies.
+ *
+ * @param lhs A proxy.
+ * @param rhs A proxy.
+ * @return -1 if the identity and facet in <code>lhs</code> compare
+ * less than the identity and facet in <code>rhs</code>; 0 if the identities
+ * and facets compare equal; 1, otherwise.
+ *
+ * @see ProxyIdentityAndFacetKey
+ * @see ProxyIdentityKey
+ * @see ProxyIdentityCompare
+ **/
+ Ice.proxyIdentityAndFacetCompare = function(lhs, rhs)
+ {
+ if(lhs === rhs)
+ {
+ return 0;
+ }
+ else if(lhs === null && rhs !== null)
+ {
+ return -1;
+ }
+ else if(lhs !== null && rhs === null)
+ {
+ return 1;
+ }
+ else
+ {
+ var lhsIdentity = lhs.ice_getIdentity();
+ var rhsIdentity = rhs.ice_getIdentity();
+ var n;
+ if((n = lhsIdentity.name.localeCompare(rhsIdentity.name)) !== 0)
+ {
+ return n;
+ }
+ if((n = lhsIdentity.category.localeCompare(rhsIdentity.category)) !== 0)
+ {
+ return n;
+ }
+
+ var lhsFacet = lhs.ice_getFacet();
+ var rhsFacet = rhs.ice_getFacet();
+ if(lhsFacet === null && rhsFacet === null)
+ {
+ return 0;
+ }
+ else if(lhsFacet === null)
+ {
+ return -1;
+ }
+ else if(rhsFacet === null)
+ {
+ return 1;
+ }
+ return lhsFacet.localeCompare(rhsFacet);
+ }
+ };
+
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ImplicitContextI.js b/js/src/Ice/ImplicitContextI.js
new file mode 100644
index 00000000000..c05f1452e58
--- /dev/null
+++ b/js/src/Ice/ImplicitContextI.js
@@ -0,0 +1,145 @@
+// **********************************************************************
+//
+// 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/HashMap");
+ require("Ice/LocalException");
+ require("Ice/Current");
+ require("Ice/Class");
+
+ var Ice = global.Ice || {};
+
+ var HashMap = Ice.HashMap;
+ var InitializationException = Ice.InitializationException;
+
+ //
+ // The base class for all ImplicitContext implementations
+ //
+ var ImplicitContextI = Ice.Class({
+ __init__: function()
+ {
+ this._context = new HashMap();
+ },
+ getContext: function()
+ {
+ return new HashMap(this._context);
+ },
+ setContext: function(context)
+ {
+ if(context !== null && context.size > 0)
+ {
+ this._context = new HashMap(context);
+ }
+ else
+ {
+ this._context.clear();
+ }
+ },
+ containsKey: function(key)
+ {
+ if(key === null)
+ {
+ key = "";
+ }
+
+ return this._context.has(key);
+ },
+ get: function(key)
+ {
+ if(key === null)
+ {
+ key = "";
+ }
+
+ var val = this._context.get(key);
+ if(val === null)
+ {
+ val = "";
+ }
+
+ return val;
+ },
+ put: function(key, value)
+ {
+ if(key === null)
+ {
+ key = "";
+ }
+ if(value === null)
+ {
+ value = "";
+ }
+
+ var oldVal = this._context.get(key);
+ if(oldVal === null)
+ {
+ oldVal = "";
+ }
+
+ this._context.set(key, value);
+
+ return oldVal;
+ },
+ remove: function(key)
+ {
+ if(key === null)
+ {
+ key = "";
+ }
+
+ var val = this._context.get(key);
+ this._context.delete(key);
+
+ if(val === null)
+ {
+ val = "";
+ }
+ return val;
+ },
+ write: function(prxContext, os)
+ {
+ if(prxContext.size === 0)
+ {
+ Ice.ContextHelper.write(os, this._context);
+ }
+ else
+ {
+ var ctx = null;
+ if(this._context.size === 0)
+ {
+ ctx = prxContext;
+ }
+ else
+ {
+ ctx = new HashMap(this._context);
+ ctx.merge(prxContext);
+ }
+ Ice.ContextHelper.write(os, ctx);
+ }
+ }
+ });
+
+ ImplicitContextI.create = function(kind)
+ {
+ if(kind.length === 0 || kind === "None")
+ {
+ return null;
+ }
+ else if(kind === "Shared")
+ {
+ return new ImplicitContextI();
+ }
+ else
+ {
+ throw new InitializationException("'" + kind + "' is not a valid value for Ice.ImplicitContext");
+ }
+ };
+ Ice.ImplicitContextI = ImplicitContextI;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
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));
diff --git a/js/src/Ice/Initialize.js b/js/src/Ice/Initialize.js
new file mode 100644
index 00000000000..e1dd0c4a2b1
--- /dev/null
+++ b/js/src/Ice/Initialize.js
@@ -0,0 +1,104 @@
+// **********************************************************************
+//
+// 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/Protocol");
+ require("Ice/LocalException");
+ require("Ice/Communicator");
+ require("Ice/Properties");
+
+ var Ice = global.Ice || {};
+ var Protocol = Ice.Protocol;
+
+ //
+ // Ice.InitializationData
+ //
+ Ice.InitializationData = function()
+ {
+ this.properties = null;
+ this.logger = null;
+ };
+
+ Ice.InitializationData.prototype.clone = function()
+ {
+ var r = new Ice.InitializationData();
+ r.properties = this.properties;
+ r.logger = this.logger;
+ return r;
+ };
+
+ //
+ // Ice.initialize()
+ //
+ Ice.initialize = function(arg1, arg2)
+ {
+ var args = null;
+ var initData = null;
+
+ if(arg1 instanceof Array)
+ {
+ args = arg1;
+ }
+ else if(arg1 instanceof Ice.InitializationData)
+ {
+ initData = arg1;
+ }
+ else if(arg1 !== undefined && arg1 !== null)
+ {
+ throw new Ice.InitializationException("invalid argument to initialize");
+ }
+
+ if(arg2 !== undefined && arg2 !== null)
+ {
+ if(arg2 instanceof Ice.InitializationData && initData === null)
+ {
+ initData = arg2;
+ }
+ else
+ {
+ throw new Ice.InitializationException("invalid argument to initialize");
+ }
+
+ }
+
+ if(initData === null)
+ {
+ initData = new Ice.InitializationData();
+ }
+ else
+ {
+ initData = initData.clone();
+ }
+ initData.properties = Ice.createProperties(args, initData.properties);
+
+ var result = new Ice.Communicator(initData);
+ result.finishSetup(null);
+ return result;
+ };
+
+ //
+ // Ice.createProperties()
+ //
+ Ice.createProperties = function(args, defaults)
+ {
+ return new Ice.Properties(args, defaults);
+ };
+
+ Ice.currentProtocol = function()
+ {
+ return Protocol.currentProtocol.clone();
+ };
+
+ Ice.currentEncoding = function()
+ {
+ return Protocol.currentEncoding.clone();
+ };
+
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Instance.js b/js/src/Ice/Instance.js
new file mode 100644
index 00000000000..92ba88894d7
--- /dev/null
+++ b/js/src/Ice/Instance.js
@@ -0,0 +1,573 @@
+// **********************************************************************
+//
+// 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/AsyncResultBase");
+ require("Ice/ConnectionMonitor");
+ require("Ice/Debug");
+ require("Ice/DefaultsAndOverrides");
+ require("Ice/EndpointFactoryManager");
+ require("Ice/HashMap");
+ require("Ice/ImplicitContextI");
+ require("Ice/IdentityUtil");
+ require("Ice/LocatorManager");
+ require("Ice/Logger");
+ require("Ice/ObjectAdapterFactory");
+ require("Ice/ObjectFactoryManager");
+ require("Ice/OutgoingConnectionFactory");
+ require("Ice/Promise");
+ require("Ice/Properties");
+ require("Ice/ProxyFactory");
+ require("Ice/RetryQueue");
+ require("Ice/RouterManager");
+ require("Ice/Timer");
+ require("Ice/TraceLevels");
+ require("Ice/Reference");
+ require("Ice/LocalException");
+ require("Ice/Exception");
+ require("Ice/ProcessLogger");
+
+ //
+ // We don't load the endpoint factories here, instead the Ice.js
+ // file for NodeJS loads the TcpEndpointFactory and the Ice.js
+ // file for the web browser includes the IceWS endpoint factory.
+ //
+ //require("Ice/TcpEndpointFactory");
+ //require("IceWS/EndpointFactory");
+
+ var Ice = global.Ice || {};
+
+ var AsyncResultBase = Ice.AsyncResultBase;
+ var ConnectionMonitor = Ice.ConnectionMonitor;
+ var Debug = Ice.Debug;
+ var DefaultsAndOverrides = Ice.DefaultsAndOverrides;
+ var EndpointFactoryManager = Ice.EndpointFactoryManager;
+ var HashMap = Ice.HashMap;
+ var ImplicitContextI = Ice.ImplicitContextI;
+ var LocatorManager = Ice.LocatorManager;
+ var Logger = Ice.Logger;
+ var ObjectAdapterFactory = Ice.ObjectAdapterFactory;
+ var ObjectFactoryManager = Ice.ObjectFactoryManager;
+ var OutgoingConnectionFactory = Ice.OutgoingConnectionFactory;
+ var Promise = Ice.Promise;
+ var Properties = Ice.Properties;
+ var ProxyFactory = Ice.ProxyFactory;
+ var RetryQueue = Ice.RetryQueue;
+ var RouterManager = Ice.RouterManager;
+ var Timer = Ice.Timer;
+ var TraceLevels = Ice.TraceLevels;
+ var ReferenceFactory = Ice.ReferenceFactory;
+
+ var StateActive = 0;
+ var StateDestroyInProgress = 1;
+ var StateDestroyed = 2;
+
+ //
+ // Instance - only for use by Communicator
+ //
+ var Instance = Ice.Class({
+ __init__: function(initData)
+ {
+ this._state = StateActive;
+ this._initData = initData;
+
+ this._traceLevels = null;
+ this._defaultsAndOverrides = null;
+ this._messageSizeMax = null;
+ this._clientACM = null;
+ this._serverACM = null;
+ this._implicitContext = null;
+ this._routerManager = null;
+ this._locatorManager = null;
+ this._referenceFactory = null;
+ this._proxyFactory = null;
+ this._outgoingConnectionFactory = null;
+ this._connectionMonitor = null;
+ this._servantFactoryManager = null;
+ this._objectAdapterFactory = null;
+ this._protocolSupport = null;
+ this._retryQueue = null;
+ this._endpointHostResolver = null;
+ this._endpointFactoryManager = null;
+ },
+ initializationData: function()
+ {
+ //
+ // No check for destruction. It must be possible to access the
+ // initialization data after destruction.
+ //
+ // This value is immutable.
+ //
+ return this._initData;
+ },
+ traceLevels: function()
+ {
+ // This value is immutable.
+ Debug.assert(this._traceLevels !== null);
+ return this._traceLevels;
+ },
+ defaultsAndOverrides: function()
+ {
+ // This value is immutable.
+ Debug.assert(this._defaultsAndOverrides !== null);
+ return this._defaultsAndOverrides;
+ },
+ routerManager: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._routerManager !== null);
+ return this._routerManager;
+ },
+ locatorManager: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._locatorManager !== null);
+ return this._locatorManager;
+ },
+ referenceFactory: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._referenceFactory !== null);
+ return this._referenceFactory;
+ },
+ proxyFactory: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._proxyFactory !== null);
+ return this._proxyFactory;
+ },
+ outgoingConnectionFactory: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._outgoingConnectionFactory !== null);
+ return this._outgoingConnectionFactory;
+ },
+ preferIPv6: function()
+ {
+ return this._preferIPv6;
+ },
+ connectionMonitor: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._connectionMonitor !== null);
+ return this._connectionMonitor;
+ },
+ servantFactoryManager: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._servantFactoryManager !== null);
+ return this._servantFactoryManager;
+ },
+ objectAdapterFactory: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._objectAdapterFactory !== null);
+ return this._objectAdapterFactory;
+ },
+ protocolSupport: function()
+ {
+ if(this._state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ return this._protocolSupport;
+ },
+ retryQueue: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._retryQueue !== null);
+ return this._retryQueue;
+ },
+ timer: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._timer !== null);
+ return this._timer;
+ },
+ endpointFactoryManager: function()
+ {
+ if(this._state === StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Debug.assert(this._endpointFactoryManager !== null);
+ return this._endpointFactoryManager;
+ },
+ messageSizeMax: function()
+ {
+ // This value is immutable.
+ return this._messageSizeMax;
+ },
+ clientACM: function()
+ {
+ // This value is immutable.
+ return this._clientACM;
+ },
+ serverACM: function()
+ {
+ // This value is immutable.
+ return this._serverACM;
+ },
+ getImplicitContext: function()
+ {
+ return this._implicitContext;
+ },
+ stringToIdentity: function(s)
+ {
+ return Ice.stringToIdentity(s);
+ },
+ identityToString: function(ident)
+ {
+ return Ice.identityToString(ident);
+ },
+
+ setDefaultLocator: function(locator)
+ {
+ if(this._state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ this._referenceFactory = this._referenceFactory.setDefaultLocator(locator);
+ },
+ setDefaultRouter: function(router)
+ {
+ if(this._state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ this._referenceFactory = this._referenceFactory.setDefaultRouter(router);
+ },
+ setLogger: function(logger)
+ {
+ this._initData.logger = logger;
+ },
+ finishSetup: function(communicator, promise)
+ {
+ //
+ // If promise == null, it means the caller is requesting a synchronous setup.
+ // Otherwise, we resolve the promise after all initialization is complete.
+ //
+
+ try
+ {
+ this._timer = new Timer();
+
+ if(this._initData.properties === null)
+ {
+ this._initData.properties = Properties.createProperties();
+ }
+
+ if(this._initData.logger === null)
+ {
+ this._initData.logger = Ice.getProcessLogger();
+ }
+
+ this._traceLevels = new TraceLevels(this._initData.properties);
+
+ this._defaultsAndOverrides = new DefaultsAndOverrides(this._initData.properties);
+
+ var defMessageSizeMax = 1024;
+ var num = this._initData.properties.getPropertyAsIntWithDefault("Ice.MessageSizeMax", defMessageSizeMax);
+ if(num < 1)
+ {
+ this._messageSizeMax = defMessageSizeMax * 1024; // Ignore non-sensical values.
+ }
+ else if(num > 0x7fffffff / 1024)
+ {
+ this._messageSizeMax = 0x7fffffff;
+ }
+ else
+ {
+ this._messageSizeMax = num * 1024; // Property is in kilobytes, _messageSizeMax in bytes
+ }
+
+ //
+ // Client ACM enabled by default. Server ACM disabled by default.
+ //
+ this._clientACM = this._initData.properties.getPropertyAsIntWithDefault("Ice.ACM.Client", 60);
+ this._serverACM = this._initData.properties.getPropertyAsInt("Ice.ACM.Server");
+
+ this._implicitContext = ImplicitContextI.create(this._initData.properties.getProperty("Ice.ImplicitContext"));
+
+ this._routerManager = new RouterManager();
+
+ this._locatorManager = new LocatorManager(this._initData.properties);
+
+ this._referenceFactory = new ReferenceFactory(this, communicator);
+
+ this._proxyFactory = new ProxyFactory(this);
+
+ this._endpointFactoryManager = new EndpointFactoryManager(this);
+
+ if(typeof(Ice.TcpEndpointFactory) !== "undefined")
+ {
+ this._endpointFactoryManager.add(new Ice.TcpEndpointFactory(this));
+ }
+
+ if(typeof(IceWS) !== "undefined" && typeof(IceWS.EndpointFactory) !== "undefined")
+ {
+ this._endpointFactoryManager.add(new IceWS.EndpointFactory(this, false));
+ this._endpointFactoryManager.add(new IceWS.EndpointFactory(this, true));
+ }
+
+ this._outgoingConnectionFactory = new OutgoingConnectionFactory(communicator, this);
+ this._servantFactoryManager = new ObjectFactoryManager();
+
+ this._objectAdapterFactory = new ObjectAdapterFactory(this, communicator);
+
+ this._retryQueue = new RetryQueue(this);
+
+ //
+ // Get default router and locator proxies. Don't move this
+ // initialization before the plug-in initialization!!! The proxies
+ // might depend on endpoint factories to be installed by plug-ins.
+ //
+ var router = Ice.RouterPrx.uncheckedCast(this._proxyFactory.propertyToProxy("Ice.Default.Router"));
+ if(router !== null)
+ {
+ this._referenceFactory = this._referenceFactory.setDefaultRouter(router);
+ }
+
+ var loc = Ice.LocatorPrx.uncheckedCast(this._proxyFactory.propertyToProxy("Ice.Default.Locator"));
+ if(loc !== null)
+ {
+ this._referenceFactory = this._referenceFactory.setDefaultLocator(loc);
+ }
+
+ //
+ // Create the connection monitor and ensure the interval for
+ // monitoring connections is appropriate for client & server
+ // ACM.
+ //
+ var interval = this._initData.properties.getPropertyAsInt("Ice.MonitorConnections");
+ this._connectionMonitor = new ConnectionMonitor(this, interval);
+ this._connectionMonitor.checkIntervalForACM(this._clientACM);
+ this._connectionMonitor.checkIntervalForACM(this._serverACM);
+
+ if(promise !== null)
+ {
+ promise.succeed(communicator);
+ }
+ }
+ catch(ex)
+ {
+ if(promise !== null)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.destroy().finally(function()
+ {
+ promise.fail(ex);
+ });
+ }
+ else
+ {
+ promise.fail(ex);
+ }
+ }
+ else
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.destroy();
+ }
+ throw ex;
+ }
+ }
+ },
+ //
+ // Only for use by Ice.CommunicatorI
+ //
+ destroy: function()
+ {
+ var promise = new AsyncResultBase(null, "destroy", null, this, null);
+
+ //
+ // If the _state is not StateActive then the instance is
+ // either being destroyed, or has already been destroyed.
+ //
+ if(this._state != StateActive)
+ {
+ promise.succeed(promise);
+ return promise;
+ }
+
+ //
+ // We cannot set state to StateDestroyed otherwise instance
+ // methods called during the destroy process (such as
+ // outgoingConnectionFactory() from
+ // ObjectAdapterI::deactivate() will cause an exception.
+ //
+ this._state = StateDestroyInProgress;
+
+ var self = this;
+ Ice.Promise.try(
+ function()
+ {
+ if(self._objectAdapterFactory)
+ {
+ return self._objectAdapterFactory.shutdown();
+ }
+ }
+ ).then(
+ function()
+ {
+ if(self._outgoingConnectionFactory !== null)
+ {
+ self._outgoingConnectionFactory.destroy();
+ }
+
+ if(self._objectAdapterFactory !== null)
+ {
+ return self._objectAdapterFactory.destroy();
+ }
+ }
+ ).then(
+ function()
+ {
+ if(self._outgoingConnectionFactory !== null)
+ {
+ return self._outgoingConnectionFactory.waitUntilFinished();
+ }
+ }
+ ).then(
+ function()
+ {
+ if(self._retryQueue)
+ {
+ self._retryQueue.destroy();
+ }
+
+ self._objectAdapterFactory = null;
+ self._outgoingConnectionFactory = null;
+ self._retryQueue = null;
+
+ if(self._connectionMonitor)
+ {
+ self._connectionMonitor.destroy();
+ self._connectionMonitor = null;
+ }
+
+ if(self._timer)
+ {
+ self._timer.destroy();
+ self._timer = null;
+ }
+
+ if(self._servantFactoryManager)
+ {
+ self._servantFactoryManager.destroy();
+ self._servantFactoryManager = null;
+ }
+
+ if(self._referenceFactory)
+ {
+ //self._referenceFactory.destroy(); // No destroy function defined.
+ self._referenceFactory = null;
+ }
+
+ // self._proxyFactory.destroy(); // No destroy function defined.
+ self._proxyFactory = null;
+
+ if(self._routerManager)
+ {
+ self._routerManager.destroy();
+ self._routerManager = null;
+ }
+
+ if(self._locatorManager)
+ {
+ self._locatorManager.destroy();
+ self._locatorManager = null;
+ }
+
+ if(self._endpointFactoryManager)
+ {
+ self._endpointFactoryManager.destroy();
+ self._endpointFactoryManager = null;
+ }
+
+ self._state = StateDestroyed;
+
+ if(self._initData.properties.getPropertyAsInt("Ice.Warn.UnusedProperties") > 0)
+ {
+ var unusedProperties = self._initData.properties.getUnusedProperties();
+ if(unusedProperties.length > 0)
+ {
+ var message = [];
+ message.push("The following properties were set but never read:");
+ for(var i = 0; i < unusedProperties.length; ++i)
+ {
+ message.push("\n ");
+ message.push(unusedProperties[i]);
+ }
+ self._initData.logger.warning(message.join(""));
+ }
+ }
+
+ promise.succeed(promise);
+ }
+ ).exception(
+ function(ex)
+ {
+ promise.fail(ex);
+ }
+ );
+ return promise;
+ },
+ });
+
+ Ice.Instance = Instance;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/LocalExceptionWrapper.js b/js/src/Ice/LocalExceptionWrapper.js
new file mode 100644
index 00000000000..993858b8e7c
--- /dev/null
+++ b/js/src/Ice/LocalExceptionWrapper.js
@@ -0,0 +1,83 @@
+// **********************************************************************
+//
+// 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/Exception");
+ require("Ice/ExUtil");
+ require("Ice/Debug");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var ExUtil = Ice.ExUtil;
+ var Debug = Ice.Debug;
+
+ var LocalExceptionWrapper = Ice.Class(Error, {
+ __init__: function(ex, retry)
+ {
+ retry = retry === undefined ? false : retry;
+
+ if(ex instanceof Ice.LocalException)
+ {
+ this._ex = ex;
+ this._retry = retry;
+ }
+ else
+ {
+ Debug.assert(ex instanceof LocalExceptionWrapper);
+ this._ex = ex._ex;
+ this._retry = ex._retry;
+ }
+ }
+ });
+
+ LocalExceptionWrapper.throwWrapper = function(ex)
+ {
+ if(ex instanceof Ice.UserException)
+ {
+ throw new LocalExceptionWrapper(new Ice.UnknownUserException(ex.ice_name()), false);
+ }
+ else if(ex instanceof Ice.LocalException)
+ {
+ if(ex instanceof Ice.UnknownException ||
+ ex instanceof Ice.ObjectNotExistException ||
+ ex instanceof Ice.OperationNotExistException ||
+ ex instanceof Ice.FacetNotExistException)
+ {
+ throw new LocalExceptionWrapper(ex, false);
+ }
+ var e = new Ice.UnknownLocalException(ex.ice_name(), ex);
+ throw new LocalExceptionWrapper(e, false);
+ }
+
+ var ue = new Ice.UnknownException(ExUtil.toString(ex), ex);
+ throw new LocalExceptionWrapper(ue, false);
+ };
+
+ var prototype = LocalExceptionWrapper.prototype;
+
+ Object.defineProperty(prototype, "inner", {
+ get: function() { return this._ex; }
+ });
+
+ //
+ // If true, always repeat the request. Don't take retry settings
+ // or "at-most-once" guarantees into account.
+ //
+ // If false, only repeat the request if the retry settings allow
+ // to do so, and if "at-most-once" does not need to be guaranteed.
+ //
+ Object.defineProperty(prototype, "retry", {
+ get: function() { return this._retry; }
+ });
+
+ Ice.LocalExceptionWrapper = LocalExceptionWrapper;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/LocatorInfo.js b/js/src/Ice/LocatorInfo.js
new file mode 100644
index 00000000000..9b255978463
--- /dev/null
+++ b/js/src/Ice/LocatorInfo.js
@@ -0,0 +1,608 @@
+// **********************************************************************
+//
+// 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/Debug");
+ require("Ice/ExUtil");
+ require("Ice/HashMap");
+ require("Ice/Promise");
+ require("Ice/Protocol");
+ require("Ice/Locator");
+ require("Ice/LocalException");
+ require("Ice/Exception");
+
+ var Ice = global.Ice || {};
+
+ var Debug = Ice.Debug;
+ var ExUtil = Ice.ExUtil;
+ var HashMap = Ice.HashMap;
+ var Promise = Ice.Promise;
+ var Protocol = Ice.Protocol;
+ var LocatorRegistryPrx = Ice.LocatorRegisterPrx;
+
+ var Class = Ice.Class;
+
+ var LocatorInfo = Class({
+ __init__: function(locator, table, background)
+ {
+ this._locator = locator;
+ this._locatorRegistry = null;
+ this._table = table;
+ this._background = background;
+
+ this._adapterRequests = new HashMap(); // Map<String, Request>
+ this._objectRequests = new HashMap(); // Map<Ice.Identity, Request>
+ this._objectRequests.keyComparator = HashMap.compareEquals;
+ },
+ destroy: function()
+ {
+ this._locatorRegistry = null;
+ this._table.clear();
+ },
+ equals: function(rhs)
+ {
+ if(this === rhs)
+ {
+ return true;
+ }
+
+ if(rhs instanceof LocatorInfo)
+ {
+ return this._locator.equals(rhs._locator);
+ }
+
+ return false;
+ },
+ hashCode: function()
+ {
+ return this._locator.hashCode();
+ },
+ getLocator: function()
+ {
+ return this._locator;
+ },
+ getLocatorRegistry: function()
+ {
+ if(this._locatorRegistry !== null)
+ {
+ return new Promise().succeed(this._locatorRegistry);
+ }
+
+ var self = this;
+ return this._locator.getRegistry().then(
+ function(reg)
+ {
+ //
+ // The locator registry can't be located.
+ //
+ self._locatorRegistry = LocatorRegistryPrx.uncheckedCast(reg.ice_locator(null));
+ return self._locatorRegistry;
+ });
+ },
+ getEndpoints: function(ref, wellKnownRef, ttl, p)
+ {
+ var promise = p || new Promise(); // success callback receives (endpoints, cached)
+
+ Debug.assert(ref.isIndirect());
+ var endpoints = null;
+ var cached = { value: false };
+ if(!ref.isWellKnown())
+ {
+ endpoints = this._table.getAdapterEndpoints(ref.getAdapterId(), ttl, cached);
+ if(!cached.value)
+ {
+ if(this._background && endpoints !== null)
+ {
+ this.getAdapterRequest(ref).addCallback(ref, wellKnownRef, ttl, null);
+ }
+ else
+ {
+ this.getAdapterRequest(ref).addCallback(ref, wellKnownRef, ttl, promise);
+ return promise;
+ }
+ }
+ }
+ else
+ {
+ var r = this._table.getObjectReference(ref.getIdentity(), ttl, cached);
+ if(!cached.value)
+ {
+ if(this._background && r !== null)
+ {
+ this.getObjectRequest(ref).addCallback(ref, null, ttl, null);
+ }
+ else
+ {
+ this.getObjectRequest(ref).addCallback(ref, null, ttl, promise);
+ return promise;
+ }
+ }
+
+ if(!r.isIndirect())
+ {
+ endpoints = r.getEndpoints();
+ }
+ else if(!r.isWellKnown())
+ {
+ this.getEndpoints(r, ref, ttl, promise);
+ return promise;
+ }
+ }
+
+ Debug.assert(endpoints !== null);
+ if(ref.getInstance().traceLevels().location >= 1)
+ {
+ this.getEndpointsTrace(ref, endpoints, true);
+ }
+ promise.succeed(endpoints, true);
+
+ return promise;
+ },
+ clearCache: function(ref)
+ {
+ Debug.assert(ref.isIndirect());
+
+ if(!ref.isWellKnown())
+ {
+ var endpoints = this._table.removeAdapterEndpoints(ref.getAdapterId());
+
+ if(endpoints !== null && ref.getInstance().traceLevels().location >= 2)
+ {
+ this.trace("removed endpoints from locator table\n", ref, endpoints);
+ }
+ }
+ else
+ {
+ var r = this._table.removeObjectReference(ref.getIdentity());
+ if(r !== null)
+ {
+ if(!r.isIndirect())
+ {
+ if(ref.getInstance().traceLevels().location >= 2)
+ {
+ this.trace("removed endpoints from locator table", ref, r.getEndpoints());
+ }
+ }
+ else if(!r.isWellKnown())
+ {
+ this.clearCache(r);
+ }
+ }
+ }
+ },
+ trace: function(msg, ref, endpoints)
+ {
+ Debug.assert(ref.isIndirect());
+
+ var s = [];
+ s.push(msg);
+ s.push("\n");
+ if(!ref.isWellKnown())
+ {
+ s.push("adapter = ");
+ s.push(ref.getAdapterId());
+ s.push("\n");
+ }
+ else
+ {
+ s.push("object = ");
+ s.push(ref.getInstance().identityToString(ref.getIdentity()));
+ s.push("\n");
+ }
+
+ s.push("endpoints = ");
+ for(var i = 0; i < endpoints.length; i++)
+ {
+ s.push(endpoints[i].toString());
+ if(i + 1 < endpoints.length)
+ {
+ s.push(":");
+ }
+ }
+
+ ref.getInstance().initializationData().logger.trace(ref.getInstance().traceLevels().locationCat, s.join(""));
+ },
+ getEndpointsException: function(ref, exc)
+ {
+ Debug.assert(ref.isIndirect());
+
+ var instance = ref.getInstance();
+ var s, e;
+ try
+ {
+ throw exc;
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.AdapterNotFoundException)
+ {
+ if(instance.traceLevels().location >= 1)
+ {
+ s = [];
+ s.push("adapter not found\n");
+ s.push("adapter = ");
+ s.push(ref.getAdapterId());
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.join(""));
+ }
+
+ e = new Ice.NotRegisteredException();
+ e.kindOfObject = "object adapter";
+ e.id = ref.getAdapterId();
+ throw e;
+ }
+ else if(ex instanceof Ice.ObjectNotFoundException)
+ {
+ if(instance.traceLevels().location >= 1)
+ {
+ s = [];
+ s.push("object not found\n");
+ s.push("object = ");
+ s.push(instance.identityToString(ref.getIdentity()));
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.join(""));
+ }
+
+ e = new Ice.NotRegisteredException();
+ e.kindOfObject = "object";
+ e.id = instance.identityToString(ref.getIdentity());
+ throw e;
+ }
+ else if(ex instanceof Ice.NotRegisteredException)
+ {
+ throw ex;
+ }
+ else if(ex instanceof Ice.LocalException)
+ {
+ if(instance.traceLevels().location >= 1)
+ {
+ s = [];
+ s.push("couldn't contact the locator to retrieve adapter endpoints\n");
+ if(ref.getAdapterId().length > 0)
+ {
+ s.push("adapter = ");
+ s.push(ref.getAdapterId());
+ s.push("\n");
+ }
+ else
+ {
+ s.push("object = ");
+ s.push(instance.identityToString(ref.getIdentity()));
+ s.push("\n");
+ }
+ s.push("reason = " + ExUtil.toString(ex));
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.join(""));
+ }
+ throw ex;
+ }
+ else
+ {
+ Debug.assert(false);
+ }
+ }
+ },
+ getEndpointsTrace: function(ref, endpoints, cached)
+ {
+ if(endpoints !== null && endpoints.length > 0)
+ {
+ if(cached)
+ {
+ this.trace("found endpoints in locator table", ref, endpoints);
+ }
+ else
+ {
+ this.trace("retrieved endpoints from locator, adding to locator table", ref, endpoints);
+ }
+ }
+ else
+ {
+ var instance = ref.getInstance();
+ var s = [];
+ s.push("no endpoints configured for ");
+ if(ref.getAdapterId().length > 0)
+ {
+ s.push("adapter\n");
+ s.push("adapter = ");
+ s.push(ref.getAdapterId());
+ s.push("\n");
+ }
+ else
+ {
+ s.push("object\n");
+ s.push("object = ");
+ s.push(instance.identityToString(ref.getIdentity()));
+ s.push("\n");
+ }
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.join(""));
+ }
+ },
+ getAdapterRequest: function(ref)
+ {
+ if(ref.getInstance().traceLevels().location >= 1)
+ {
+ var instance = ref.getInstance();
+ var s = [];
+ s.push("searching for adapter by id\n");
+ s.push("adapter = ");
+ s.push(ref.getAdapterId());
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.join(""));
+ }
+
+ var request = this._adapterRequests.get(ref.getAdapterId());
+ if(request !== undefined)
+ {
+ return request;
+ }
+ request = new AdapterRequest(this, ref);
+ this._adapterRequests.set(ref.getAdapterId(), request);
+ return request;
+ },
+ getObjectRequest: function(ref)
+ {
+ if(ref.getInstance().traceLevels().location >= 1)
+ {
+ var instance = ref.getInstance();
+ var s = [];
+ s.push("searching for object by id\n");
+ s.push("object = ");
+ s.push(instance.identityToString(ref.getIdentity()));
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.join(""));
+ }
+
+ var request = this._objectRequests.get(ref.getIdentity());
+ if(request !== undefined)
+ {
+ return request;
+ }
+ request = new ObjectRequest(this, ref);
+ this._objectRequests.set(ref.getIdentity(), request);
+ return request;
+ },
+ finishRequest: function(ref, wellKnownRefs, proxy, notRegistered)
+ {
+ if(proxy === null || proxy.__reference().isIndirect())
+ {
+ //
+ // Remove the cached references of well-known objects for which we tried
+ // to resolved the endpoints if these endpoints are empty.
+ //
+ for(var i = 0; i < wellKnownRefs.length; ++i)
+ {
+ this._table.removeObjectReference(wellKnownRefs[i].getIdentity());
+ }
+ }
+
+ if(!ref.isWellKnown())
+ {
+ if(proxy !== null && !proxy.__reference().isIndirect())
+ {
+ // Cache the adapter endpoints.
+ this._table.addAdapterEndpoints(ref.getAdapterId(), proxy.__reference().getEndpoints());
+ }
+ else if(notRegistered) // If the adapter isn't registered anymore, remove it from the cache.
+ {
+ this._table.removeAdapterEndpoints(ref.getAdapterId());
+ }
+
+ Debug.assert(this._adapterRequests.has(ref.getAdapterId()));
+ this._adapterRequests.delete(ref.getAdapterId());
+ }
+ else
+ {
+ if(proxy !== null && !proxy.__reference().isWellKnown())
+ {
+ // Cache the well-known object reference.
+ this._table.addObjectReference(ref.getIdentity(), proxy.__reference());
+ }
+ else if(notRegistered) // If the well-known object isn't registered anymore, remove it from the cache.
+ {
+ this._table.removeObjectReference(ref.getIdentity());
+ }
+
+ Debug.assert(this._objectRequests.has(ref.getIdentity()));
+ this._objectRequests.delete(ref.getIdentity());
+ }
+ }
+ });
+
+ Ice.LocatorInfo = LocatorInfo;
+ global.Ice = Ice;
+
+ var RequestCallback = Class({
+ __init__: function(ref, ttl, promise)
+ {
+ this._ref = ref;
+ this._ttl = ttl;
+ this._promise = promise;
+ },
+ response: function(locatorInfo, proxy)
+ {
+ var endpoints = null;
+ if(proxy !== null)
+ {
+ var r = proxy.__reference();
+ if(this._ref.isWellKnown() && !Protocol.isSupported(this._ref.getEncoding(), r.getEncoding()))
+ {
+ //
+ // If a well-known proxy and the returned proxy
+ // encoding isn't supported, we're done: there's
+ // no compatible endpoint we can use.
+ //
+ }
+ else if(!r.isIndirect())
+ {
+ endpoints = r.getEndpoints();
+ }
+ else if(this._ref.isWellKnown() && !r.isWellKnown())
+ {
+ //
+ // We're resolving the endpoints of a well-known object and the proxy returned
+ // by the locator is an indirect proxy. We now need to resolve the endpoints
+ // of this indirect proxy.
+ //
+ var self = this;
+ locatorInfo.getEndpoints(r, this._ref, this._ttl).then(
+ function(endpts, b)
+ {
+ if(self._promise !== null)
+ {
+ self._promise.succeed(endpts, b);
+ }
+ },
+ function(ex)
+ {
+ if(self._promise !== null)
+ {
+ self._promise.fail(ex);
+ }
+ });
+ return;
+ }
+ }
+
+ if(this._ref.getInstance().traceLevels().location >= 1)
+ {
+ locatorInfo.getEndpointsTrace(this._ref, endpoints, false);
+ }
+
+ if(this._promise !== null)
+ {
+ this._promise.succeed(endpoints === null ? [] : endpoints, false);
+ }
+ },
+ exception: function(locatorInfo, exc)
+ {
+ try
+ {
+ locatorInfo.getEndpointsException(this._ref, exc); // This throws.
+ }
+ catch(ex)
+ {
+ if(this._promise !== null)
+ {
+ this._promise.fail(ex);
+ }
+ }
+ }
+ });
+
+ var Request = Class({
+ __init__: function(locatorInfo, ref)
+ {
+ this._locatorInfo = locatorInfo;
+ this._ref = ref;
+
+ this._callbacks = []; // Array<RequestCallback>
+ this._wellKnownRefs = []; // Array<Reference>
+ this._sent = false;
+ this._response = false;
+ this._proxy = null;
+ this._exception = null;
+ },
+ addCallback: function(ref, wellKnownRef, ttl, promise)
+ {
+ var callback = new RequestCallback(ref, ttl, promise);
+ if(this._response)
+ {
+ callback.response(this._locatorInfo, this._proxy);
+ }
+ else if(this._exception !== null)
+ {
+ callback.exception(this._locatorInfo, this._exception);
+ }
+ else
+ {
+ this._callbacks.push(callback);
+ if(wellKnownRef !== null) // This request is to resolve the endpoints of a cached well-known object ref
+ {
+ this._wellKnownRefs.push(wellKnownRef);
+ }
+ if(!this._sent)
+ {
+ this._sent = true;
+ this.send();
+ }
+ }
+ },
+ response: function(proxy)
+ {
+ this._locatorInfo.finishRequest(this._ref, this._wellKnownRefs, proxy, false);
+ this._response = true;
+ this._proxy = proxy;
+ for(var i = 0; i < this._callbacks.length; ++i)
+ {
+ this._callbacks[i].response(this._locatorInfo, proxy);
+ }
+ },
+ exception: function(ex)
+ {
+ this._locatorInfo.finishRequest(this._ref, this._wellKnownRefs, null, ex instanceof Ice.UserException);
+ this._exception = ex;
+ for(var i = 0; i < this._callbacks.length; ++i)
+ {
+ this._callbacks[i].exception(this._locatorInfo, ex);
+ }
+ }
+ });
+
+ var ObjectRequest = Class(Request, {
+ __init__: function(locatorInfo, reference)
+ {
+ Request.call(this, locatorInfo, reference);
+ Debug.assert(reference.isWellKnown());
+ },
+ send: function()
+ {
+ try
+ {
+ var self = this;
+ this._locatorInfo.getLocator().findObjectById(this._ref.getIdentity()).then(
+ function(proxy)
+ {
+ self.response(proxy);
+ },
+ function(ex)
+ {
+ self.exception(ex);
+ });
+ }
+ catch(ex)
+ {
+ this.exception(ex);
+ }
+ }
+ });
+
+ var AdapterRequest = Class(Request, {
+ __init__: function(locatorInfo, reference)
+ {
+ Request.call(this, locatorInfo, reference);
+ Debug.assert(reference.isIndirect());
+ },
+ send: function()
+ {
+ try
+ {
+ var self = this;
+ this._locatorInfo.getLocator().findAdapterById(this._ref.getAdapterId()).then(
+ function(proxy)
+ {
+ self.response(proxy);
+ },
+ function(ex)
+ {
+ self.exception(ex);
+ });
+ }
+ catch(ex)
+ {
+ this.exception(ex);
+ }
+ }
+ });
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/LocatorManager.js b/js/src/Ice/LocatorManager.js
new file mode 100644
index 00000000000..e7389b844af
--- /dev/null
+++ b/js/src/Ice/LocatorManager.js
@@ -0,0 +1,88 @@
+// **********************************************************************
+//
+// 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/HashMap");
+ require("Ice/LocatorInfo");
+ require("Ice/LocatorTable");
+ require("Ice/Locator");
+
+ var Ice = global.Ice || {};
+
+ var HashMap = Ice.HashMap;
+ var LocatorInfo = Ice.LocatorInfo;
+ var LocatorTable = Ice.LocatorTable;
+ var LocatorPrx = Ice.LocatorPrx;
+
+ var LocatorManager = Ice.Class({
+ __init__: function(properties)
+ {
+ this._background = properties.getPropertyAsInt("Ice.BackgroundLocatorCacheUpdates") > 0;
+
+ this._table = new HashMap(); // Map<Ice.LocatorPrx, LocatorInfo>
+ this._table.keyComparator = HashMap.compareEquals;
+ this._locatorTables = new HashMap(); // Map<Ice.Identity, LocatorTable>
+ this._locatorTables.keyComparator = HashMap.compareEquals;
+ },
+ destroy: function()
+ {
+ for(var e = this._table.entries; e !== null; e = e.next)
+ {
+ e.value.destroy();
+ }
+ this._table.clear();
+ this._locatorTables.clear();
+ },
+ //
+ // Returns locator info for a given locator. Automatically creates
+ // the locator info if it doesn't exist yet.
+ //
+ find: function(loc)
+ {
+ if(loc === null)
+ {
+ return null;
+ }
+
+ //
+ // The locator can't be located.
+ //
+ var locator = LocatorPrx.uncheckedCast(loc.ice_locator(null));
+
+ //
+ // TODO: reap unused locator info objects?
+ //
+
+ var info = this._table.get(locator);
+ if(info === undefined)
+ {
+ //
+ // Rely on locator identity for the adapter table. We want to
+ // have only one table per locator (not one per locator
+ // proxy).
+ //
+ var table = this._locatorTables.get(locator.ice_getIdentity());
+ if(table === undefined)
+ {
+ table = new LocatorTable();
+ this._locatorTables.set(locator.ice_getIdentity(), table);
+ }
+
+ info = new LocatorInfo(locator, table, this._background);
+ this._table.set(locator, info);
+ }
+
+ return info;
+ }
+ });
+
+ Ice.LocatorManager = LocatorManager;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/LocatorTable.js b/js/src/Ice/LocatorTable.js
new file mode 100644
index 00000000000..e80465b5be9
--- /dev/null
+++ b/js/src/Ice/LocatorTable.js
@@ -0,0 +1,114 @@
+// **********************************************************************
+//
+// 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/HashMap");
+ require("Ice/Debug");
+
+ var Ice = global.Ice || {};
+
+ var HashMap = Ice.HashMap;
+ var Debug = Ice.Debug;
+
+ var LocatorTable = Ice.Class({
+ __init__: function()
+ {
+ this._adapterEndpointsTable = new HashMap(); // Map<String, EndpointTableEntry>
+ this._objectTable = new HashMap(); // Map<Ice.Identity, ReferenceTableEntry>
+ this._objectTable.keyComparator = HashMap.compareEquals;
+ },
+ clear: function()
+ {
+ this._adapterEndpointsTable.clear();
+ this._objectTable.clear();
+ },
+ getAdapterEndpoints: function(adapter, ttl, cached)
+ {
+ if(ttl === 0) // Locator cache disabled.
+ {
+ cached.value = false;
+ return null;
+ }
+
+ var entry = this._adapterEndpointsTable.get(adapter);
+ if(entry !== undefined)
+ {
+ cached.value = this.checkTTL(entry.time, ttl);
+ return entry.endpoints;
+ }
+ cached.value = false;
+ return null;
+ },
+ addAdapterEndpoints: function(adapter, endpoints)
+ {
+ this._adapterEndpointsTable.set(adapter, new EndpointTableEntry(Date.now(), endpoints));
+ },
+ removeAdapterEndpoints: function(adapter)
+ {
+ var entry = this._adapterEndpointsTable.get(adapter);
+ this._adapterEndpointsTable.delete(adapter);
+ return entry !== undefined ? entry.endpoints : null;
+ },
+ getObjectReference: function(id, ttl, cached)
+ {
+ if(ttl === 0) // Locator cache disabled.
+ {
+ cached.value = false;
+ return null;
+ }
+
+ var entry = this._objectTable.get(id);
+ if(entry !== undefined)
+ {
+ cached.value = this.checkTTL(entry.time, ttl);
+ return entry.reference;
+ }
+ cached.value = false;
+ return null;
+ },
+ addObjectReference: function(id, ref)
+ {
+ this._objectTable.set(id, new ReferenceTableEntry(Date.now(), ref));
+ },
+ removeObjectReference: function(id)
+ {
+ var entry = this._objectTable.get(id);
+ this._objectTable.delete(id);
+ return entry !== undefined ? entry.reference : null;
+ },
+ checkTTL: function(time, ttl)
+ {
+ Debug.assert(ttl !== 0);
+ if(ttl < 0) // TTL = infinite
+ {
+ return true;
+ }
+ else
+ {
+ return Date.now() - time <= (ttl * 1000);
+ }
+ }
+ });
+
+ Ice.LocatorTable = LocatorTable;
+ global.Ice = Ice;
+
+ var EndpointTableEntry = function(time, endpoints)
+ {
+ this.time = time;
+ this.endpoints = endpoints;
+ };
+
+ var ReferenceTableEntry = function(time, reference)
+ {
+ this.time = time;
+ this.reference = reference;
+ };
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Logger.js b/js/src/Ice/Logger.js
new file mode 100644
index 00000000000..38ab8d8ee4b
--- /dev/null
+++ b/js/src/Ice/Logger.js
@@ -0,0 +1,93 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+
+ require("Ice/Class");
+
+ var Logger = Ice.Class({
+ __init__: function(prefix)
+ {
+ if(prefix !== undefined && prefix.length > 0)
+ {
+ this._prefix = prefix + ": ";
+ }
+ else
+ {
+ this._prefix = "";
+ }
+ },
+ print: function(message)
+ {
+ this.write(message, false);
+ },
+ trace: function(category, message)
+ {
+ var s = [];
+ var d = new Date();
+ s.push("-- ");
+ s.push(this.timestamp());
+ s.push(' ');
+ s.push(this._prefix);
+ s.push(category);
+ s.push(": ");
+ s.push(message);
+ this.write(s.join(""), true);
+ },
+ warning: function(message)
+ {
+ var s = [];
+ var d = new Date();
+ s.push("-! ");
+ s.push(this.timestamp());
+ s.push(' ');
+ s.push(this._prefix);
+ s.push("warning: ");
+ s.push(message);
+ this.write(s.join(""), true);
+ },
+ error: function(message)
+ {
+ var s = [];
+ var d = new Date();
+ s.push("!! ");
+ s.push(this.timestamp());
+ s.push(' ');
+ s.push(this._prefix);
+ s.push("error: ");
+ s.push(message);
+ this.write(s.join(""), true);
+ },
+ cloneWithPrefix: function(prefix)
+ {
+ return new Logger(prefix);
+ },
+ write: function(message, indent)
+ {
+ if(indent)
+ {
+ message = message.replace(/\n/g, "\n ");
+ }
+
+ console.log(message);
+ },
+ timestamp: function()
+ {
+ var d = new Date();
+ var mon = d.getMonth() + 1;
+ mon = mon < 10 ? "0" + mon : mon;
+ var day = d.getDate();
+ day = day < 10 ? "0" + day : day;
+ return mon + "-" + day + "-" + d.getFullYear() + " " + d.toLocaleTimeString() + "." + d.getMilliseconds();
+ }
+ });
+ Ice.Logger = Logger;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Long.js b/js/src/Ice/Long.js
new file mode 100644
index 00000000000..1445b4098e9
--- /dev/null
+++ b/js/src/Ice/Long.js
@@ -0,0 +1,100 @@
+// **********************************************************************
+//
+// 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");
+
+ //
+ // The Long type represents a signed 64-bit integer as two 32-bit values
+ // corresponding to the high and low words.
+ //
+ var Ice = global.Ice || {};
+
+ var Long = Ice.Class({
+ __init__: function(high, low)
+ {
+ this.high = high;
+ this.low = low;
+ },
+ hashCode: function()
+ {
+ return this.low;
+ },
+ equals: function(rhs)
+ {
+ if(this === rhs)
+ {
+ return true;
+ }
+ if(!(rhs instanceof Long))
+ {
+ return false;
+ }
+ return this.high === rhs.high && this.low === rhs.low;
+ },
+ toString: function()
+ {
+ return this.high + ":" + this.low;
+ },
+ toNumber: function()
+ {
+ if((this.high & Long.SIGN_MASK) != 0)
+ {
+ var low = ~this.low;
+ var high = ~this.high;
+ if(low < 0xFFFFFFFF)
+ {
+ low += 1;
+ }
+ else
+ {
+ low = 0;
+ high += 1;
+ if(high > Long.HIGH_MAX)
+ {
+ return Number.NEGATIVE_INFINITY;
+ }
+ }
+ return -1 * (high * Long.HIGH_MASK) + low;
+ }
+ else
+ {
+ if(this.high > Long.HIGH_MAX)
+ {
+ return Number.POSITIVE_INFINITY;
+ }
+ return (this.high * Long.HIGH_MASK) + this.low;
+ }
+ }
+ });
+
+ //
+ // (high & SIGN_MASK) != 0 denotes a negative number;
+ // that is, the most significant bit is set.
+ //
+ Long.SIGN_MASK = 0x80000000;
+
+ //
+ // When converting to a JavaScript Number we left shift the
+ // high word by 32 bits. As that isn't possible using JavaScript's
+ // left shift operator, we multiply the value by 2^32 which will
+ // produce the same result.
+ //
+ Long.HIGH_MASK = 0x100000000;
+
+ //
+ // The maximum value for the high word when coverting to
+ // a JavaScript Number is 2^21 - 1, in which case all
+ // 53 bits are used.
+ //
+ Long.HIGH_MAX = 0x1FFFFF;
+
+ Ice.Long = Long;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Makefile b/js/src/Ice/Makefile
new file mode 100644
index 00000000000..0b1edfc2694
--- /dev/null
+++ b/js/src/Ice/Makefile
@@ -0,0 +1,163 @@
+# **********************************************************************
+#
+# 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.
+#
+# **********************************************************************
+
+top_srcdir = ../..
+
+LIBNAME = Ice
+
+TARGETS = $(call mklibtargets,$(LIBNAME))
+
+SLICES = $(SDIR)/BuiltinSequences.ice \
+ $(SDIR)/Connection.ice \
+ $(SDIR)/ConnectionF.ice \
+ $(SDIR)/Current.ice \
+ $(SDIR)/Endpoint.ice \
+ $(SDIR)/EndpointF.ice \
+ $(SDIR)/EndpointTypes.ice \
+ $(SDIR)/Identity.ice \
+ $(SDIR)/LocalException.ice \
+ $(SDIR)/Locator.ice \
+ $(SDIR)/Metrics.ice \
+ $(SDIR)/ObjectAdapterF.ice \
+ $(SDIR)/Process.ice \
+ $(SDIR)/ProcessF.ice \
+ $(SDIR)/PropertiesAdmin.ice \
+ $(SDIR)/Router.ice \
+ $(SDIR)/SliceChecksumDict.ice \
+ $(SDIR)/Version.ice
+
+SDIR = $(slicedir)/Ice
+
+GEN_SRCS = $(patsubst $(SDIR)/%.ice, %.js, $(SLICES))
+
+COMMON_SRCS = \
+ Address.js \
+ ArrayUtil.js \
+ AsyncResultBase.js \
+ AsyncResult.js \
+ AsyncStatus.js \
+ Base64.js \
+ BasicStream.js \
+ BatchOutgoingAsync.js \
+ Class.js \
+ Communicator.js \
+ ConnectionBatchOutgoingAsync.js \
+ ConnectionI.js \
+ ConnectionMonitor.js \
+ ConnectionReaper.js \
+ ConnectionRequestHandler.js \
+ ConnectRequestHandler.js \
+ DefaultsAndOverrides.js \
+ DispatchStatus.js \
+ EndpointFactoryManager.js \
+ EnumBase.js \
+ Exception.js \
+ ExUtil.js \
+ FormatType.js \
+ HashMap.js \
+ HashUtil.js \
+ IdentityUtil.js \
+ ImplicitContextI.js \
+ IncomingAsync.js \
+ Initialize.js \
+ Instance.js \
+ LocalExceptionWrapper.js \
+ LocatorInfo.js \
+ LocatorManager.js \
+ LocatorTable.js \
+ Logger.js \
+ Long.js \
+ ObjectAdapterFactory.js \
+ ObjectAdapterI.js \
+ ObjectFactory.js \
+ ObjectFactoryManager.js \
+ Object.js \
+ ObjectPrx.js \
+ OpaqueEndpointI.js \
+ Operation.js \
+ OptionalFormat.js \
+ OutgoingAsync.js \
+ OutgoingConnectionFactory.js \
+ ProcessLogger.js \
+ Promise.js \
+ Properties.js \
+ Property.js \
+ PropertyNames.js \
+ Protocol.js \
+ ProxyBatchOutgoingAsync.js \
+ ProxyFactory.js \
+ Reference.js \
+ ReferenceMode.js \
+ RetryQueue.js \
+ RouterInfo.js \
+ RouterManager.js \
+ ServantManager.js \
+ SocketOperation.js \
+ StreamHelpers.js \
+ StringUtil.js \
+ Struct.js \
+ Timer.js \
+ TraceLevels.js \
+ TraceUtil.js \
+ CompactIdRegistry.js \
+ UnknownSlicedObject.js \
+ UUID.js
+
+NODEJS_SRCS = \
+ Buffer.js \
+ Ice.js \
+ TcpEndpointFactory.js \
+ TcpEndpointI.js \
+ TcpTransceiver.js \
+
+BROWSER_SRCS = \
+ browser/Buffer.js \
+ browser/EndpointInfo.js \
+ browser/ConnectionInfo.js \
+ browser/Transceiver.js \
+ browser/EndpointI.js \
+ browser/EndpointFactory.js
+
+ifneq ($(OPTIMIZE),yes)
+ NODEJS_SRCS := $(NODEJS_SRCS) Debug.js
+ BROWSER_SRCS := $(BROWSER_SRCS) browser/Debug.js
+endif
+
+SRCS := $(BROWSER_SRCS) $(GEN_SRCS) $(COMMON_SRCS)
+INSTALL_SRCS := $(NODEJS_SRCS) $(GEN_SRCS) $(COMMON_SRCS)
+
+include $(top_srcdir)/config/Make.rules.js
+
+# Prevent generation of these files from .ice files
+Communicator.js:
+
+Properties.js:
+
+Logger.js:
+
+ServantLocator.js:
+
+ObjectFactory.js:
+
+
+SLICE2JSFLAGS := $(SLICE2JSFLAGS) --ice -I$(slicedir)
+
+# IceWS slice files
+browser/%.js: $(slicedir)/IceWS/%.ice $(SLICE2JS) $(SLICEPARSERLIB)
+ rm -f browser/$(*F).js
+ $(SLICE2JS) $(SLICE2JSFLAGS) $<
+ mv $(*F).js browser/
+
+lint:: $(SRCS)
+ jshint $(LINTFLAGS) $(NODEJS_SRCS) $(BROWSER_SRCS) $(GEN_SRCS) $(COMMON_SRCS)
+
+install:: all
+ $(call installlib,$(DESTDIR)$(install_libdir),$(libdir),$(LIBNAME))
+ $(call installmodule,$(DESTDIR)$(install_moduledir),$(INSTALL_SRCS),$(LIBNAME))
+
diff --git a/js/src/Ice/Makefile.mak b/js/src/Ice/Makefile.mak
new file mode 100644
index 00000000000..17e2a3688a7
--- /dev/null
+++ b/js/src/Ice/Makefile.mak
@@ -0,0 +1,167 @@
+# **********************************************************************
+#
+# 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.
+#
+# **********************************************************************
+
+top_srcdir = ..\..
+
+LIBNAME = Ice
+
+GEN_SRCS = BuiltinSequences.js \
+ Connection.js \
+ ConnectionF.js \
+ Current.js \
+ Endpoint.js \
+ EndpointF.js \
+ EndpointTypes.js \
+ Identity.js \
+ LocalException.js \
+ Locator.js \
+ Metrics.js \
+ ObjectAdapterF.js \
+ Process.js \
+ ProcessF.js \
+ PropertiesAdmin.js \
+ Router.js \
+ SliceChecksumDict.js \
+ Version.js
+
+COMMON_SRCS = \
+ Address.js \
+ ArrayUtil.js \
+ AsyncResultBase.js \
+ AsyncResult.js \
+ AsyncStatus.js \
+ Base64.js \
+ BasicStream.js \
+ BatchOutgoingAsync.js \
+ Class.js \
+ Communicator.js \
+ ConnectionBatchOutgoingAsync.js \
+ ConnectionI.js \
+ ConnectionMonitor.js \
+ ConnectionReaper.js \
+ ConnectionRequestHandler.js \
+ ConnectRequestHandler.js \
+ DefaultsAndOverrides.js \
+ DispatchStatus.js \
+ EndpointFactoryManager.js \
+ EnumBase.js \
+ Exception.js \
+ ExUtil.js \
+ FormatType.js \
+ HashMap.js \
+ HashUtil.js \
+ IdentityUtil.js \
+ ImplicitContextI.js \
+ IncomingAsync.js \
+ Initialize.js \
+ Instance.js \
+ LocalExceptionWrapper.js \
+ LocatorInfo.js \
+ LocatorManager.js \
+ LocatorTable.js \
+ Logger.js \
+ Long.js \
+ ObjectAdapterFactory.js \
+ ObjectAdapterI.js \
+ ObjectFactory.js \
+ ObjectFactoryManager.js \
+ Object.js \
+ ObjectPrx.js \
+ OpaqueEndpointI.js \
+ Operation.js \
+ OptionalFormat.js \
+ OutgoingAsync.js \
+ OutgoingConnectionFactory.js \
+ ProcessLogger.js \
+ Promise.js \
+ Properties.js \
+ Property.js \
+ PropertyNames.js \
+ Protocol.js \
+ ProxyBatchOutgoingAsync.js \
+ ProxyFactory.js \
+ Reference.js \
+ ReferenceMode.js \
+ RetryQueue.js \
+ RouterInfo.js \
+ RouterManager.js \
+ ServantManager.js \
+ SocketOperation.js \
+ StreamHelpers.js \
+ StringUtil.js \
+ Struct.js \
+ Timer.js \
+ TraceLevels.js \
+ TraceUtil.js \
+ CompactIdRegistry.js \
+ UnknownSlicedObject.js \
+ UUID.js
+
+NODEJS_SRCS = \
+ Buffer.js \
+ Ice.js \
+ TcpEndpointFactory.js \
+ TcpEndpointI.js \
+ TcpTransceiver.js \
+
+BROWSER_SRCS = \
+ browser\Buffer.js \
+ browser\EndpointInfo.js \
+ browser\ConnectionInfo.js \
+ browser\Transceiver.js \
+ browser\EndpointI.js \
+ browser\EndpointFactory.js
+
+!if "$(OPTIMIZE)" != "yes"
+NODEJS_SRCS = $(NODEJS_SRCS) Debug.js
+BROWSER_SRCS = $(BROWSER_SRCS) browser\Debug.js
+!endif
+
+SDIR = $(slicedir)\Ice
+
+SRCS = $(BROWSER_SRCS) $(GEN_SRCS) $(COMMON_SRCS)
+INSTALL_SRCS = $(NODEJS_SRCS) $(GEN_SRCS) $(COMMON_SRCS)
+
+!include $(top_srcdir)\config\Make.rules.mak.js
+
+# Prevent generation of these files from .ice files
+Communicator.js:
+
+Properties.js:
+
+Logger.js:
+
+ServantLocator.js:
+
+ObjectFactory.js:
+
+
+SLICE2JSFLAGS = $(SLICE2JSFLAGS) --ice -I"$(slicedir)"
+
+# IceWS slice files
+browser\EndpointInfo.js: "$(SLICE2JS)" "$(SLICEPARSERLIB)"
+ del /q browser\EndpointInfo.js
+ "$(SLICE2JS)" $(SLICE2JSFLAGS) "$(slicedir)\IceWS\EndpointInfo.ice"
+ move EndpointInfo.js browser
+
+browser\ConnectionInfo.js: "$(SLICE2JS)" "$(SLICEPARSERLIB)"
+ -del /q browser\ConnectionInfo.js
+ "$(SLICE2JS)" $(SLICE2JSFLAGS) "$(slicedir)\IceWS\ConnectionInfo.ice"
+ move ConnectionInfo.js browser
+
+MODULEDIR = $(install_moduledir)\$(LIBNAME)
+
+install:: all
+ @if not exist $(MODULEDIR) \
+ @echo "Creating $(MODULEDIR)" && \
+ mkdir "$(MODULEDIR)"
+ @for %i in ( $(INSTALL_SRCS) ) do \
+ copy %i "$(MODULEDIR)"
+ copy package.json "$(MODULEDIR)"
+
diff --git a/js/src/Ice/Object.js b/js/src/Ice/Object.js
new file mode 100644
index 00000000000..a60a60d6d9d
--- /dev/null
+++ b/js/src/Ice/Object.js
@@ -0,0 +1,307 @@
+// **********************************************************************
+//
+// 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){
+ //
+ // Ice.Object
+ //
+ // Using IceObject in this file to avoid collisions with the native Object.
+ //
+ require("Ice/Class");
+ require("Ice/DispatchStatus");
+ require("Ice/Exception");
+ require("Ice/FormatType");
+ require("Ice/StreamHelpers");
+ require("Ice/OptionalFormat");
+
+ var Ice = global.Ice || {};
+ var Slice = global.Slice || {};
+
+ var Class = Ice.Class;
+
+ var nextAddress = 0;
+
+ var IceObject = Class({
+ __init__: function()
+ {
+ // Fake Address used as the hashCode for this object instance.
+ this.__address = nextAddress++;
+ },
+ hashCode: function()
+ {
+ return this.__address;
+ },
+ ice_isA: function(s, current)
+ {
+ return this.__mostDerivedType().__ids.indexOf(s) >= 0;
+ },
+ ice_ping: function(current)
+ {
+ },
+ ice_ids: function(current)
+ {
+ return this.__mostDerivedType().__ids;
+ },
+ ice_id: function(current)
+ {
+ return this.__mostDerivedType().__id;
+ },
+ toString: function()
+ {
+ return "[object " + this.ice_id() + "]";
+ },
+ ice_preMarshal: function()
+ {
+ },
+ ice_postUnmarshal: function()
+ {
+ },
+ __write: function(os)
+ {
+ os.startWriteObject(null);
+ __writeImpl(this, os, this.__mostDerivedType());
+ os.endWriteObject();
+ },
+ __read: function(is)
+ {
+ is.startReadObject();
+ __readImpl(this, is, this.__mostDerivedType());
+ is.endReadObject(false);
+ },
+ ice_instanceof: function(T)
+ {
+ if(T)
+ {
+ if(this instanceof T)
+ {
+ return true;
+ }
+ return this.__mostDerivedType().__instanceof(T);
+ }
+ return false;
+ },
+ //
+ // __mostDerivedType returns the the most derived Ice generated class. This is
+ // necessary because the user might extend Slice generated classes. The user
+ // class extensions don't have __id, __ids, __instanceof etc static members so
+ // the implementation of ice_id, ice_ids and ice_instanceof would fail trying
+ // to access those members of the user defined class. Instead, ice_id, ice_ids
+ // and ice_instanceof call __mostDerivedType to get the most derived Ice class.
+ //
+ // The __mostDerivedType is overriden by each Slice generated class, see the
+ // Slice.defineObject method implementation for details.
+ //
+ __mostDerivedType: function()
+ {
+ return IceObject;
+ }
+ });
+
+ //
+ // These methods are used for object parameters.
+ //
+ IceObject.write = function(os, v)
+ {
+ os.writeObject(v);
+ };
+
+ IceObject.writeOpt = function(os, tag, v)
+ {
+ os.writeOptObject(tag, v);
+ };
+
+ IceObject.read = function(is)
+ {
+ var v = { value: null };
+ is.readObject(function(o) { v.value = o; }, IceObject);
+ return v;
+ };
+
+ IceObject.readOpt = function(is, tag)
+ {
+ var v = { value: undefined };
+ is.readOptObject(tag, function(o) { v.value = o; }, IceObject);
+ return v;
+ };
+
+ IceObject.ice_staticId = function()
+ {
+ return IceObject.__id;
+ };
+
+ IceObject.__instanceof = function(T)
+ {
+ if(T === this)
+ {
+ return true;
+ }
+
+ for(var i in this.__implements)
+ {
+ if(this.__implements[i].__instanceof(T))
+ {
+ return true;
+ }
+ }
+
+ if(this.__parent)
+ {
+ return this.__parent.__instanceof(T);
+ }
+ return false;
+ };
+
+ IceObject.__ids = ["::Ice::Object"];
+ IceObject.__id = IceObject.__ids[0];
+ IceObject.__compactId = -1;
+ IceObject.__preserved = false;
+
+ //
+ // Private methods
+ //
+
+ var __writeImpl = function(obj, os, type)
+ {
+ //
+ // The __writeImpl method is a recursive method that goes down the
+ // class hierarchy to marshal each slice of the class using the
+ // generated __writeMemberImpl method.
+ //
+
+ if(type === undefined || type === IceObject)
+ {
+ return; // Don't marshal anything for IceObject
+ }
+
+ os.startWriteSlice(type.__id, type.__compactId, type.__parent === IceObject);
+ if(type.prototype.__writeMemberImpl)
+ {
+ type.prototype.__writeMemberImpl.call(obj, os);
+ }
+ os.endWriteSlice();
+ __writeImpl(obj, os, type.__parent);
+ };
+
+ var __readImpl = function(obj, is, type)
+ {
+ //
+ // The __readImpl method is a recursive method that goes down the
+ // class hierarchy to marshal each slice of the class using the
+ // generated __readMemberImpl method.
+ //
+
+ if(type === undefined || type === IceObject)
+ {
+ return; // Don't marshal anything for IceObject
+ }
+
+ is.startReadSlice();
+ if(type.prototype.__readMemberImpl)
+ {
+ type.prototype.__readMemberImpl.call(obj, is);
+ }
+ is.endReadSlice();
+ __readImpl(obj, is, type.__parent);
+ };
+
+ var __writePreserved = function(os)
+ {
+ //
+ // For Slice classes which are marked "preserved", the implementation of this method
+ // replaces the Ice.Object.prototype.__write method.
+ //
+ os.startWriteObject(this.__slicedData);
+ __writeImpl(this, os, this.__mostDerivedType());
+ os.endWriteObject();
+ };
+
+ var __readPreserved = function(is)
+ {
+ //
+ // For Slice classes which are marked "preserved", the implementation of this method
+ // replaces the Ice.Object.prototype.__read method.
+ //
+ is.startReadObject();
+ __readImpl(this, is, this.__mostDerivedType());
+ this.__slicedData = is.endReadObject(true);
+ };
+
+ Ice.Object = IceObject;
+
+ Slice.defineLocalObject = function(constructor, base)
+ {
+ var obj = constructor || function(){};
+
+ if(base !== undefined)
+ {
+ obj.prototype = new base();
+ obj.__parent = base;
+ obj.prototype.constructor = constructor;
+ }
+
+ return obj;
+ };
+
+ Slice.defineObject = function(constructor, base, intfs, scope, ids, compactId, writeImpl, readImpl, preserved)
+ {
+ var obj = constructor || function(){};
+
+ obj.prototype = new base();
+ obj.__parent = base;
+ obj.__ids = ids;
+ obj.__id = ids[scope];
+ obj.__compactId = compactId;
+ obj.__instanceof = IceObject.__instanceof;
+ obj.__implements = intfs;
+
+ //
+ // These methods are used for object parameters.
+ //
+ obj.write = function(os, v)
+ {
+ os.writeObject(v);
+ };
+ obj.writeOpt = function(os, tag, v)
+ {
+ os.writeOptObject(tag, v);
+ };
+ obj.read = function(is)
+ {
+ var v = { value: null };
+ is.readObject(function(o) { v.value = o; }, obj);
+ return v;
+ };
+ obj.readOpt = function(is, tag)
+ {
+ var v = { value: undefined };
+ is.readOptObject(tag, function(o) { v.value = o; }, obj);
+ return v;
+ };
+
+ obj.ice_staticId = function()
+ {
+ return ids[scope];
+ };
+
+ obj.prototype.constructor = obj;
+ obj.prototype.__mostDerivedType = function() { return obj; };
+ if(preserved)
+ {
+ obj.prototype.__write = __writePreserved;
+ obj.prototype.__read = __readPreserved;
+ }
+ obj.prototype.__writeMemberImpl = writeImpl;
+ obj.prototype.__readMemberImpl = readImpl;
+
+ return obj;
+ };
+
+ global.Slice = Slice;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ObjectAdapterFactory.js b/js/src/Ice/ObjectAdapterFactory.js
new file mode 100644
index 00000000000..8fe50d5d872
--- /dev/null
+++ b/js/src/Ice/ObjectAdapterFactory.js
@@ -0,0 +1,150 @@
+// **********************************************************************
+//
+// 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/AsyncResultBase");
+ require("Ice/LocalException");
+ require("Ice/ObjectAdapterI");
+ require("Ice/Promise");
+ require("Ice/UUID");
+
+ var Ice = global.Ice || {};
+
+ var AsyncResultBase = Ice.AsyncResultBase;
+ var ObjectAdapterI = Ice.ObjectAdapterI;
+ var Promise = Ice.Promise;
+ var UUID = Ice.UUID;
+
+ //
+ // Only for use by Instance.
+ //
+ var ObjectAdapterFactory = Ice.Class({
+ __init__: function(instance, communicator)
+ {
+ this._instance = instance;
+ this._communicator = communicator;
+ this._adapters = [];
+ this._adapterNamesInUse = [];
+ this._shutdownPromise = new Promise();
+ },
+ shutdown: function()
+ {
+ //
+ // Ignore shutdown requests if the object adapter factory has
+ // already been shut down.
+ //
+ if(this._instance === null)
+ {
+ return this._shutdownPromise;
+ }
+
+ this._instance = null;
+ this._communicator = null;
+ var self = this;
+ Promise.all(
+ this._adapters.map(function(adapter)
+ {
+ return adapter.deactivate();
+ })
+ ).then(
+ function()
+ {
+ self._shutdownPromise.succeed();
+ },
+ function(ex)
+ {
+ self._shutdownPromise.fail(ex);
+ }
+ );
+ return this._shutdownPromise;
+ },
+ waitForShutdown: function()
+ {
+ var self = this;
+ return this._shutdownPromise.then(
+ function()
+ {
+ return Promise.all(self._adapters.map(function(adapter)
+ {
+ return adapter.waitForDeactivate();
+ }));
+ });
+ },
+ isShutdown: function()
+ {
+ return this._instance === null;
+ },
+ destroy: function()
+ {
+ var self = this;
+ return this.waitForShutdown().then(
+ function()
+ {
+ return Promise.all(self._adapters.map(function(adapter)
+ {
+ return adapter.destroy();
+ }));
+ });
+ },
+ createObjectAdapter: function(name, router, promise)
+ {
+ if(this._instance === null)
+ {
+ throw new Ice.ObjectAdapterDeactivatedException();
+ }
+
+ var adapter = null;
+ try
+ {
+ if(name.length === 0)
+ {
+ var uuid = UUID.generateUUID();
+ adapter = new ObjectAdapterI(this._instance, this._communicator, this, uuid, null, true, promise);
+ }
+ else
+ {
+ if(this._adapterNamesInUse.indexOf(name) !== -1)
+ {
+ throw new Ice.AlreadyRegisteredException("object adapter", name);
+ }
+ adapter = new ObjectAdapterI(this._instance, this._communicator, this, name, router, false, promise);
+ this._adapterNamesInUse.push(name);
+ }
+ this._adapters.push(adapter);
+ }
+ catch(ex)
+ {
+ promise.fail(ex, promise);
+ }
+ },
+ removeObjectAdapter: function(adapter)
+ {
+ if(this._instance === null)
+ {
+ return;
+ }
+
+ var n = this._adapters.indexOf(adapter);
+ if(n !== -1)
+ {
+ this._adapters.splice(n, 1);
+ }
+
+ n = this._adapterNamesInUse.indexOf(adapter.getName());
+ if(n !== -1)
+ {
+ this._adapterNamesInUse.splice(n, 1);
+ }
+ }
+ });
+
+ Ice.ObjectAdapterFactory = ObjectAdapterFactory;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ObjectAdapterI.js b/js/src/Ice/ObjectAdapterI.js
new file mode 100644
index 00000000000..422b6a759e6
--- /dev/null
+++ b/js/src/Ice/ObjectAdapterI.js
@@ -0,0 +1,547 @@
+// **********************************************************************
+//
+// 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/AsyncResultBase");
+ require("Ice/Debug");
+ require("Ice/Identity");
+ require("Ice/LocalException");
+ require("Ice/Promise");
+ require("Ice/PropertyNames");
+ require("Ice/Router");
+ require("Ice/ServantManager");
+ require("Ice/StringUtil");
+ require("Ice/UUID");
+
+ var Ice = global.Ice || {};
+
+ var AsyncResultBase = Ice.AsyncResultBase;
+ var Debug = Ice.Debug;
+ var Identity = Ice.Identity;
+ var Promise = Ice.Promise;
+ var PropertyNames = Ice.PropertyNames;
+ var ServantManager = Ice.ServantManager;
+ var StringUtil = Ice.StringUtil;
+ var UUID = Ice.UUID;
+
+ var _suffixes =
+ [
+ "ACM",
+ "AdapterId",
+ "Endpoints",
+ "Locator",
+ "Locator.EncodingVersion",
+ "Locator.EndpointSelection",
+ "Locator.ConnectionCached",
+ "Locator.PreferSecure",
+ "Locator.CollocationOptimized",
+ "Locator.Router",
+ "PublishedEndpoints",
+ "RegisterProcess",
+ "ReplicaGroupId",
+ "Router",
+ "Router.EncodingVersion",
+ "Router.EndpointSelection",
+ "Router.ConnectionCached",
+ "Router.PreferSecure",
+ "Router.CollocationOptimized",
+ "Router.Locator",
+ "Router.Locator.EndpointSelection",
+ "Router.Locator.ConnectionCached",
+ "Router.Locator.PreferSecure",
+ "Router.Locator.CollocationOptimized",
+ "Router.Locator.LocatorCacheTimeout",
+ "Router.LocatorCacheTimeout",
+ "ProxyOptions",
+ "ThreadPool.Size",
+ "ThreadPool.SizeMax",
+ "ThreadPool.SizeWarn",
+ "ThreadPool.StackSize",
+ "ThreadPool.Serialize"
+ ];
+
+ //
+ // Only for use by IceInternal.ObjectAdapterFactory
+ //
+ var ObjectAdapterI = Ice.Class({
+ __init__: function(instance, communicator, objectAdapterFactory, name, router, noConfig, promise)
+ {
+ this._deactivated = false;
+ this._instance = instance;
+ this._communicator = communicator;
+ this._objectAdapterFactory = objectAdapterFactory;
+ this._servantManager = new ServantManager(instance, name);
+ this._name = name;
+ this._routerEndpoints = [];
+ this._routerInfo = null;
+ this._destroyed = false;
+ this._noConfig = noConfig;
+
+ if(this._noConfig)
+ {
+ this._reference = this._instance.referenceFactory().createFromString("dummy -t", "");
+ promise.succeed(this, promise);
+ return;
+ }
+
+ var properties = this._instance.initializationData().properties;
+ var unknownProps = [];
+ var noProps = this.filterProperties(unknownProps);
+
+ //
+ // Warn about unknown object adapter properties.
+ //
+ if(unknownProps.length !== 0 && properties.getPropertyAsIntWithDefault("Ice.Warn.UnknownProperties", 1) > 0)
+ {
+ var message = ["found unknown properties for object adapter `" + name + "':"];
+ for(var i = 0; i < unknownProps.length; ++i)
+ {
+ message.push("\n " + unknownProps[i]);
+ }
+ this._instance.initializationData().logger.warning(message.join(""));
+ }
+
+ //
+ // Make sure named adapter has some configuration.
+ //
+ if(router === null && noProps)
+ {
+ var ex = new Ice.InitializationException();
+ ex.reason = "object adapter `" + this._name + "' requires configuration";
+ throw ex;
+ }
+
+ //
+ // Setup a reference to be used to get the default proxy options
+ // when creating new proxies. By default, create twoway proxies.
+ //
+ var proxyOptions = properties.getPropertyWithDefault(this._name + ".ProxyOptions", "-t");
+ try
+ {
+ this._reference = this._instance.referenceFactory().createFromString("dummy " + proxyOptions, "");
+ }
+ catch(e)
+ {
+ if(e instanceof Ice.ProxyParseException)
+ {
+ var ex = new Ice.InitializationException();
+ ex.reason = "invalid proxy options `" + proxyOptions + "' for object adapter `" + name + "'";
+ throw ex;
+ }
+ else
+ {
+ throw e;
+ }
+ }
+
+ try
+ {
+
+ if(router === null)
+ {
+ router = Ice.RouterPrx.uncheckedCast(
+ this._instance.proxyFactory().propertyToProxy(this._name + ".Router"));
+ }
+ if(router !== null)
+ {
+ this._routerInfo = this._instance.routerManager().find(router);
+ Debug.assert(this._routerInfo !== null);
+
+ //
+ // Make sure this router is not already registered with another adapter.
+ //
+ if(this._routerInfo.getAdapter() !== null)
+ {
+ throw new Ice.AlreadyRegisteredException(
+ "object adapter with router",
+ this._instance.identityToString(router.ice_getIdentity()));
+ }
+
+ //
+ // Add the router's server proxy endpoints to this object
+ // adapter.
+ //
+ var self = this;
+ this._routerInfo.getServerEndpoints().then(
+ function(endpoints)
+ {
+ var i;
+
+ for(i = 0; i < endpoints.length; ++i)
+ {
+ self._routerEndpoints.push(endpoints[i]);
+ }
+ self._routerEndpoints.sort( // Must be sorted.
+ function(e1, e2)
+ {
+ return e1.compareTo(e2);
+ });
+
+ //
+ // Remove duplicate endpoints, so we have a list of unique
+ // endpoints.
+ //
+ for(i = 0; i < self._routerEndpoints.length - 1;)
+ {
+ var e1 = self._routerEndpoints[i];
+ var e2 = self._routerEndpoints[i + 1];
+ if(e1.equals(e2))
+ {
+ self._routerEndpoints.splice(i, 1);
+ }
+ else
+ {
+ ++i;
+ }
+ }
+
+ //
+ // Associate this object adapter with the router. This way,
+ // new outgoing connections to the router's client proxy will
+ // use this object adapter for callbacks.
+ //
+ self._routerInfo.setAdapter(self);
+
+ //
+ // Also modify all existing outgoing connections to the
+ // router's client proxy to use this object adapter for
+ // callbacks.
+ //
+ return self._instance.outgoingConnectionFactory().setRouterInfo(self._routerInfo);
+ }
+ ).then(
+ function()
+ {
+ promise.succeed(self, promise);
+ },
+ function(ex)
+ {
+ promise.fail(ex, promise);
+ });
+ }
+ else
+ {
+ var endpoints = properties.getProperty(this._name + ".Endpoints");
+ if(endpoints.length > 0)
+ {
+ throw new Ice.FeatureNotSupportedException("object adapter endpoints not supported");
+ }
+ promise.succeed(this, promise);
+ }
+ }
+ catch(ex)
+ {
+ this.destroy();
+ throw ex;
+ }
+ },
+ getName: function()
+ {
+ //
+ // No mutex lock necessary, _name is immutable.
+ //
+ return this._noConfig ? "" : this._name;
+ },
+ getCommunicator: function()
+ {
+ return this._communicator;
+ },
+ activate: function()
+ {
+ },
+ hold: function()
+ {
+ this.checkForDeactivation();
+ },
+ waitForHold: function()
+ {
+ var promise = new AsyncResultBase(this._communicator, "waitForHold", null, null, this);
+ if(adapter.checkForDeactivation(promise))
+ {
+ return promise;
+ }
+ return promise.succeed(promise);
+ },
+ deactivate: function()
+ {
+ var promise = new AsyncResultBase(this._communicator, "deactivate", null, null, this);
+ if(!this._deactivated)
+ {
+ this._deactivated = true;
+ this._instance.outgoingConnectionFactory().removeAdapter(this);
+ }
+ return promise.succeed(promise);
+ },
+ waitForDeactivate: function()
+ {
+ var promise = new AsyncResultBase(this._communicator, "deactivate", null, null, this);
+ return promise.succeed(promise);
+ },
+ isDeactivated: function()
+ {
+ return this._deactivated;
+ },
+ destroy: function()
+ {
+ var promise = new AsyncResultBase(this._communicator, "destroy", null, null, this);
+ if(!this._deactivated)
+ {
+ this.deactivate();
+ }
+ if(!this._destroyed)
+ {
+ this._destroyed = true;
+ this._servantManager.destroy();
+ this._objectAdapterFactory.removeObjectAdapter(this);
+ }
+ return promise.succeed(promise);
+ },
+ add: function(object, ident)
+ {
+ return this.addFacet(object, ident, "");
+ },
+ addFacet: function(object, ident, facet)
+ {
+ this.checkForDeactivation();
+ this.checkIdentity(ident);
+
+ //
+ // Create a copy of the Identity argument, in case the caller
+ // reuses it.
+ //
+ var id = ident.clone();
+
+ this._servantManager.addServant(object, id, facet);
+
+ return this.newProxy(id, facet);
+ },
+ addWithUUID: function(object)
+ {
+ return this.addFacetWithUUID(object, "");
+ },
+ addFacetWithUUID: function(object, facet)
+ {
+ return this.addFacet(object, new Identity(UUID.generateUUID(), ""), facet);
+ },
+ addDefaultServant: function(servant, category)
+ {
+ this.checkForDeactivation();
+
+ this._servantManager.addDefaultServant(servant, category);
+ },
+ remove: function(ident)
+ {
+ return this.removeFacet(ident, "");
+ },
+ removeFacet: function(ident, facet)
+ {
+ this.checkForDeactivation();
+ this.checkIdentity(ident);
+
+ return this._servantManager.removeServant(ident, facet);
+ },
+ removeAllFacets: function(ident)
+ {
+ this.checkForDeactivation();
+ this.checkIdentity(ident);
+
+ return this._servantManager.removeAllFacets(ident);
+ },
+ removeDefaultServant: function(category)
+ {
+ this.checkForDeactivation();
+
+ return this._servantManager.removeDefaultServant(category);
+ },
+ find: function(ident)
+ {
+ return this.findFacet(ident, "");
+ },
+ findFacet: function(ident, facet)
+ {
+ this.checkForDeactivation();
+ this.checkIdentity(ident);
+
+ return this._servantManager.findServant(ident, facet);
+ },
+ findAllFacets: function(ident)
+ {
+ this.checkForDeactivation();
+ this.checkIdentity(ident);
+
+ return this._servantManager.findAllFacets(ident);
+ },
+ findByProxy: function(proxy)
+ {
+ this.checkForDeactivation();
+
+ var ref = proxy.__reference();
+ return this.findFacet(ref.getIdentity(), ref.getFacet());
+ },
+ findDefaultServant: function(category)
+ {
+ this.checkForDeactivation();
+
+ return this._servantManager.findDefaultServant(category);
+ },
+ addServantLocator: function(locator, prefix)
+ {
+ this.checkForDeactivation();
+
+ this._servantManager.addServantLocator(locator, prefix);
+ },
+ removeServantLocator: function(prefix)
+ {
+ this.checkForDeactivation();
+
+ return this._servantManager.removeServantLocator(prefix);
+ },
+ findServantLocator: function(prefix)
+ {
+ this.checkForDeactivation();
+
+ return this._servantManager.findServantLocator(prefix);
+ },
+ createProxy: function(ident)
+ {
+ this.checkForDeactivation();
+ this.checkIdentity(ident);
+
+ return this.newProxy(ident, "");
+ },
+ createDirectProxy: function(ident)
+ {
+ return this.createProxy(ident);
+ },
+ createIndirectProxy: function(ident)
+ {
+ throw new Ice.FeatureNotSupportedException("setLocator not supported");
+ },
+ setLocator: function(locator)
+ {
+ throw new Ice.FeatureNotSupportedException("setLocator not supported");
+ },
+ refreshPublishedEndpoints: function()
+ {
+ throw new Ice.FeatureNotSupportedException("refreshPublishedEndpoints not supported");
+ },
+ getEndpoints: function()
+ {
+ return [];
+ },
+ getPublishedEndpoints: function()
+ {
+ return [];
+ },
+ getServantManager: function()
+ {
+ //
+ // _servantManager is immutable.
+ //
+ return this._servantManager;
+ },
+ newProxy: function(ident, facet)
+ {
+ var endpoints = [];
+
+ //
+ // Now we also add the endpoints of the router's server proxy, if
+ // any. This way, object references created by this object adapter
+ // will also point to the router's server proxy endpoints.
+ //
+ for(var i = 0; i < this._routerEndpoints.length; ++i)
+ {
+ endpoints.push(this._routerEndpoints[i]);
+ }
+
+ //
+ // Create a reference and return a proxy for this reference.
+ //
+ var ref = this._instance.referenceFactory().create(ident, facet, this._reference, endpoints);
+ return this._instance.proxyFactory().referenceToProxy(ref);
+ },
+ checkForDeactivation: function(promise)
+ {
+ if(this._deactivated)
+ {
+ var ex = new Ice.ObjectAdapterDeactivatedException();
+ ex.name = this.getName();
+
+ if(promise !== undefined)
+ {
+ promise.fail(ex, promise);
+ return true;
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ return false;
+ },
+ checkIdentity: function(ident)
+ {
+ if(ident.name === undefined || ident.name === null || ident.name.length === 0)
+ {
+ var e = new Ice.IllegalIdentityException();
+ e.id = ident.clone();
+ throw e;
+ }
+
+ if(ident.category === undefined || ident.category === null)
+ {
+ ident.category = "";
+ }
+ },
+ filterProperties: function(unknownProps)
+ {
+ //
+ // Do not create unknown properties list if Ice prefix, i.e., Ice, Glacier2, etc.
+ //
+ var addUnknown = true, i;
+ var prefix = this._name + ".";
+ for(i = 0; i < PropertyNames.clPropNames.length; ++i)
+ {
+ if(prefix.indexOf(PropertyNames.clPropNames[i] + ".") === 0)
+ {
+ addUnknown = false;
+ break;
+ }
+ }
+
+ var noProps = true;
+ var props = this._instance.initializationData().properties.getPropertiesForPrefix(prefix);
+ for(var e = props.entries; e !== null; e = e.next)
+ {
+ var valid = false;
+ for(i = 0; i < _suffixes.length; ++i)
+ {
+ if(e.key === prefix + _suffixes[i])
+ {
+ noProps = false;
+ valid = true;
+ break;
+ }
+ }
+
+ if(!valid && addUnknown)
+ {
+ unknownProps.push(e.key);
+ }
+ }
+
+ return noProps;
+ }
+ });
+
+ Ice.ObjectAdapterI = ObjectAdapterI;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ObjectFactory.js b/js/src/Ice/ObjectFactory.js
new file mode 100644
index 00000000000..2f178c4c73c
--- /dev/null
+++ b/js/src/Ice/ObjectFactory.js
@@ -0,0 +1,28 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+
+ require("Ice/Class");
+
+ var ObjectFactory = Ice.Class({
+ create: function(type)
+ {
+ throw new Error("not implemented");
+ },
+ destroy: function()
+ {
+ throw new Error("not implemented");
+ }
+ });
+
+ Ice.ObjectFactory = ObjectFactory;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ObjectFactoryManager.js b/js/src/Ice/ObjectFactoryManager.js
new file mode 100644
index 00000000000..bffaeaa3070
--- /dev/null
+++ b/js/src/Ice/ObjectFactoryManager.js
@@ -0,0 +1,76 @@
+// **********************************************************************
+//
+// 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/HashMap");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var HashMap = Ice.HashMap;
+ var AlreadyRegisteredException = Ice.AlreadyRegisteredException;
+ var NotRegisteredException = Ice.NotRegisteredException;
+
+ //
+ // Only for use by Instance
+ //
+ var ObjectFactoryManager = Ice.Class({
+ __init__: function()
+ {
+ this._factoryMap = new HashMap(); // Map<String, ObjectFactory>
+ },
+ add: function(factory, id)
+ {
+ var o, ex;
+ o = this._factoryMap.get(id);
+ if(o !== undefined)
+ {
+ ex = new AlreadyRegisteredException();
+ ex.id = id;
+ ex.kindOfObject = "object factory";
+ throw ex;
+ }
+ this._factoryMap.set(id, factory);
+ },
+ remove: function(id)
+ {
+ var factory, ex;
+ factory = this._factoryMap.get(id);
+ if(factory === undefined)
+ {
+ ex = new NotRegisteredException();
+ ex.id = id;
+ ex.kindOfObject = "object factory";
+ throw ex;
+ }
+ this._factoryMap.delete(id);
+ factory.destroy();
+ },
+ find: function(id)
+ {
+ return this._factoryMap.get(id);
+ },
+ destroy: function()
+ {
+ var oldMap = this._factoryMap,
+ e = oldMap.entries;
+ this._factoryMap = new HashMap(); // Map<String, ObjectFactory>
+
+ while(e !== null)
+ {
+ e.value.destroy();
+ e = e.next;
+ }
+ }
+ });
+
+ Ice.ObjectFactoryManager = ObjectFactoryManager;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ObjectPrx.js b/js/src/Ice/ObjectPrx.js
new file mode 100644
index 00000000000..e6e2e0da9aa
--- /dev/null
+++ b/js/src/Ice/ObjectPrx.js
@@ -0,0 +1,967 @@
+// **********************************************************************
+//
+// 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/ArrayUtil");
+ require("Ice/AsyncResult");
+ require("Ice/ConnectRequestHandler");
+ require("Ice/Debug");
+ require("Ice/FormatType");
+ require("Ice/HashMap");
+ require("Ice/OutgoingAsync");
+ require("Ice/ProxyBatchOutgoingAsync");
+ require("Ice/ReferenceMode");
+ require("Ice/Current");
+ require("Ice/Exception");
+ require("Ice/BuiltinSequences");
+ require("Ice/LocalException");
+ require("Ice/Object");
+
+ var Ice = global.Ice || {};
+ var Slice = global.Slice || {};
+
+ var ArrayUtil = Ice.ArrayUtil;
+ var AsyncResultBase = Ice.AsyncResultBase;
+ var AsyncResult = Ice.AsyncResult;
+ var ConnectRequestHandler = Ice.ConnectRequestHandler;
+ var Debug = Ice.Debug;
+ var FormatType = Ice.FormatType;
+ var HashMap = Ice.HashMap;
+ var OutgoingAsync = Ice.OutgoingAsync;
+ var ProxyBatchOutgoingAsync = Ice.ProxyBatchOutgoingAsync;
+ var RefMode = Ice.ReferenceMode;
+ var OperationMode = Ice.OperationMode;
+
+ //
+ // Ice.ObjectPrx
+ //
+ var ObjectPrx = Ice.Class({
+ __init__: function()
+ {
+ this._reference = null;
+ this._handler = null;
+ },
+ hashCode: function(r)
+ {
+ return this._reference.hashCode();
+ },
+ ice_getCommunicator: function()
+ {
+ return this._reference.getCommunicator();
+ },
+ toString: function()
+ {
+ return this._reference.toString();
+ },
+ ice_getIdentity: function()
+ {
+ return this._reference.getIdentity().clone();
+ },
+ ice_identity: function(newIdentity)
+ {
+ if(newIdentity === undefined || newIdentity === null || newIdentity.name.length === 0)
+ {
+ throw new Ice.IllegalIdentityException();
+ }
+ if(newIdentity.equals(this._reference.getIdentity()))
+ {
+ return this;
+ }
+ else
+ {
+ var proxy = new ObjectPrx();
+ proxy.__setup(this._reference.changeIdentity(newIdentity));
+ return proxy;
+ }
+ },
+ ice_getContext: function()
+ {
+ return new HashMap(this._reference.getContext());
+ },
+ ice_context: function(newContext)
+ {
+ return this.__newInstance(this._reference.changeContext(newContext));
+ },
+ ice_getFacet: function()
+ {
+ return this._reference.getFacet();
+ },
+ ice_facet: function(newFacet)
+ {
+ if(newFacet === undefined || newFacet === null)
+ {
+ newFacet = "";
+ }
+
+ if(newFacet === this._reference.getFacet())
+ {
+ return this;
+ }
+ else
+ {
+ var proxy = new ObjectPrx();
+ proxy.__setup(this._reference.changeFacet(newFacet));
+ return proxy;
+ }
+ },
+ ice_getAdapterId: function()
+ {
+ return this._reference.getAdapterId();
+ },
+ ice_adapterId: function(newAdapterId)
+ {
+ if(newAdapterId === undefined || newAdapterId === null)
+ {
+ newAdapterId = "";
+ }
+
+ if(newAdapterId === this._reference.getAdapterId())
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeAdapterId(newAdapterId));
+ }
+ },
+ ice_getEndpoints: function()
+ {
+ return ArrayUtil.clone(this._reference.getEndpoints());
+ },
+ ice_endpoints: function(newEndpoints)
+ {
+ if(newEndpoints === undefined || newEndpoints === null)
+ {
+ newEndpoints = [];
+ }
+
+ if(ArrayUtil.equals(newEndpoints, this._reference.getEndpoints()))
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeEndpoints(newEndpoints));
+ }
+ },
+ ice_getLocatorCacheTimeout: function()
+ {
+ return this._reference.getLocatorCacheTimeout();
+ },
+ ice_locatorCacheTimeout: function(newTimeout)
+ {
+ if(newTimeout === this._reference.getLocatorCacheTimeout())
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeLocatorCacheTimeout(newTimeout));
+ }
+ },
+ ice_isConnectionCached: function()
+ {
+ return this._reference.getCacheConnection();
+ },
+ ice_connectionCached: function(newCache)
+ {
+ if(newCache === this._reference.getCacheConnection())
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeCacheConnection(newCache));
+ }
+ },
+ ice_getEndpointSelection: function()
+ {
+ return this._reference.getEndpointSelection();
+ },
+ ice_endpointSelection: function(newType)
+ {
+ if(newType === this._reference.getEndpointSelection())
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeEndpointSelection(newType));
+ }
+ },
+ ice_isSecure: function()
+ {
+ return this._reference.getSecure();
+ },
+ ice_secure: function(b)
+ {
+ if(b === this._reference.getSecure())
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeSecure(b));
+ }
+ },
+ ice_getEncodingVersion: function()
+ {
+ return this._reference.getEncoding().clone();
+ },
+ ice_encodingVersion: function(e)
+ {
+ if(e.equals(this._reference.getEncoding()))
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeEncoding(e));
+ }
+ },
+ ice_isPreferSecure: function()
+ {
+ return this._reference.getPreferSecure();
+ },
+ ice_preferSecure: function(b)
+ {
+ if(b === this._reference.getPreferSecure())
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changePreferSecure(b));
+ }
+ },
+ ice_getRouter: function()
+ {
+ var ri = this._reference.getRouterInfo();
+ return ri !== null ? ri.getRouter() : null;
+ },
+ ice_router: function(router)
+ {
+ var ref = this._reference.changeRouter(router);
+ if(ref.equals(this._reference))
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(ref);
+ }
+ },
+ ice_getLocator: function()
+ {
+ var ri = this._reference.getLocatorInfo();
+ return ri !== null ? ri.getLocator() : null;
+ },
+ ice_locator: function(locator)
+ {
+ var ref = this._reference.changeLocator(locator);
+ if(ref.equals(this._reference))
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(ref);
+ }
+ },
+ ice_isTwoway: function()
+ {
+ return this._reference.getMode() === RefMode.ModeTwoway;
+ },
+ ice_twoway: function()
+ {
+ if(this._reference.getMode() === RefMode.ModeTwoway)
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeMode(RefMode.ModeTwoway));
+ }
+ },
+ ice_isOneway: function()
+ {
+ return this._reference.getMode() === RefMode.ModeOneway;
+ },
+ ice_oneway: function()
+ {
+ if(this._reference.getMode() === RefMode.ModeOneway)
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeMode(RefMode.ModeOneway));
+ }
+ },
+ ice_isBatchOneway: function()
+ {
+ return this._reference.getMode() === RefMode.ModeBatchOneway;
+ },
+ ice_batchOneway: function()
+ {
+ if(this._reference.getMode() === RefMode.ModeBatchOneway)
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeMode(RefMode.ModeBatchOneway));
+ }
+ },
+ ice_isDatagram: function()
+ {
+ return this._reference.getMode() === RefMode.ModeDatagram;
+ },
+ ice_datagram: function()
+ {
+ if(this._reference.getMode() === RefMode.ModeDatagram)
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeMode(RefMode.ModeDatagram));
+ }
+ },
+ ice_isBatchDatagram: function()
+ {
+ return this._reference.getMode() === RefMode.ModeBatchDatagram;
+ },
+ ice_batchDatagram: function()
+ {
+ if(this._reference.getMode() === RefMode.ModeBatchDatagram)
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(this._reference.changeMode(RefMode.ModeBatchDatagram));
+ }
+ },
+ ice_compress: function(co)
+ {
+ var ref = this._reference.changeCompress(co);
+ if(ref.equals(this._reference))
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(ref);
+ }
+ },
+ ice_timeout: function(t)
+ {
+ var ref = this._reference.changeTimeout(t);
+ if(ref.equals(this._reference))
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(ref);
+ }
+ },
+ ice_getConnectionId: function()
+ {
+ return this._reference.getConnectionId();
+ },
+ ice_connectionId: function(id)
+ {
+ var ref = this._reference.changeConnectionId(id);
+ if(ref.equals(this._reference))
+ {
+ return this;
+ }
+ else
+ {
+ return this.__newInstance(ref);
+ }
+ },
+ ice_getConnection: function()
+ {
+ var __r = new AsyncResultBase(this._reference.getCommunicator(), "ice_getConnection", null, this, null);
+ this.__getRequestHandler().onConnection(__r);
+ return __r;
+ },
+ ice_getCachedConnection: function()
+ {
+ return this._handler ? this._handler.getConnection() : null;
+ },
+ ice_flushBatchRequests: function()
+ {
+ var __r = new ProxyBatchOutgoingAsync(this, "ice_flushBatchRequests");
+ try
+ {
+ __r.__send();
+ }
+ catch(__ex)
+ {
+ this.__handleLocalException(__r, __ex);
+ }
+ return __r;
+ },
+ equals: function(r)
+ {
+ if(this === r)
+ {
+ return true;
+ }
+
+ if(r instanceof ObjectPrx)
+ {
+ return this._reference.equals(r._reference);
+ }
+
+ return false;
+ },
+ __reference: function()
+ {
+ return this._reference;
+ },
+ __copyFrom: function(from)
+ {
+ Debug.assert(this._reference === null);
+ Debug.assert(this._handler === null);
+
+ this._reference = from._reference;
+
+ if(this._reference.getCacheConnection())
+ {
+ this._handler = from._handler;
+ }
+ },
+ __handleException: function(handler, ex, interval, cnt)
+ {
+ if(this._handler !== null && handler._connection === this._handler._connection)
+ {
+ this._handler = null;
+ }
+
+ if(cnt == -1) // Don't retry if the retry count is -1.
+ {
+ throw ex;
+ }
+
+ try
+ {
+ return this._reference.getInstance().proxyFactory().checkRetryAfterException(ex, this._reference,
+ interval, cnt);
+ }
+ catch(e)
+ {
+ if(e instanceof Ice.CommunicatorDestroyedException)
+ {
+ //
+ // The communicator is already destroyed, so we cannot
+ // retry.
+ //
+ throw ex;
+ }
+ else
+ {
+ throw e;
+ }
+ }
+ },
+ __handleExceptionWrapper: function(handler, ex)
+ {
+ if(this._handler !== null && handler._connection === this._handler._connection)
+ {
+ this._handler = null;
+ }
+
+ if(!ex.retry)
+ {
+ throw ex.inner;
+ }
+ },
+ __handleExceptionWrapperRelaxed: function(handler, ex, interval, cnt)
+ {
+ if(!ex.retry)
+ {
+ return this.__handleException(handler, ex.inner, interval, cnt);
+ }
+ else
+ {
+ if(this._handler !== null && handler._connection === this._handler._connection)
+ {
+ this._handler = null;
+ }
+
+ return cnt;
+ }
+ },
+ __checkAsyncTwowayOnly: function(name)
+ {
+ if(!this.ice_isTwoway())
+ {
+ throw new Error("`" + name + "' can only be called with a twoway proxy");
+ }
+ },
+ ice_invoke: function(operation, mode, inParams, ctx, explicitCtx)
+ {
+ if(explicitCtx && ctx === null)
+ {
+ ctx = new Ice.HashMap();
+ }
+
+ var self = this;
+
+ var completedFn = function(__res)
+ {
+ try
+ {
+ var results = [];
+ if((__r._state & AsyncResult.OK) === 0)
+ {
+ results.push(false);
+ }
+ else
+ {
+ results.push(true);
+ }
+ if(self._reference.getMode() === Ice.ReferenceMode.ModeTwoway)
+ {
+ results.push(__res._is.readEncaps(null));
+ }
+ results.push(__res);
+ __res.succeed.apply(__res, results);
+ }
+ catch(ex)
+ {
+ ObjectPrx.__dispatchLocalException(__res, ex);
+ return;
+ }
+ };
+
+ var __r = new OutgoingAsync(this, operation, completedFn, completedFn);
+
+ try
+ {
+ __r.__prepare(operation, mode, ctx);
+ __r.__writeParamEncaps(inParams);
+ __r.__send();
+ }
+ catch(ex)
+ {
+ this.__handleLocalException(__r, ex);
+ }
+ return __r;
+ },
+ __getRequestHandler: function()
+ {
+ if(this._reference.getCacheConnection())
+ {
+ if(this._handler !== null)
+ {
+ return this._handler;
+ }
+ this._handler = this.__createRequestHandler();
+ return this._handler;
+ }
+ else
+ {
+ return this.__createRequestHandler();
+ }
+ },
+ __setRequestHandler: function(handler)
+ {
+ if(this._reference.getCacheConnection())
+ {
+ this._handler = handler;
+ }
+ },
+ __createRequestHandler: function()
+ {
+ var handler = new ConnectRequestHandler(this._reference, this);
+ return handler.connect();
+ },
+ //
+ // Only for use by IceInternal.ProxyFactory
+ //
+ __setup: function(ref)
+ {
+ Debug.assert(this._reference === null);
+
+ this._reference = ref;
+ },
+ __newInstance: function(ref)
+ {
+ var proxy = new this.constructor();
+ proxy.__setup(ref);
+ return proxy;
+ },
+ __handleLocalException: function(__r, __ex)
+ {
+ if(__ex instanceof Ice.LocalException)
+ {
+ __r.__exception(__ex);
+ }
+ else
+ {
+ throw __ex;
+ }
+ },
+ ice_instanceof: function(T)
+ {
+ if(T)
+ {
+ if(this instanceof T)
+ {
+ return true;
+ }
+ return this.constructor.__instanceof(T);
+ }
+ return false;
+ }
+ });
+
+ //
+ // Generic invocation for operations that have input parameters.
+ //
+ ObjectPrx.__invoke = function(p, name, mode, fmt, ctx, marshalFn, unmarshalFn, userEx, args)
+ {
+ if(unmarshalFn !== null || userEx.length > 0)
+ {
+ p.__checkAsyncTwowayOnly(name);
+ }
+
+ var __r = new OutgoingAsync(p, name,
+ function(__res)
+ {
+ ObjectPrx.__completed(__res, unmarshalFn, userEx);
+ });
+
+ try
+ {
+ __r.__prepare(name, mode, ctx);
+ if(marshalFn === null)
+ {
+ __r.__writeEmptyParams();
+ }
+ else
+ {
+ var __os = __r.__startWriteParams(fmt);
+ marshalFn.call(null, __os, args);
+ __r.__endWriteParams();
+ }
+ __r.__send();
+ }
+ catch(ex)
+ {
+ p.__handleLocalException(__r, ex);
+ }
+ return __r;
+ };
+
+ //
+ // Handles the completion of an invocation.
+ //
+ ObjectPrx.__completed = function(__r, unmarshalFn, userEx)
+ {
+ if(!ObjectPrx.__check(__r, userEx))
+ {
+ return;
+ }
+
+ try
+ {
+ if(unmarshalFn === null)
+ {
+ __r.__readEmptyParams();
+ __r.succeed(__r);
+ }
+ else
+ {
+ var results = unmarshalFn(__r);
+ __r.succeed.apply(__r, results);
+ }
+ }
+ catch(ex)
+ {
+ ObjectPrx.__dispatchLocalException(__r, ex);
+ return;
+ }
+ };
+
+ //
+ // Unmarshal callback for operations that return a bool as the only result.
+ //
+ ObjectPrx.__returns_bool = function(__is, __results)
+ {
+ __results.push(__is.readBool());
+ };
+
+ //
+ // Unmarshal callback for operations that return a byte as the only result.
+ //
+ ObjectPrx.__returns_byte = function(__is, __results)
+ {
+ __results.push(__is.readByte());
+ };
+
+ //
+ // Unmarshal callback for operations that return a short as the only result.
+ //
+ ObjectPrx.__returns_short = function(__is, __results)
+ {
+ __results.push(__is.readShort());
+ };
+
+ //
+ // Unmarshal callback for operations that return an int as the only result.
+ //
+ ObjectPrx.__returns_int = function(__is, __results)
+ {
+ __results.push(__is.readInt());
+ };
+
+ //
+ // Unmarshal callback for operations that return a long as the only result.
+ //
+ ObjectPrx.__returns_long = function(__is, __results)
+ {
+ __results.push(__is.readLong());
+ };
+
+ //
+ // Unmarshal callback for operations that return a float as the only result.
+ //
+ ObjectPrx.__returns_float = function(__is, __results)
+ {
+ __results.push(__is.readFloat());
+ };
+
+ //
+ // Unmarshal callback for operations that return a double as the only result.
+ //
+ ObjectPrx.__returns_double = function(__is, __results)
+ {
+ __results.push(__is.readDouble());
+ };
+
+ //
+ // Unmarshal callback for operations that return a string as the only result.
+ //
+ ObjectPrx.__returns_string = function(__is, __results)
+ {
+ __results.push(__is.readString());
+ };
+
+ //
+ // Unmarshal callback for operations that return a proxy as the only result.
+ //
+ ObjectPrx.__returns_ObjectPrx = function(__is, __results)
+ {
+ __results.push(__is.readProxy());
+ };
+
+ //
+ // Unmarshal callback for operations that return an object as the only result.
+ //
+ ObjectPrx.__returns_Object = function(__is, __results)
+ {
+ __is.readObject(function(obj){ __results.push(obj); }, Ice.Object);
+ __is.readPendingObjects();
+ };
+
+ //
+ // Handles user exceptions.
+ //
+ ObjectPrx.__check = function(__r, __uex)
+ {
+ //
+ // If __uex is non-null, it must be an array of exception types.
+ //
+ try
+ {
+ __r.__throwUserException();
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.UserException)
+ {
+ if(__uex !== null)
+ {
+ for(var i = 0; i < __uex.length; ++i)
+ {
+ if(ex instanceof __uex[i])
+ {
+ __r.fail(ex, __r);
+ return false;
+ }
+ }
+ }
+ __r.fail(new Ice.UnknownUserException(ex.ice_name()), __r);
+ return false;
+ }
+ else
+ {
+ __r.fail(ex, __r);
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ ObjectPrx.__dispatchLocalException = function(__r, __ex)
+ {
+ __r.fail(__ex, __r);
+ };
+
+ ObjectPrx.ice_staticId = Ice.Object.ice_staticId;
+
+ ObjectPrx.checkedCast = function(prx, facet, ctx)
+ {
+ var __r = null;
+
+ if(prx === undefined || prx === null)
+ {
+ __r = new AsyncResultBase(null, "checkedCast", null, null, null);
+ __r.succeed(null, __r);
+ }
+ else
+ {
+ if(facet !== undefined)
+ {
+ prx = prx.ice_facet(facet);
+ }
+
+ var __h = new this();
+ __h.__copyFrom(prx);
+ __r = new AsyncResultBase(prx.ice_getCommunicator(), "checkedCast", null, __h, null);
+ prx.ice_isA(this.ice_staticId(), ctx).then(
+ function(__res, __ret)
+ {
+ __r.succeed(__ret ? __h : null, __r);
+ }).exception(
+ function(__ex)
+ {
+ if(__ex instanceof Ice.FacetNotExistException)
+ {
+ __r.succeed(null, __r);
+ }
+ else
+ {
+ __r.fail(__ex, __r);
+ }
+ });
+ }
+
+ return __r;
+ };
+
+ ObjectPrx.uncheckedCast = function(prx, facet)
+ {
+ var r = null;
+ if(prx !== undefined && prx !== null)
+ {
+ r = new this();
+ if(facet !== undefined)
+ {
+ prx = prx.ice_facet(facet);
+ }
+ r.__copyFrom(prx);
+ }
+ return r;
+ };
+
+ Object.defineProperty(ObjectPrx, "minWireSize", {
+ get: function(){ return 2; }
+ });
+
+ ObjectPrx.write = function(os, v)
+ {
+ os.writeProxy(v);
+ };
+
+ ObjectPrx.read = function(is)
+ {
+ return is.readProxy(this);
+ };
+
+ ObjectPrx.writeOpt = function(os, tag, v)
+ {
+ os.writeOptProxy(tag, v);
+ };
+
+ ObjectPrx.readOpt = function(is, tag)
+ {
+ return is.readOptProxy(tag, this);
+ };
+
+ ObjectPrx.__instanceof = function(T)
+ {
+ if(T === this)
+ {
+ return true;
+ }
+
+ for(var i in this.__implements)
+ {
+ if(this.__implements[i].__instanceof(T))
+ {
+ return true;
+ }
+ }
+
+ if(this.__parent)
+ {
+ return this.__parent.__instanceof(T);
+ }
+ return false;
+ };
+
+ Slice.defineProxy = function(base, staticId, prxInterfaces)
+ {
+ var prx = function()
+ {
+ base.call(this);
+ };
+ prx.__parent = base;
+ prx.__implements = prxInterfaces;
+
+ // All generated proxies inherit from ObjectPrx
+ prx.prototype = new base();
+ prx.prototype.constructor = prx;
+
+ // Static methods
+ prx.ice_staticId = staticId;
+
+ // Copy static methods inherited from ObjectPrx
+ prx.checkedCast = ObjectPrx.checkedCast;
+ prx.uncheckedCast = ObjectPrx.uncheckedCast;
+ prx.write = ObjectPrx.write;
+ prx.writeOpt = ObjectPrx.writeOpt;
+ prx.read = ObjectPrx.read;
+ prx.readOpt = ObjectPrx.readOpt;
+
+ prx.__instanceof = ObjectPrx.__instanceof;
+
+ // Static properties
+ Object.defineProperty(prx, "minWireSize", {
+ get: function(){ return 2; }
+ });
+
+ return prx;
+ };
+
+ Ice.ObjectPrx = ObjectPrx;
+
+ global.Slice = Slice;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/OpaqueEndpointI.js b/js/src/Ice/OpaqueEndpointI.js
new file mode 100644
index 00000000000..32472804727
--- /dev/null
+++ b/js/src/Ice/OpaqueEndpointI.js
@@ -0,0 +1,446 @@
+// **********************************************************************
+//
+// 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/Base64");
+ require("Ice/Debug");
+ require("Ice/FormatType");
+ require("Ice/HashUtil");
+ require("Ice/Protocol");
+ require("Ice/StringUtil");
+ require("Ice/Endpoint");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var Base64 = Ice.Base64;
+ var Debug = Ice.Debug;
+ var HashUtil = Ice.HashUtil;
+ var Protocol = Ice.Protocol;
+ var StringUtil = Ice.StringUtil;
+
+ var Class = Ice.Class;
+
+ var OpaqueEndpointI = Class(Ice.Endpoint, {
+ //
+ // Marshal the endpoint
+ //
+ streamWrite: function(s)
+ {
+ s.writeShort(this._type);
+ s.startWriteEncaps(this._rawEncoding, Ice.FormatType.DefaultFormat);
+ s.writeBlob(this._rawBytes);
+ s.endWriteEncaps();
+ },
+ //
+ // Convert the endpoint to its string form
+ //
+ toString: function()
+ {
+ var val = Base64.encode(this._rawBytes);
+ return "opaque -t " + this._type + " -e " + Ice.encodingVersionToString(this._rawEncoding) +
+ " -v " + val;
+ },
+ //
+ // Return the endpoint information.
+ //
+ getInfo: function()
+ {
+ return new OpaqueEndpointInfoI(-1, false, this._rawEncoding, this._rawBytes, this._type);
+ },
+ //
+ // Return the endpoint type
+ //
+ type: function()
+ {
+ return this._type;
+ },
+ protocol: function()
+ {
+ return "opaque";
+ },
+ //
+ // Return the timeout for the endpoint in milliseconds. 0 means
+ // non-blocking, -1 means no timeout.
+ //
+ timeout: function()
+ {
+ return -1;
+ },
+ //
+ // Return a new endpoint with a different timeout value, provided
+ // that timeouts are supported by the endpoint. Otherwise the same
+ // endpoint is returned.
+ //
+ changeTimeout: function(t)
+ {
+ return this;
+ },
+ //
+ // Return a new endpoint with a different connection id.
+ //
+ changeConnectionId: function(connectionId)
+ {
+ return this;
+ },
+ //
+ // Return true if the endpoints support bzip2 compress, or false
+ // otherwise.
+ //
+ compress: function()
+ {
+ return false;
+ },
+ //
+ // Return a new endpoint with a different compression value,
+ // provided that compression is supported by the
+ // endpoint. Otherwise the same endpoint is returned.
+ //
+ changeCompress: function(compress)
+ {
+ return this;
+ },
+ //
+ // Return true if the endpoint is datagram-based.
+ //
+ datagram: function()
+ {
+ return false;
+ },
+ //
+ // Return true if the endpoint is secure.
+ //
+ secure: function()
+ {
+ return false;
+ },
+ //
+ // Get the encoded endpoint.
+ //
+ rawBytes: function()
+ {
+ return this._rawBytes; // Returns a Uint8Array
+ },
+ //
+ // Return a server side transceiver for this endpoint, or null if a
+ // transceiver can only be created by an acceptor. In case a
+ // transceiver is created, this operation also returns a new
+ // "effective" endpoint, which might differ from this endpoint,
+ // for example, if a dynamic port number is assigned.
+ //
+ transceiver: function(endpoint)
+ {
+ endpoint.value = null;
+ return null;
+ },
+ //
+ // Return an acceptor for this endpoint, or null if no acceptors
+ // is available. In case an acceptor is created, this operation
+ // also returns a new "effective" endpoint, which might differ
+ // from this endpoint, for example, if a dynamic port number is
+ // assigned.
+ //
+ acceptor: function(endpoint, adapterName)
+ {
+ endpoint.value = this;
+ return null;
+ },
+ connect: function()
+ {
+ return null;
+ },
+ hashCode: function()
+ {
+ return this._hashCode;
+ },
+ //
+ // Compare endpoints for sorting purposes
+ //
+ equals: function(p)
+ {
+ if(!(p instanceof OpaqueEndpointI))
+ {
+ return false;
+ }
+
+ if(this === p)
+ {
+ return true;
+ }
+
+ if(this._type !== p._type)
+ {
+ return false;
+ }
+
+ if(!this._rawEncoding.equals(p._rawEncoding))
+ {
+ return false;
+ }
+
+ if(this._rawBytes.length !== p._rawBytes.length)
+ {
+ return false;
+ }
+ for(var i = 0; i < this._rawBytes.length; i++)
+ {
+ if(this._rawBytes[i] !== p._rawBytes[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ },
+ compareTo: function(p)
+ {
+ if(this === p)
+ {
+ return 0;
+ }
+
+ if(p === null)
+ {
+ return 1;
+ }
+
+ if(!(p instanceof OpaqueEndpointI))
+ {
+ return this.type() < p.type() ? -1 : 1;
+ }
+
+ if(this._type < p._type)
+ {
+ return -1;
+ }
+ else if(p._type < this._type)
+ {
+ return 1;
+ }
+
+ if(this._rawEncoding.major < p._rawEncoding.major)
+ {
+ return -1;
+ }
+ else if(p._rawEncoding.major < this._rawEncoding.major)
+ {
+ return 1;
+ }
+
+ if(this._rawEncoding.minor < p._rawEncoding.minor)
+ {
+ return -1;
+ }
+ else if(p._rawEncoding.minor < this._rawEncoding.minor)
+ {
+ return 1;
+ }
+
+ if(this._rawBytes.length < p._rawBytes.length)
+ {
+ return -1;
+ }
+ else if(p._rawBytes.length < this._rawBytes.length)
+ {
+ return 1;
+ }
+ for(var i = 0; i < this._rawBytes.length; i++)
+ {
+ if(this._rawBytes[i] < p._rawBytes[i])
+ {
+ return -1;
+ }
+ else if(p._rawBytes[i] < this._rawBytes[i])
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+ },
+ calcHashValue: function()
+ {
+ var h = 5381;
+ h = HashUtil.addNumber(h, this._type);
+ h = HashUtil.addHashable(h, this._rawEncoding);
+ h = HashUtil.addArray(h, this._rawBytes, HashUtil.addNumber);
+ this._hashCode = h;
+ }
+ });
+
+ OpaqueEndpointI.fromString = function(str)
+ {
+ var result = new OpaqueEndpointI();
+
+ result._rawEncoding = Protocol.Encoding_1_0;
+
+ var topt = 0;
+ var vopt = 0;
+
+ var arr = str.split(/[ \t\n\r]+/);
+ var i = 0;
+ while(i < arr.length)
+ {
+ if(arr[i].length === 0)
+ {
+ i++;
+ continue;
+ }
+
+ var option = arr[i++];
+ if(option.length != 2 && option.charAt(0) != '-')
+ {
+ throw new Ice.EndpointParseException("expected an endpoint option but found `" + option +
+ "' in endpoint `opaque " + str + "'");
+ }
+
+ var argument = null;
+ if(i < arr.length && arr[i].charAt(0) != '-')
+ {
+ argument = arr[i++];
+ }
+
+ switch(option.charAt(1))
+ {
+ case 't':
+ {
+ if(argument === null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -t option in endpoint `opaque " +
+ str + "'");
+ }
+
+ var type;
+
+ try
+ {
+ type = StringUtil.toInt(argument);
+ }
+ catch(ex)
+ {
+ throw new Ice.EndpointParseException("invalid type value `" + argument +
+ "' in endpoint `opaque " + str + "'");
+ }
+
+ if(type < 0 || type > 65535)
+ {
+ throw new Ice.EndpointParseException("type value `" + argument +
+ "' out of range in endpoint `opaque " + str + "'");
+ }
+
+ result._type = type;
+ ++topt;
+ if(topt > 1)
+ {
+ throw new Ice.EndpointParseException("multiple -t options in endpoint `opaque " + str + "'");
+ }
+ break;
+ }
+
+ case 'v':
+ {
+ if(argument === null || argument.length === 0)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -v option in endpoint `opaque " +
+ str + "'");
+ }
+ for(var j = 0; j < argument.length; ++j)
+ {
+ if(!Base64.isBase64(argument.charAt(j)))
+ {
+ throw new Ice.EndpointParseException("invalid base64 character `" + argument.charAt(j) +
+ "' (ordinal " + argument.charCodeAt(j) +
+ ") in endpoint `opaque " + str + "'");
+ }
+ }
+ result._rawBytes = Base64.decode(argument);
+ ++vopt;
+ if(vopt > 1)
+ {
+ throw new Ice.EndpointParseException("multiple -v options in endpoint `opaque " + str + "'");
+ }
+ break;
+ }
+
+ case 'e':
+ {
+ if(argument === null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -e option in endpoint `opaque " +
+ str + "'");
+ }
+ try
+ {
+ result._rawEncoding = Ice.stringToEncodingVersion(argument);
+ }
+ catch(e)
+ {
+ throw new Ice.EndpointParseException("invalid encoding version `" + argument +
+ "' in endpoint `opaque " + str + "':\n" + e.str);
+ }
+ break;
+ }
+
+ default:
+ {
+ throw new Ice.EndpointParseException("invalid option `" + option + "' in endpoint `opaque " +
+ str + "'");
+ }
+ }
+ }
+
+ if(topt != 1)
+ {
+ throw new Ice.EndpointParseException("no -t option in endpoint `opaque " + str + "'");
+ }
+ if(vopt != 1)
+ {
+ throw new Ice.EndpointParseException("no -v option in endpoint `opaque " + str + "'");
+ }
+ result.calcHashValue();
+ return result;
+ };
+
+ OpaqueEndpointI.fromStream = function(type, s)
+ {
+ var result = new OpaqueEndpointI();
+ result._type = type;
+ result._rawEncoding = s.startReadEncaps();
+ var sz = s.getReadEncapsSize();
+ result._rawBytes = s.readBlob(sz);
+ s.endReadEncaps();
+ result.calcHashValue();
+ return result;
+ };
+
+ Ice.OpaqueEndpointI = OpaqueEndpointI;
+
+ var OpaqueEndpointInfoI = Class(Ice.OpaqueEndpointInfo, {
+ __init__: function(timeout, compress, rawEncoding, rawBytes, type)
+ {
+ Ice.OpaqueEndpointInfo.call(this, -1, false, rawEncoding, rawBytes);
+ this._type = type;
+ },
+ type: function()
+ {
+ return this._type;
+ },
+ datagram: function()
+ {
+ return false;
+ },
+ secure: function()
+ {
+ return false;
+ }
+ });
+
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Operation.js b/js/src/Ice/Operation.js
new file mode 100644
index 00000000000..11a130f542f
--- /dev/null
+++ b/js/src/Ice/Operation.js
@@ -0,0 +1,773 @@
+// **********************************************************************
+//
+// 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/Current");
+ require("Ice/DispatchStatus");
+ require("Ice/Exception");
+ require("Ice/FormatType");
+ require("Ice/Object");
+ require("Ice/ObjectPrx");
+ require("Ice/OptionalFormat");
+ require("Ice/StreamHelpers");
+
+ var Ice = global.Ice || {};
+ var Slice = global.Slice || {};
+
+ /*jshint -W069 */
+
+ var Class = Ice.Class;
+
+ var builtinHelpers =
+ [
+ Ice.ByteHelper,
+ Ice.BoolHelper,
+ Ice.ShortHelper,
+ Ice.IntHelper,
+ Ice.LongHelper,
+ Ice.FloatHelper,
+ Ice.DoubleHelper,
+ Ice.StringHelper,
+ Ice.Object,
+ Ice.ObjectPrx
+ ];
+
+ function parseParam(p)
+ {
+ var type = p[0];
+ var t = typeof(type);
+ if(t === 'number')
+ {
+ type = builtinHelpers[p[0]];
+ }
+ else if(t === 'string')
+ {
+ /*jshint -W061 */
+ type = eval(type);
+ /*jshint +W061 */
+ }
+
+ return {
+ "type": type,
+ "isObject": (p[1] === true),
+ "tag": p[2] // Optional tag, which may not be present - an undefined tag means "not optional".
+ };
+ }
+
+ //
+ // Each operation descriptor is a property. The key is the "on-the-wire"
+ // name, and the value is an array consisting of the following elements:
+ //
+ // 0: native method name in case of a keyword conflict (e.g., "_while"),
+ // otherwise an empty string
+ // 1: mode (undefined == Normal or int)
+ // 2: sendMode (undefined == Normal or int)
+ // 3: amd (undefined or 1)
+ // 4: format (undefined == Default or int)
+ // 5: return type (undefined if void, or [type, tag])
+ // 6: in params (undefined if none, or array of [type, tag])
+ // 7: out params (undefined if none, or array of [type, tag])
+ // 8: exceptions (undefined if none, or array of types)
+ // 9: sends classes (true or undefined)
+ // 10: returns classes (true or undefined)
+ //
+ function parseOperation(name, arr)
+ {
+ var r = {};
+ var i;
+ var p;
+
+ r["name"] = name;
+ r["mode"] = arr[1] ? Ice.OperationMode.valueOf(arr[1]) : Ice.OperationMode.Normal;
+ r["sendMode"] = arr[2] ? Ice.OperationMode.valueOf(arr[2]) : Ice.OperationMode.Normal;
+ r["amd"] = arr[3] ? true : false;
+ r["format"] = arr[4] ? Ice.FormatType.valueOf(arr[4]) : Ice.FormatType.DefaultFormat;
+
+ if(r["amd"])
+ {
+ r["servantMethod"] = name + "_async";
+ }
+ else
+ {
+ r["servantMethod"] = arr[0] ? arr[0] : name;
+ }
+
+ var ret;
+ if(arr[5])
+ {
+ ret = parseParam(arr[5]);
+ ret["pos"] = 0;
+ }
+ r["returns"] = ret;
+
+ var inParams = [];
+ var inParamsOpt = [];
+ if(arr[6])
+ {
+ for(i = 0; i < arr[6].length; ++i)
+ {
+ p = parseParam(arr[6][i]);
+ p["pos"] = i;
+ inParams.push(p);
+ if(p.tag)
+ {
+ inParamsOpt.push(p);
+ }
+ }
+ }
+ inParamsOpt.sort(function(p1, p2) { return p1.tag - p2.tag; }); // Sort by tag.
+ r["inParams"] = inParams;
+ r["inParamsOpt"] = inParamsOpt;
+
+ var outParams = [];
+ var outParamsOpt = [];
+ if(arr[7])
+ {
+ var offs = ret ? 1 : 0;
+ for(i = 0; i < arr[7].length; ++i)
+ {
+ p = parseParam(arr[7][i]);
+ p["pos"] = i + offs;
+ outParams.push(p);
+ if(p.tag)
+ {
+ outParamsOpt.push(p);
+ }
+ }
+ }
+ if(ret && ret.tag)
+ {
+ outParamsOpt.push(ret);
+ }
+ outParamsOpt.sort(function(p1, p2) { return p1.tag - p2.tag; }); // Sort by tag.
+ r["outParams"] = outParams;
+ r["outParamsOpt"] = outParamsOpt;
+
+ var exceptions = [];
+ if(arr[8])
+ {
+ for(i = 0; i < arr[8].length; ++i)
+ {
+ exceptions.push(arr[8][i]);
+ }
+ }
+ r["exceptions"] = exceptions;
+
+ r["sendsClasses"] = arr[9] === true;
+ r["returnsClasses"] = arr[10] === true;
+
+ return r;
+ }
+
+ var OpTable = Class({
+ __init__: function(ops)
+ {
+ this.raw = ops;
+ this.parsed = {};
+ },
+ find: function(name)
+ {
+ //
+ // Check if we've already parsed the operation.
+ //
+ var op = this.parsed[name];
+ if(op === undefined && this.raw[name] !== undefined)
+ {
+ //
+ // We haven't parsed it yet, but we found a match for the name, so parse it now.
+ //
+ op = parseOperation(name, this.raw[name]);
+ this.parsed[name] = op;
+ }
+ return op;
+ }
+ });
+
+ function unmarshalParams(is, retvalInfo, allParamInfo, optParamInfo, usesClasses, params, offset)
+ {
+ var i, p, v;
+ //
+ // First read all required params.
+ //
+ for(i = 0; i < allParamInfo.length; ++i)
+ {
+ p = allParamInfo[i];
+ if(!p.tag)
+ {
+ v = p.type.read(is);
+ params[p.pos + offset] = v;
+ }
+ }
+
+ //
+ // Then read a required return value (if any).
+ //
+ if(retvalInfo)
+ {
+ v = retvalInfo.type.read(is);
+ params[retvalInfo.pos + offset] = v;
+ }
+
+ //
+ // Then read all optional params.
+ //
+ for(i = 0; i < optParamInfo.length; ++i)
+ {
+ p = optParamInfo[i];
+ v = p.type.readOpt(is, p.tag);
+ params[p.pos + offset] = v;
+ }
+
+ if(usesClasses)
+ {
+ is.readPendingObjects();
+ }
+ }
+
+ function marshalParams(os, params, retvalInfo, paramInfo, optParamInfo, usesClasses)
+ {
+ var i, p;
+
+ //
+ // Write the required params.
+ //
+ for(i = 0; i < paramInfo.length; ++i)
+ {
+ p = paramInfo[i];
+ if(!p.tag)
+ {
+ p.type.write(os, params[p.pos]);
+ }
+ }
+
+ //
+ // retvalInfo should only be provided if there is a non-void required return value.
+ //
+ if(retvalInfo)
+ {
+ retvalInfo.type.write(os, params[retvalInfo.pos]);
+ }
+
+ //
+ // Write the optional params.
+ //
+ for(i = 0; i < optParamInfo.length; ++i)
+ {
+ p = optParamInfo[i];
+ p.type.writeOpt(os, p.tag, params[p.pos]);
+ }
+
+ if(usesClasses)
+ {
+ os.writePendingObjects();
+ }
+ }
+
+ var Upcall = Class({
+ __init__: function(incomingAsync, op)
+ {
+ this.incomingAsync = incomingAsync;
+ this.op = op;
+ },
+ ice_response: function()
+ {
+ var args = arguments;
+
+ if(this.incomingAsync.__validateResponse(true))
+ {
+ try
+ {
+ this.__sendResponse(args);
+ this.incomingAsync.__response();
+ }
+ catch(ex)
+ {
+ this.incomingAsync.__exception(ex);
+ }
+ }
+ },
+ ice_exception: function(ex)
+ {
+ if(this.__checkException(ex))
+ {
+ if(this.incomingAsync.__validateResponse(false))
+ {
+ this.__sendException(ex);
+ this.incomingAsync.__response();
+ }
+ }
+ else
+ {
+ this.incomingAsync.ice_exception(ex);
+ }
+ },
+ __sendResponse: function(results)
+ {
+ if(this.op.returns === undefined && this.op.outParams.length === 0)
+ {
+ if(results && results.length > 0)
+ {
+ //
+ // No results expected.
+ //
+ throw new Error("ice_response called with invalid arguments");
+ }
+ else
+ {
+ this.incomingAsync.__writeEmptyParams();
+ }
+ }
+ else
+ {
+ var __os = this.incomingAsync.__startWriteParams(this.op.format);
+ var retvalInfo;
+ if(this.op.returns && !this.op.returns.tag)
+ {
+ retvalInfo = this.op.returns;
+ }
+ marshalParams(__os, results, retvalInfo, this.op.outParams, this.op.outParamsOpt,
+ this.op.returnsClasses);
+ this.incomingAsync.__endWriteParams(true);
+ }
+ },
+ __checkException: function(ex)
+ {
+ //
+ // Make sure the given exception is an instance of one of the declared user exceptions
+ // for this operation.
+ //
+ for(var i = 0; i < this.op.exceptions.length; ++i)
+ {
+ if(ex instanceof this.op.exceptions[i])
+ {
+ //
+ // User exception is valid.
+ //
+ return true;
+ }
+ }
+
+ return false;
+ },
+ __sendException: function(ex)
+ {
+ //
+ // User exception is valid, now marshal it.
+ //
+ this.incomingAsync.__writeUserException(ex, this.op.format);
+ }
+ });
+
+ var __dispatchImpl = function(servant, op, incomingAsync, current)
+ {
+ //
+ // Check to make sure the servant implements the operation.
+ //
+ var method = servant[op.servantMethod];
+ if(method === undefined || typeof(method) !== "function")
+ {
+ var comm = current.adapter.getCommunicator();
+ var msg = "servant for identity " + comm.identityToString(current.id) +
+ " does not define operation `" + op.servantMethod + "'";
+ console.log(msg);
+ throw new Ice.UnknownException(msg);
+ }
+
+ var up = new Upcall(incomingAsync, op);
+
+ try
+ {
+ //
+ // Unmarshal the in params (if any).
+ //
+ var params = op.amd ? [null] : [];
+ if(op.inParams.length === 0)
+ {
+ incomingAsync.readEmptyParams();
+ }
+ else
+ {
+ var __is = incomingAsync.startReadParams();
+ var offset = op.amd ? 1 : 0;
+ unmarshalParams(__is, undefined, op.inParams, op.inParamsOpt, op.sendsClasses, params, offset);
+ incomingAsync.endReadParams();
+
+ //
+ // When unmarshaling objects, the ObjectHelper returns a wrapper object
+ // and eventually stores the unmarshaled object into its "value" member.
+ // Here we scan the parameter array and replace the wrappers with the
+ // actual object references.
+ //
+ if(op.inParams.length > 0 && (op.sendsClasses || op.inParamsOpt.length > 0))
+ {
+ for(var i = 0; i < op.inParams.length; ++i)
+ {
+ var p = op.inParams[i];
+ //
+ // Optional parameters may be undefined.
+ //
+ if(p.isObject && params[p.pos + offset] !== undefined)
+ {
+ params[p.pos + offset] = params[p.pos + offset].value;
+ }
+ }
+ }
+ }
+
+ params.push(current);
+
+ if(op.amd)
+ {
+ params[0] = up; // The AMD callback object.
+ try
+ {
+ method.apply(servant, params);
+ }
+ catch(ex)
+ {
+ up.ice_exception(ex);
+ }
+ return Ice.DispatchStatus.DispatchAsync;
+ }
+ else
+ {
+ //
+ // Determine how many out parameters to expect.
+ //
+ var numExpectedResults = op.outParams.length;
+ if(op.returns)
+ {
+ ++numExpectedResults;
+ }
+
+ var results = method.apply(servant, params);
+
+ //
+ // Complain if we expect more than out parameter and the servant doesn't return an array.
+ //
+ if(numExpectedResults > 1 && !(results instanceof Array))
+ {
+ var msg = "operation `" + op.servantMethod + "' should return an array of length " + numParams;
+ console.log(msg);
+ throw new Ice.MarshalException(msg);
+ }
+ else if(numExpectedResults === 1)
+ {
+ //
+ // Wrap a single out parameter in an array.
+ //
+ results = [results];
+ }
+
+ up.__sendResponse(results);
+ return Ice.DispatchStatus.DispatchOK;
+ }
+ }
+ catch(ex)
+ {
+ if(up.__checkException(ex))
+ {
+ up.__sendException(ex);
+ return Ice.DispatchStatus.DispatchUserException;
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ };
+
+ function getServantMethodFromInterfaces(interfaces, methodName, all)
+ {
+ var method;
+ for(var i = 0; method === undefined && i < interfaces.length; ++i)
+ {
+ var intf = interfaces[i];
+ method = intf[methodName];
+ if(method === undefined)
+ {
+ if(all.indexOf(intf) === -1)
+ {
+ all.push(intf);
+ }
+ if(intf.__implements)
+ {
+ method = getServantMethodFromInterfaces(intf.__implements, methodName, all);
+ }
+ }
+ }
+ return method;
+ }
+
+ var dispatchPrefix = "__op_";
+
+ function getServantMethod(servantType, name)
+ {
+ //
+ // The dispatch method is named __op_<Slice name> and is stored in the type (not the prototype).
+ //
+ var methodName = dispatchPrefix + name;
+
+ //
+ // First check the servant type.
+ //
+ var method = servantType[methodName];
+
+ var allInterfaces;
+
+ if(method === undefined)
+ {
+ allInterfaces = [];
+
+ //
+ // Now check the prototypes of the implemented interfaces.
+ //
+ var curr = servantType;
+ while(curr && method === undefined)
+ {
+ if(curr.__implements)
+ {
+ method = getServantMethodFromInterfaces(curr.__implements, methodName, allInterfaces);
+ }
+ curr = curr.__parent;
+ }
+
+ if(method !== undefined)
+ {
+ //
+ // Add the method to the servant's type.
+ //
+ servantType[methodName] = method;
+ }
+ }
+
+ if(method === undefined)
+ {
+ //
+ // Next check the op table for the servant's type.
+ //
+ var op;
+ if(servantType.__ops)
+ {
+ op = servantType.__ops.find(name);
+ }
+
+ var source;
+ if(op === undefined)
+ {
+ //
+ // Now check the op tables of the base types.
+ //
+ var parent = servantType.__parent;
+ while(op === undefined && parent)
+ {
+ if(parent.__ops)
+ {
+ if((op = parent.__ops.find(name)) !== undefined)
+ {
+ source = parent;
+ }
+ }
+ parent = parent.__parent;
+ }
+
+ //
+ // Now check the op tables of all base interfaces.
+ //
+ for(var i = 0; op === undefined && i < allInterfaces.length; ++i)
+ {
+ var intf = allInterfaces[i];
+ if(intf.__ops)
+ {
+ if((op = intf.__ops.find(name)) !== undefined)
+ {
+ source = intf;
+ }
+ }
+ }
+ }
+
+ if(op !== undefined)
+ {
+ method = function(servant, incomingAsync, current)
+ {
+ return __dispatchImpl(servant, op, incomingAsync, current);
+ };
+
+ //
+ // Add the method to the servant type.
+ //
+ servantType[methodName] = method;
+
+ //
+ // Also add the method to the type in which the operation was found.
+ //
+ if(source)
+ {
+ source[methodName] = method;
+ }
+ }
+ }
+
+ return method;
+ }
+
+ function addProxyOperation(proxyType, name, data)
+ {
+ var method = data[0] ? data[0] : name;
+
+ var op = null;
+
+ proxyType.prototype[method] = function()
+ {
+ var args = arguments;
+
+ //
+ // Parse the operation data on the first invocation of a proxy method.
+ //
+ if(op === null)
+ {
+ op = parseOperation(name, data);
+ }
+
+ var ctx = args[op.inParams.length]; // The request context is the last argument (if present).
+
+ var marshalFn = null;
+ if(op.inParams.length > 0)
+ {
+ marshalFn = function(os, params)
+ {
+ marshalParams(os, params, undefined, op.inParams, op.inParamsOpt, op.sendsClasses);
+ };
+ }
+
+ var unmarshalFn = null;
+ if(op.returns || op.outParams.length > 0)
+ {
+ unmarshalFn = function(asyncResult)
+ {
+ //
+ // The results array holds the out parameters in the following format:
+ //
+ // [retval, out1, out2, ..., asyncResult]
+ //
+ var results = [];
+
+ var is = asyncResult.__startReadParams();
+
+ var retvalInfo;
+ if(op.returns && !op.returns.tag)
+ {
+ retvalInfo = op.returns;
+ }
+ unmarshalParams(is, retvalInfo, op.outParams, op.outParamsOpt, op.returnsClasses, results, 0);
+
+ asyncResult.__endReadParams();
+
+ //
+ // When unmarshaling objects, the ObjectHelper returns a wrapper object
+ // and eventually stores the unmarshaled object into its "value" member.
+ // Here we scan the results array and replace the wrappers with the
+ // actual object references.
+ //
+ if(op.returnsClasses || op.outParamsOpt.length > 0)
+ {
+ var offset = 0; // Skip asyncResult in results.
+ if(op.returns && op.returns.isObject && results[op.returns.pos + offset] !== undefined)
+ {
+ results[op.returns.pos + offset] = results[op.returns.pos + offset].value;
+ }
+ for(var i = 0; i < op.outParams.length; ++i)
+ {
+ var p = op.outParams[i];
+ //
+ // Optional parameters may be undefined.
+ //
+ if(p.isObject && results[p.pos + offset] !== undefined)
+ {
+ results[p.pos + offset] = results[p.pos + offset].value;
+ }
+ }
+ }
+ results.push(asyncResult);
+ return results;
+ };
+ }
+
+ return Ice.ObjectPrx.__invoke(this, op.name, op.sendMode, op.format, ctx, marshalFn, unmarshalFn,
+ op.exceptions, Array.prototype.slice.call(args));
+ };
+ }
+
+ Slice.defineOperations = function(classType, proxyType, ops)
+ {
+ if(ops)
+ {
+ classType.__ops = new OpTable(ops);
+ }
+
+ classType.prototype.__dispatch = function(incomingAsync, current)
+ {
+ //
+ // Retrieve the dispatch method for this operation.
+ //
+ var method = getServantMethod(classType, current.operation);
+
+ if(method === undefined || typeof(method) !== 'function')
+ {
+ throw new Ice.OperationNotExistException(current.id, current.facet, current.operation);
+ }
+
+ return method.call(method, this, incomingAsync, current);
+ };
+
+ if(ops)
+ {
+ for(var name in ops)
+ {
+ addProxyOperation(proxyType, name, ops[name]);
+ }
+ }
+
+ //
+ // Copy proxy methods from super-interfaces.
+ //
+ if(proxyType.__implements)
+ {
+ for(var intf in proxyType.__implements)
+ {
+ var proto = proxyType.__implements[intf].prototype;
+ for(var f in proto)
+ {
+ if(typeof proto[f] == "function" && proxyType.prototype[f] === undefined)
+ {
+ proxyType.prototype[f] = proto[f];
+ }
+ }
+ }
+ }
+ };
+
+ //
+ // Define the "built-in" operations for all Ice objects.
+ //
+ Slice.defineOperations(Ice.Object, Ice.ObjectPrx,
+ {
+ "ice_ping": [, 1, 1, , , , , , ],
+ "ice_isA": [, 1, 1, , , [1], [[7]], , ],
+ "ice_id": [, 1, 1, , , [7], , , ],
+ "ice_ids": [, 1, 1, , , ["Ice.StringSeqHelper"], , , ]
+ });
+
+ global.Slice = Slice;
+ global.Ice = Ice;
+
+ /*jshint +W069 */
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/OptionalFormat.js b/js/src/Ice/OptionalFormat.js
new file mode 100644
index 00000000000..6e3f866ee66
--- /dev/null
+++ b/js/src/Ice/OptionalFormat.js
@@ -0,0 +1,19 @@
+// **********************************************************************
+//
+// 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/EnumBase");
+
+ var Ice = global.Ice || {};
+
+ Ice.OptionalFormat = Slice.defineEnum(
+ {'F1':0, 'F2':1, 'F4':2, 'F8':3, 'Size':4, 'VSize':5, 'FSize':6, 'Class':7});
+
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/OutgoingAsync.js b/js/src/Ice/OutgoingAsync.js
new file mode 100644
index 00000000000..ec72d35e436
--- /dev/null
+++ b/js/src/Ice/OutgoingAsync.js
@@ -0,0 +1,572 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_FOR_ACTIONSCRIPT_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+(function(global){
+ require("Ice/Class");
+ require("Ice/AsyncStatus");
+ require("Ice/AsyncResult");
+ require("Ice/BasicStream");
+ require("Ice/Debug");
+ require("Ice/HashMap");
+ require("Ice/LocalExceptionWrapper");
+ require("Ice/Current");
+ require("Ice/Protocol");
+ require("Ice/BuiltinSequences");
+ require("Ice/Exception");
+ require("Ice/LocalException");
+ require("Ice/Identity");
+
+ var Ice = global.Ice || {};
+
+ var AsyncStatus = Ice.AsyncStatus;
+ var AsyncResult = Ice.AsyncResult;
+ var BasicStream = Ice.BasicStream;
+ var Debug = Ice.Debug;
+ var HashMap = Ice.HashMap;
+ var LocalExceptionWrapper = Ice.LocalExceptionWrapper;
+ var OperationMode = Ice.OperationMode;
+ var Protocol = Ice.Protocol;
+ var Identity = Ice.Identity;
+
+ var OutgoingAsync = Ice.Class(AsyncResult, {
+ __init__: function(prx, operation, completed, sent)
+ {
+ //
+ // OutgoingAsync can be constructed by a sub-type's prototype, in which case the
+ // arguments are undefined.
+ //
+ if(prx !== undefined)
+ {
+ AsyncResult.call(this, prx.ice_getCommunicator(), operation, null, prx, null, completed, sent);
+ this._batch = this._proxy.ice_isBatchOneway() || this._proxy.ice_isBatchDatagram();
+
+ this._batchStarted = false;
+
+ this._timerToken = -1;
+ this._timerConnection = null;
+
+ this._handler = null;
+ this._encoding = Protocol.getCompatibleEncoding(this._proxy.__reference().getEncoding());
+ this._cnt = 0;
+ this._mode = null;
+ }
+ else
+ {
+ AsyncResult.call(this);
+ }
+ },
+ __prepare: function(op, mode, ctx)
+ {
+ this._handler = null;
+ this._cnt = 0;
+ this._mode = mode;
+
+ Protocol.checkSupportedProtocol(Protocol.getCompatibleProtocol(this._proxy.__reference().getProtocol()));
+
+ if(ctx === null)
+ {
+ ctx = OutgoingAsync._emptyContext;
+ }
+
+ if(this._batch)
+ {
+ while(true)
+ {
+ try
+ {
+ this._handler = this._proxy.__getRequestHandler();
+ this._handler.prepareBatchRequest(this._os);
+ this._batchStarted = true;
+ break;
+ }
+ catch(ex)
+ {
+ if(ex instanceof LocalExceptionWrapper)
+ {
+ this.handleExceptionWrapper(ex);
+ }
+ else if(ex instanceof Ice.LocalException)
+ {
+ this.handleException(ex, false);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ }
+ }
+ else
+ {
+ this._os.writeBlob(Protocol.requestHdr);
+ }
+
+ var ref = this._proxy.__reference();
+
+ ref.getIdentity().__write(this._os);
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ var facet = ref.getFacet();
+ if(facet === null || facet.length === 0)
+ {
+ Ice.StringSeqHelper.write(this._os, null);
+ }
+ else
+ {
+ Ice.StringSeqHelper.write(this._os, [ facet ]);
+ }
+
+ this._os.writeString(this._operation);
+
+ this._os.writeByte(mode.value);
+
+ if(ctx !== undefined)
+ {
+ if(ctx !== null && !(ctx instanceof HashMap))
+ {
+ throw new Error("illegal context value, expecting null or HashMap");
+ }
+
+ //
+ // Explicit context
+ //
+ Ice.ContextHelper.write(this._os, ctx);
+ }
+ else
+ {
+ //
+ // Implicit context
+ //
+ var implicitContext = ref.getInstance().getImplicitContext();
+ var prxContext = ref.getContext();
+
+ if(implicitContext === null)
+ {
+ Ice.ContextHelper.write(this._os, prxContext);
+ }
+ else
+ {
+ implicitContext.write(prxContext, this._os);
+ }
+ }
+ },
+ __sent: function(connection)
+ {
+ this._state |= AsyncResult.Sent;
+
+ if((this._state & AsyncResult.Done) === 0)
+ {
+ if(!this._proxy.ice_isTwoway())
+ {
+ this._state |= AsyncResult.Done | AsyncResult.OK;
+ this._os.resize(0);
+ if(this._sent)
+ {
+ this._sent.call(null, this);
+ }
+ else
+ {
+ this.succeed(this);
+ }
+ }
+ else if(connection.timeout() > 0)
+ {
+ Debug.assert(this._timerToken === -1);
+ this._timerConnection = connection;
+ var self = this;
+ this._timerToken = this._instance.timer().schedule(
+ function() { self.__runTimerTask(); }, connection.timeout());
+ }
+ }
+ },
+ __finishedEx: function(exc, sent)
+ {
+ Debug.assert((this._state & AsyncResult.Done) === 0);
+ if(this._timerConnection !== null)
+ {
+ this._instance.timer().cancel(this._timerToken);
+ this._timerConnection = null;
+ this._timerToken = -1;
+ }
+
+ try
+ {
+ var interval = this.handleException(exc, sent); // This will throw if the invocation can't be retried.
+ if(interval > 0)
+ {
+ this._instance.retryQueue().add(this, interval);
+ }
+ else
+ {
+ this.__send();
+ }
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.__exception(ex);
+ }
+ else
+ {
+ this.fail(ex, this);
+ }
+ }
+ },
+ __finishedWrapper: function(exc)
+ {
+ //
+ // The LocalExceptionWrapper exception is only called before the invocation is sent.
+ //
+
+ try
+ {
+ var interval = this.handleExceptionWrapper(exc); // This will throw if the invocation can't be retried.
+ if(interval > 0)
+ {
+ this._instance.retryQueue().add(this, interval);
+ }
+ else
+ {
+ this.__send();
+ }
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.__exception(ex);
+ }
+ else
+ {
+ this.fail(ex, this);
+ }
+ }
+ },
+ __finished: function(istr)
+ {
+ Debug.assert(this._proxy.ice_isTwoway()); // Can only be called for twoways.
+
+ var replyStatus;
+ try
+ {
+ Debug.assert(this._exception === null && (this._state & AsyncResult.Done) === 0);
+
+ if(this._timerConnection !== null)
+ {
+ Debug.assert(this._timerToken !== -1);
+ this._instance.timer().cancel(this._timerToken);
+ this._timerConnection = null;
+ this._timerToken = -1;
+ }
+
+ if(this._is === null) // _is can already be initialized if the invocation is retried
+ {
+ this._is = new BasicStream(this._instance, Protocol.currentProtocolEncoding, false);
+ }
+ this._is.swap(istr);
+ replyStatus = this._is.readByte();
+
+ switch(replyStatus)
+ {
+ case Protocol.replyOK:
+ case Protocol.replyUserException:
+ {
+ break;
+ }
+
+ case Protocol.replyObjectNotExist:
+ case Protocol.replyFacetNotExist:
+ case Protocol.replyOperationNotExist:
+ {
+ var id = new Identity();
+ id.__read(this._is);
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ var facetPath = Ice.StringSeqHelper.read(this._is);
+ var facet;
+ if(facetPath.length > 0)
+ {
+ if(facetPath.length > 1)
+ {
+ throw new Ice.MarshalException();
+ }
+ facet = facetPath[0];
+ }
+ else
+ {
+ facet = "";
+ }
+
+ var operation = this._is.readString();
+
+ var rfe = null;
+ switch(replyStatus)
+ {
+ case Protocol.replyObjectNotExist:
+ {
+ rfe = new Ice.ObjectNotExistException();
+ break;
+ }
+
+ case Protocol.replyFacetNotExist:
+ {
+ rfe = new Ice.FacetNotExistException();
+ break;
+ }
+
+ case Protocol.replyOperationNotExist:
+ {
+ rfe = new Ice.OperationNotExistException();
+ break;
+ }
+
+ default:
+ {
+ Debug.assert(false);
+ break;
+ }
+ }
+
+ rfe.id = id;
+ rfe.facet = facet;
+ rfe.operation = operation;
+ throw rfe;
+ }
+
+ case Protocol.replyUnknownException:
+ case Protocol.replyUnknownLocalException:
+ case Protocol.replyUnknownUserException:
+ {
+ var unknown = this._is.readString();
+
+ var ue = null;
+ switch(replyStatus)
+ {
+ case Protocol.replyUnknownException:
+ {
+ ue = new Ice.UnknownException();
+ break;
+ }
+
+ case Protocol.replyUnknownLocalException:
+ {
+ ue = new Ice.UnknownLocalException();
+ break;
+ }
+
+ case Protocol.replyUnknownUserException:
+ {
+ ue = new Ice.UnknownUserException();
+ break;
+ }
+
+ default:
+ {
+ Debug.assert(false);
+ break;
+ }
+ }
+
+ ue.unknown = unknown;
+ throw ue;
+ }
+
+ default:
+ {
+ throw new Ice.UnknownReplyStatusException();
+ }
+ }
+
+ this._state |= AsyncResult.Done;
+ if(replyStatus == Protocol.replyOK)
+ {
+ this._state |= AsyncResult.OK;
+ }
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ this.__finishedEx(ex, true);
+ return;
+ }
+ else
+ {
+ this.fail(ex, this);
+ return;
+ }
+ }
+
+ Debug.assert(replyStatus === Protocol.replyOK || replyStatus === Protocol.replyUserException);
+ this.__response();
+ },
+ __send: function()
+ {
+ if(this._batch)
+ {
+ Debug.assert(this._handler !== null);
+ this._handler.finishBatchRequest(this._os);
+ this.succeed(this);
+ }
+ else
+ {
+ while(true)
+ {
+ var interval = 0;
+ try
+ {
+ this._handler = this._proxy.__getRequestHandler();
+ this._handler.sendAsyncRequest(this);
+ break;
+ }
+ catch(ex)
+ {
+ if(ex instanceof LocalExceptionWrapper)
+ {
+ interval = this.handleExceptionWrapper(ex);
+ }
+ else if(ex instanceof Ice.LocalException)
+ {
+ interval = this.handleException(ex, false);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ if(interval > 0)
+ {
+ this._instance.retryQueue().add(this, interval);
+ return false;
+ }
+ }
+ }
+ },
+ __startWriteParams: function(format)
+ {
+ this._os.startWriteEncaps(this._encoding, format);
+ return this._os;
+ },
+ __endWriteParams: function()
+ {
+ this._os.endWriteEncaps();
+ },
+ __writeEmptyParams: function()
+ {
+ this._os.writeEmptyEncaps(this._encoding);
+ },
+ __writeParamEncaps: function(encaps)
+ {
+ if(encaps === null || encaps.length === 0)
+ {
+ this._os.writeEmptyEncaps(this._encoding);
+ }
+ else
+ {
+ this._os.writeEncaps(encaps);
+ }
+ },
+ __exception: function(ex)
+ {
+ AsyncResult.prototype.__exception.call(this, ex);
+
+ if(this._batchStarted)
+ {
+ Debug.assert(this._handler !== null);
+ this._handler.abortBatchRequest();
+ }
+ },
+ handleException: function(exc, sent)
+ {
+ var interval = { value: 0 };
+ try
+ {
+ //
+ // A CloseConnectionException indicates graceful server shutdown, and is therefore
+ // always repeatable without violating "at-most-once". That's because by sending a
+ // close connection message, the server guarantees that all outstanding requests
+ // can safely be repeated.
+ //
+ // An ObjectNotExistException can always be retried as well without violating
+ // "at-most-once" (see the implementation of the checkRetryAfterException method of
+ // the ProxyFactory class for the reasons why it can be useful).
+ //
+ if(!sent || exc instanceof Ice.CloseConnectionException || exc instanceof Ice.ObjectNotExistException)
+ {
+ throw exc;
+ }
+
+ //
+ // Throw the exception wrapped in a LocalExceptionWrapper, to indicate that the
+ // request cannot be resent without potentially violating the "at-most-once"
+ // principle.
+ //
+ throw new LocalExceptionWrapper(exc, false);
+ }
+ catch(ex)
+ {
+ if(ex instanceof LocalExceptionWrapper)
+ {
+ if(this._mode === OperationMode.Nonmutating || this._mode === OperationMode.Idempotent)
+ {
+ this._cnt = this._proxy.__handleExceptionWrapperRelaxed(this._handler, ex, interval, this._cnt);
+ }
+ else
+ {
+ this._proxy.__handleExceptionWrapper(this._handler, ex);
+ }
+ }
+ else if(ex instanceof Ice.LocalException)
+ {
+ this._cnt = this._proxy.__handleException(this._handler, ex, interval, this._cnt);
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ return interval.value;
+ },
+ handleExceptionWrapper: function(ex)
+ {
+ var interval = { value: 0 };
+ if(this._mode === OperationMode.Nonmutating || this._mode === OperationMode.Idempotent)
+ {
+ this._cnt = this._proxy.__handleExceptionWrapperRelaxed(this._handler, ex, interval, this._cnt);
+ }
+ else
+ {
+ this._proxy.__handleExceptionWrapper(this._handler, ex);
+ }
+ return interval.value;
+ },
+ __runTimerTask: function()
+ {
+ var connection = this._timerConnection;
+ this._timerConnection = null;
+ this._timerToken = -1;
+
+ if(connection !== null)
+ {
+ connection.exception(new Ice.TimeoutException());
+ }
+ }
+ });
+
+ OutgoingAsync._emptyContext = new HashMap();
+
+ Ice.OutgoingAsync = OutgoingAsync;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/OutgoingConnectionFactory.js b/js/src/Ice/OutgoingConnectionFactory.js
new file mode 100644
index 00000000000..6399b6ea5b4
--- /dev/null
+++ b/js/src/Ice/OutgoingConnectionFactory.js
@@ -0,0 +1,956 @@
+// **********************************************************************
+//
+// 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/ArrayUtil");
+ require("Ice/AsyncResultBase");
+ require("Ice/ConnectionI");
+ require("Ice/ConnectionReaper");
+ require("Ice/Debug");
+ require("Ice/ExUtil");
+ require("Ice/HashMap");
+ require("Ice/Promise");
+ require("Ice/EndpointTypes");
+ require("Ice/LocalException");
+ require("Ice/Exception");
+
+ var Ice = global.Ice || {};
+
+ var ArrayUtil = Ice.ArrayUtil;
+ var AsyncResultBase = Ice.AsyncResultBase;
+ var ConnectionI = Ice.ConnectionI;
+ var ConnectionReaper = Ice.ConnectionReaper;
+ var Debug = Ice.Debug;
+ var ExUtil = Ice.ExUtil;
+ var HashMap = Ice.HashMap;
+ var Promise = Ice.Promise;
+ var EndpointSelectionType = Ice.EndpointSelectionType;
+
+ var Class = Ice.Class;
+ //
+ // Only for use by Instance.
+ //
+ var OutgoingConnectionFactory = Class({
+ __init__: function(communicator, instance)
+ {
+ this._communicator = communicator;
+ this._instance = instance;
+ this._destroyed = false;
+
+ this._reaper = new ConnectionReaper();
+
+ this._connectionsByEndpoint = new ConnectionListMap(); // map<EndpointI, Array<Ice.ConnectionI>>
+ this._pending = new HashMap(); // map<EndpointI, Array<ConnectCallback>>
+ this._pending.keyComparator = HashMap.compareEquals;
+ this._pendingConnectCount = 0;
+
+ this._waitPromise = null;
+ },
+ destroy: function()
+ {
+ if(this._destroyed)
+ {
+ return;
+ }
+
+ this._connectionsByEndpoint.forEach(function(connection)
+ {
+ connection.destroy(ConnectionI.CommunicatorDestroyed);
+ });
+
+ this._destroyed = true;
+ this._communicator = null;
+ this.checkFinished();
+ },
+ waitUntilFinished: function()
+ {
+ this._waitPromise = new Promise();
+ this.checkFinished();
+ return this._waitPromise;
+ },
+ //
+ // Returns a promise, success callback receives (connection, compress)
+ //
+ create: function(endpts, hasMore, selType)
+ {
+ Debug.assert(endpts.length > 0);
+
+ //
+ // Apply the overrides.
+ //
+ var endpoints = this.applyOverrides(endpts);
+
+ //
+ // Try to find a connection to one of the given endpoints.
+ //
+ try
+ {
+ var compress = { value: false };
+ var connection = this.findConnectionByEndpoint(endpoints, compress);
+ if(connection !== null)
+ {
+ return new Promise().succeed(connection, compress.value);
+ }
+ }
+ catch(ex)
+ {
+ return new Promise().fail(ex);
+ }
+
+ var cb = new ConnectCallback(this, endpoints, hasMore, selType);
+ return cb.start();
+ },
+ setRouterInfo: function(routerInfo)
+ {
+ var self = this;
+ return Ice.Promise.try(
+ function()
+ {
+ if(self._destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+ return routerInfo.getClientEndpoints();
+ }
+ ).then(
+ function(endpoints)
+ {
+ //
+ // Search for connections to the router's client proxy
+ // endpoints, and update the object adapter for such
+ // connections, so that callbacks from the router can be
+ // received over such connections.
+ //
+ var adapter = routerInfo.getAdapter();
+ var defaultsAndOverrides = self._instance.defaultsAndOverrides();
+ for(var i = 0; i < endpoints.length; ++i)
+ {
+ var endpoint = endpoints[i];
+
+ //
+ // Modify endpoints with overrides.
+ //
+ if(defaultsAndOverrides.overrideTimeout)
+ {
+ endpoint = endpoint.changeTimeout(defaultsAndOverrides.overrideTimeoutValue);
+ }
+
+ //
+ // The Connection object does not take the compression flag of
+ // endpoints into account, but instead gets the information
+ // about whether messages should be compressed or not from
+ // other sources. In order to allow connection sharing for
+ // endpoints that differ in the value of the compression flag
+ // only, we always set the compression flag to false here in
+ // this connection factory.
+ //
+ endpoint = endpoint.changeCompress(false);
+
+ self._connectionsByEndpoint.forEach(function(connection)
+ {
+ if(connection.endpoint().equals(endpoint))
+ {
+ connection.setAdapter(adapter);
+ }
+ });
+ }
+ }
+ );
+ },
+ removeAdapter: function(adapter)
+ {
+ if(this._destroyed)
+ {
+ return;
+ }
+ this._connectionsByEndpoint.forEach(function(connection)
+ {
+ if(connection.getAdapter() === adapter)
+ {
+ connection.setAdapter(null);
+ }
+ });
+ },
+ flushAsyncBatchRequests: function()
+ {
+ var promise = new AsyncResultBase(this._communicator, "flushBatchRequests", null, null, null);
+ if(this._destroyed)
+ {
+ promise.succeed();
+ return;
+ }
+
+ Promise.all(
+ this._connectionsByEndpoint.map(
+ function(connection)
+ {
+ if(connection.isActiveOrHolding())
+ {
+ return connection.flushBatchRequests().exception(
+ function(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ // Ignore
+ }
+ else
+ {
+ throw ex;
+ }
+ });
+ }
+ })
+ ).then(
+ function()
+ {
+ promise.succeed(promise);
+ },
+ function(ex)
+ {
+ promise.fail(ex, promise);
+ }
+ );
+ return promise;
+ },
+ applyOverrides: function(endpts)
+ {
+ var defaultsAndOverrides = this._instance.defaultsAndOverrides();
+ var endpoints = [];
+ for(var i = 0; i < endpts.length; ++i)
+ {
+ var endpoint = endpts[i];
+
+ //
+ // Modify endpoints with overrides.
+ //
+ if(defaultsAndOverrides.overrideTimeout)
+ {
+ endpoints.push(endpoint.changeTimeout(defaultsAndOverrides.overrideTimeoutValue));
+ }
+ else
+ {
+ endpoints.push(endpoint);
+ }
+ }
+
+ return endpoints;
+ },
+ findConnectionByEndpoint: function(endpoints, compress)
+ {
+ if(this._destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ var defaultsAndOverrides = this._instance.defaultsAndOverrides();
+ Debug.assert(endpoints.length > 0);
+
+ for(var i = 0; i < endpoints.length; ++i)
+ {
+ var endpoint = endpoints[i];
+
+ if(this._pending.has(endpoint))
+ {
+ continue;
+ }
+
+ var connectionList = this._connectionsByEndpoint.get(endpoint);
+ if(connectionList === undefined)
+ {
+ continue;
+ }
+
+ for(var j = 0; j < connectionList.length; ++j)
+ {
+ if(connectionList[j].isActiveOrHolding()) // Don't return destroyed or un-validated connections
+ {
+ if(defaultsAndOverrides.overrideCompress)
+ {
+ compress.value = defaultsAndOverrides.overrideCompressValue;
+ }
+ else
+ {
+ compress.value = endpoint.compress();
+ }
+ return connectionList[j];
+ }
+ }
+ }
+
+ return null;
+ },
+ incPendingConnectCount: function()
+ {
+ //
+ // Keep track of the number of pending connects. The outgoing connection factory
+ // waitUntilFinished() method waits for all the pending connects to terminate before
+ // to return. This ensures that the communicator client thread pool isn't destroyed
+ // too soon and will still be available to execute the ice_exception() callbacks for
+ // the asynchronous requests waiting on a connection to be established.
+ //
+
+ if(this._destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+ ++this._pendingConnectCount;
+ },
+ decPendingConnectCount: function()
+ {
+ --this._pendingConnectCount;
+ Debug.assert(this._pendingConnectCount >= 0);
+ if(this._destroyed && this._pendingConnectCount === 0)
+ {
+ this.checkFinished();
+ }
+ },
+ getConnection: function(endpoints, cb, compress)
+ {
+ if(this._destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ //
+ // Reap closed connections
+ //
+ var cons = this._reaper.swapConnections();
+ if(cons !== null)
+ {
+ for(var i = 0; i < cons.length; ++i)
+ {
+ var c = cons[i];
+ this._connectionsByEndpoint.removeConnection(c.endpoint(), c);
+ this._connectionsByEndpoint.removeConnection(c.endpoint().changeCompress(true), c);
+ }
+ }
+
+ //
+ // Try to get the connection.
+ //
+ while(true)
+ {
+ if(this._destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ //
+ // Search for a matching connection. If we find one, we're done.
+ //
+ var connection = this.findConnectionByEndpoint(endpoints, compress);
+ if(connection !== null)
+ {
+ return connection;
+ }
+
+ if(this.addToPending(cb, endpoints))
+ {
+ //
+ // A connection is already pending.
+ //
+ return null;
+ }
+ else
+ {
+ //
+ // No connection is currently pending to one of our endpoints, so we
+ // get out of this loop and start the connection establishment to one of the
+ // given endpoints.
+ //
+ break;
+ }
+ }
+
+ //
+ // At this point, we're responsible for establishing the connection to one of
+ // the given endpoints. If it's a non-blocking connect, calling nextEndpoint
+ // will start the connection establishment. Otherwise, we return null to get
+ // the caller to establish the connection.
+ //
+ cb.nextEndpoint();
+
+ return null;
+ },
+ createConnection: function(transceiver, endpoint)
+ {
+ Debug.assert(this._pending.has(endpoint) && transceiver !== null);
+
+ //
+ // Create and add the connection to the connection map. Adding the connection to the map
+ // is necessary to support the interruption of the connection initialization and validation
+ // in case the communicator is destroyed.
+ //
+ var connection = null;
+ try
+ {
+ if(this._destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ connection = new ConnectionI(this._communicator, this._instance, this._reaper, transceiver,
+ endpoint.changeCompress(false), false, null);
+ }
+ catch(ex)
+ {
+ if(ex instanceof Ice.LocalException)
+ {
+ try
+ {
+ transceiver.close();
+ }
+ catch(exc)
+ {
+ // Ignore
+ }
+ }
+ throw ex;
+ }
+
+ this._connectionsByEndpoint.set(connection.endpoint(), connection);
+ this._connectionsByEndpoint.set(connection.endpoint().changeCompress(true), connection);
+ return connection;
+ },
+ finishGetConnection: function(endpoints, endpoint, connection, cb)
+ {
+ // cb is-a ConnectCallback
+
+ var connectionCallbacks = [];
+ if(cb !== null)
+ {
+ connectionCallbacks.push(cb);
+ }
+
+ var i;
+ var cc;
+ var callbacks = [];
+ for(i = 0; i < endpoints.length; ++i)
+ {
+ var endpt = endpoints[i];
+ var cbs = this._pending.get(endpt);
+ if(cbs !== undefined)
+ {
+ this._pending.delete(endpt);
+ for(var j = 0; j < cbs.length; ++j)
+ {
+ cc = cbs[j];
+ if(cc.hasEndpoint(endpoint))
+ {
+ if(connectionCallbacks.indexOf(cc) === -1)
+ {
+ connectionCallbacks.push(cc);
+ }
+ }
+ else
+ {
+ if(callbacks.indexOf(cc) === -1)
+ {
+ callbacks.push(cc);
+ }
+ }
+ }
+ }
+ }
+
+ for(i = 0; i < connectionCallbacks.length; ++i)
+ {
+ cc = connectionCallbacks[i];
+ cc.removeFromPending();
+ var idx = callbacks.indexOf(cc);
+ if(idx !== -1)
+ {
+ callbacks.splice(idx, 1);
+ }
+ }
+ for(i = 0; i < callbacks.length; ++i)
+ {
+ cc = callbacks[i];
+ cc.removeFromPending();
+ }
+
+ var compress;
+ var defaultsAndOverrides = this._instance.defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideCompress)
+ {
+ compress = defaultsAndOverrides.overrideCompressValue;
+ }
+ else
+ {
+ compress = endpoint.compress();
+ }
+
+ for(i = 0; i < callbacks.length; ++i)
+ {
+ cc = callbacks[i];
+ cc.getConnection();
+ }
+ for(i = 0; i < connectionCallbacks.length; ++i)
+ {
+ cc = connectionCallbacks[i];
+ cc.setConnection(connection, compress);
+ }
+
+ this.checkFinished();
+ },
+ finishGetConnectionEx: function(endpoints, ex, cb)
+ {
+ // cb is-a ConnectCallback
+
+ var failedCallbacks = [];
+ if(cb !== null)
+ {
+ failedCallbacks.push(cb);
+ }
+ var i;
+ var cc;
+ var callbacks = [];
+ for(i = 0; i < endpoints.length; ++i)
+ {
+ var endpt = endpoints[i];
+ var cbs = this._pending.get(endpt);
+ if(cbs !== undefined)
+ {
+ this._pending.delete(endpt);
+ for(var j = 0; j < cbs.length; ++j)
+ {
+ cc = cbs[j];
+ if(cc.removeEndpoints(endpoints))
+ {
+ if(failedCallbacks.indexOf(cc) === -1)
+ {
+ failedCallbacks.push(cc);
+ }
+ }
+ else
+ {
+ if(callbacks.indexOf(cc) === -1)
+ {
+ callbacks.push(cc);
+ }
+ }
+ }
+ }
+ }
+
+ for(i = 0; i < callbacks.length; ++i)
+ {
+ cc = callbacks[i];
+ Debug.assert(failedCallbacks.indexOf(cc) === -1);
+ cc.removeFromPending();
+ }
+ this.checkFinished();
+
+ for(i = 0; i < callbacks.length; ++i)
+ {
+ cc = callbacks[i];
+ cc.getConnection();
+ }
+ for(i = 0; i < failedCallbacks.length; ++i)
+ {
+ cc = failedCallbacks[i];
+ cc.setException(ex);
+ }
+ },
+ addToPending: function(cb, endpoints)
+ {
+ // cb is-a ConnectCallback
+
+ //
+ // Add the callback to each pending list.
+ //
+ var found = false;
+ var p;
+ var i;
+ if(cb !== null)
+ {
+ for(i = 0; i < endpoints.length; ++i)
+ {
+ p = endpoints[i];
+ var cbs = this._pending.get(p);
+ if(cbs !== undefined)
+ {
+ found = true;
+ if(cbs.indexOf(cb) === -1)
+ {
+ cbs.push(cb); // Add the callback to each pending endpoint.
+ }
+ }
+ }
+ }
+
+ if(found)
+ {
+ return true;
+ }
+
+ //
+ // If there's no pending connection for the given endpoints, we're
+ // responsible for its establishment. We add empty pending lists,
+ // other callbacks to the same endpoints will be queued.
+ //
+ for(i = 0; i < endpoints.length; ++i)
+ {
+ p = endpoints[i];
+ if(!this._pending.has(p))
+ {
+ this._pending.set(p, []);
+ }
+ }
+
+ return false;
+ },
+ removeFromPending: function(cb, endpoints)
+ {
+ // cb is-a ConnectCallback
+
+ for(var i = 0; i < endpoints.length; ++i)
+ {
+ var p = endpoints[i];
+ var cbs = this._pending.get(p);
+ if(cbs !== undefined)
+ {
+ var idx = cbs.indexOf(cb);
+ if(idx !== -1)
+ {
+ cbs.splice(idx, 1);
+ }
+ }
+ }
+ },
+ handleConnectionException: function(ex, hasMore)
+ {
+ var traceLevels = this._instance.traceLevels();
+ if(traceLevels.retry >= 2)
+ {
+ var s = [];
+ s.push("connection to endpoint failed");
+ if(ex instanceof Ice.CommunicatorDestroyedException)
+ {
+ s.push("\n");
+ }
+ else
+ {
+ if(hasMore)
+ {
+ s.push(", trying next endpoint\n");
+ }
+ else
+ {
+ s.push(" and no more endpoints to try\n");
+ }
+ }
+ s.push(ExUtil.toString(ex));
+ this._instance.initializationData().logger.trace(traceLevels.retryCat, s.join(""));
+ }
+ },
+ handleException: function(ex, hasMore)
+ {
+ var traceLevels = this._instance.traceLevels();
+ if(traceLevels.retry >= 2)
+ {
+ var s = [];
+ s.push("couldn't resolve endpoint host");
+ if(ex instanceof Ice.CommunicatorDestroyedException)
+ {
+ s.push("\n");
+ }
+ else
+ {
+ if(hasMore)
+ {
+ s.push(", trying next endpoint\n");
+ }
+ else
+ {
+ s.push(" and no more endpoints to try\n");
+ }
+ }
+ s.push(ExUtil.toString(ex));
+ this._instance.initializationData().logger.trace(traceLevels.retryCat, s.join(""));
+ }
+ },
+ checkFinished: function()
+ {
+ //
+ // Can't continue until the factory is destroyed and there are no pending connections.
+ //
+ if(!this._waitPromise || !this._destroyed || this._pending.size > 0 || this._pendingConnectCount > 0)
+ {
+ return;
+ }
+
+ var self = this;
+ Promise.all(
+ self._connectionsByEndpoint.map(
+ function(connection)
+ {
+ return connection.waitUntilFinished().exception(function(ex)
+ {
+ Debug.assert(false);
+ });
+ }
+ )
+ ).then(
+ function()
+ {
+ var cons = self._reaper.swapConnections();
+ if(cons !== null)
+ {
+ var arr = [];
+ for(var e = self._connectionsByEndpoint.entries; e !== null; e = e.next)
+ {
+ var connectionList = e.value;
+ for(var i = 0; i < connectionList.length; ++i)
+ {
+ if(arr.indexOf(connectionList[i]) === -1)
+ {
+ arr.push(connectionList[i]);
+ }
+ }
+ }
+ Debug.assert(cons.length === arr.length);
+ self._connectionsByEndpoint.clear();
+ }
+ else
+ {
+ Debug.assert(self._connectionsByEndpoint.size === 0);
+ }
+
+ Debug.assert(self._waitPromise !== null);
+ self._waitPromise.succeed();
+ }
+ );
+ }
+ });
+
+ Ice.OutgoingConnectionFactory = OutgoingConnectionFactory;
+ global.Ice = Ice;
+
+ //
+ // Value is a Vector<Ice.ConnectionI>
+ //
+ var ConnectionListMap = Class(HashMap, {
+ __init__: function(h)
+ {
+ HashMap.call(this, h);
+ this.keyComparator = HashMap.compareEquals;
+ },
+ set: function(key, value)
+ {
+ var list = this.get(key);
+ if(list === undefined)
+ {
+ list = [];
+ HashMap.prototype.set.call(this, key, list);
+ }
+ Debug.assert(value instanceof ConnectionI);
+ list.push(value);
+ return undefined;
+ },
+ removeConnection: function(key, conn)
+ {
+ var list = this.get(key);
+ Debug.assert(list !== null);
+ var idx = list.indexOf(conn);
+ Debug.assert(idx !== -1);
+ list.splice(idx, 1);
+ if(list.length === 0)
+ {
+ this.delete(key);
+ }
+ },
+ map: function(fn)
+ {
+ var arr = [];
+ this.forEach(function(c) { arr.push(fn(c)); });
+ return arr;
+ },
+ forEach: function(fn)
+ {
+ for(var e = this._head; e !== null; e = e._next)
+ {
+ for(var i = 0; i < e.value.length; ++i)
+ {
+ fn(e.value[i]);
+ }
+ }
+ }
+ });
+
+ var ConnectCallback = Class({
+ __init__: function(f, endpoints, more, selType)
+ {
+ this._factory = f;
+ this._endpoints = endpoints;
+ this._hasMore = more;
+ this._selType = selType;
+ this._promise = new Promise();
+ this._index = 0;
+ this._current = null;
+ },
+ //
+ // Methods from ConnectionI_StartCallback
+ //
+ connectionStartCompleted: function(connection)
+ {
+ connection.activate();
+ this._factory.finishGetConnection(this._endpoints, this._current, connection, this);
+ },
+ connectionStartFailed: function(connection, ex)
+ {
+ Debug.assert(this._current !== null);
+
+ if(ex instanceof Ice.LocalException)
+ {
+ this._factory.handleConnectionException(ex, this._hasMore || this._index < this._endpoints.length);
+ if(ex instanceof Ice.CommunicatorDestroyedException) // No need to continue.
+ {
+ this._factory.finishGetConnectionEx(this._endpoints, ex, this);
+ }
+ else if(this._index < this._endpoints.length) // Try the next endpoint.
+ {
+ this.nextEndpoint();
+ }
+ else
+ {
+ this._factory.finishGetConnectionEx(this._endpoints, ex, this);
+ }
+ }
+ else
+ {
+ this._factory.finishGetConnectionEx(this._endpoints, ex, this);
+ }
+ },
+ setConnection: function(connection, compress)
+ {
+ //
+ // Callback from the factory: the connection to one of the callback
+ // connectors has been established.
+ //
+ this._promise.succeed(connection, compress);
+ this._factory.decPendingConnectCount(); // Must be called last.
+ },
+ setException: function(ex)
+ {
+ //
+ // Callback from the factory: connection establishment failed.
+ //
+ this._promise.fail(ex);
+ this._factory.decPendingConnectCount(); // Must be called last.
+ },
+ hasEndpoint: function(endpt)
+ {
+ return this.findEndpoint(endpt) !== -1;
+ },
+ findEndpoint: function(endpt)
+ {
+ for(var index = 0; index < this._endpoints.length; ++index)
+ {
+ if(endpt.equals(this._endpoints[index]))
+ {
+ return index;
+ }
+ }
+ return -1;
+ },
+ removeEndpoints: function(endpoints)
+ {
+ for(var i = 0; i < endpoints.length; ++i)
+ {
+ var idx = this.findEndpoint(endpoints[i]);
+ if(idx !== -1)
+ {
+ this._endpoints.splice(idx, 1);
+ }
+ }
+ this._index = 0;
+ return this._endpoints.length === 0;
+ },
+ removeFromPending: function()
+ {
+ this._factory.removeFromPending(this, this._endpoints);
+ },
+ start: function()
+ {
+ try
+ {
+ //
+ // Notify the factory that there's an async connect pending. This is necessary
+ // to prevent the outgoing connection factory to be destroyed before all the
+ // pending asynchronous connects are finished.
+ //
+ this._factory.incPendingConnectCount();
+ }
+ catch(ex)
+ {
+ this._promise.fail(ex);
+ return;
+ }
+
+ this.getConnection();
+ return this._promise;
+ },
+ getConnection: function()
+ {
+ try
+ {
+ //
+ // Ask the factory to get a connection.
+ //
+ var compress = { value: false };
+ var connection = this._factory.getConnection(this._endpoints, this, compress);
+ if(connection === null)
+ {
+ //
+ // A null return value from getConnection indicates that the connection
+ // is being established and that everthing has been done to ensure that
+ // the callback will be notified when the connection establishment is
+ // done.
+ //
+ return;
+ }
+
+ this._promise.succeed(connection, compress.value);
+ this._factory.decPendingConnectCount(); // Must be called last.
+ }
+ catch(ex)
+ {
+ this._promise.fail(ex);
+ this._factory.decPendingConnectCount(); // Must be called last.
+ }
+ },
+ nextEndpoint: function()
+ {
+ var connection = null;
+ try
+ {
+ Debug.assert(this._index < this._endpoints.length);
+ this._current = this._endpoints[this._index++];
+ connection = this._factory.createConnection(this._current.connect(), this._current);
+ var self = this;
+ connection.start().then(
+ function()
+ {
+ self.connectionStartCompleted(connection);
+ },
+ function(ex)
+ {
+ self.connectionStartFailed(connection, ex);
+ });
+ }
+ catch(ex)
+ {
+ this.connectionStartFailed(connection, ex);
+ }
+ }
+ });
+
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ProcessLogger.js b/js/src/Ice/ProcessLogger.js
new file mode 100644
index 00000000000..b414d183adc
--- /dev/null
+++ b/js/src/Ice/ProcessLogger.js
@@ -0,0 +1,39 @@
+
+// **********************************************************************
+//
+// 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/Logger");
+ var Ice = global.Ice || {};
+ var Logger = Ice.Logger;
+
+ var processLogger = null;
+
+ var getProcessLogger = function()
+ {
+ if(processLogger === null)
+ {
+ //
+ // TODO: Would be nice to be able to use process name as prefix by default.
+ //
+ processLogger = new Logger("", "");
+ }
+
+ return processLogger;
+ };
+
+ var setProcessLogger = function(logger)
+ {
+ processLogger = logger;
+ };
+
+ Ice.getProcessLogger = getProcessLogger;
+ Ice.setProcessLogger = setProcessLogger;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Promise.js b/js/src/Ice/Promise.js
new file mode 100644
index 00000000000..91608d13873
--- /dev/null
+++ b/js/src/Ice/Promise.js
@@ -0,0 +1,297 @@
+// **********************************************************************
+//
+// 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");
+
+ var Ice = global.Ice || {};
+
+ //
+ // Promise State
+ //
+ var State = {Pending: 0, Success: 1, Failed: 2};
+
+ var resolveImp = function(self, listener)
+ {
+ var callback = self.__state === State.Success ? listener.onResponse : listener.onException;
+ try
+ {
+ if(typeof callback !== "function")
+ {
+ listener.promise.setState(self.__state, self._args);
+ }
+ else
+ {
+ var result = callback.apply(null, self._args);
+
+ //
+ // Callback can return a new promise.
+ //
+ if(result && typeof result.then == "function")
+ {
+ result.then(
+ function()
+ {
+ var args = arguments;
+ listener.promise.succeed.apply(listener.promise, args);
+ },
+ function()
+ {
+ var args = arguments;
+ listener.promise.fail.apply(listener.promise, args);
+ });
+ }
+ else
+ {
+ listener.promise.succeed(result);
+ }
+ }
+ }
+ catch(e)
+ {
+ listener.promise.fail.call(listener.promise, e);
+ }
+ };
+
+ var Promise = Ice.Class({
+ __init__: function()
+ {
+ this.__state = State.Pending;
+ this.__listeners = [];
+ },
+ then: function(onResponse, onException)
+ {
+ var promise = new Promise();
+ var self = this;
+ //
+ // Use setTimeout so the listeners are not resolved until the call stack is empty.
+ //
+ setTimeout(
+ function()
+ {
+ self.__listeners.push(
+ {
+ promise:promise,
+ onResponse:onResponse,
+ onException:onException
+ });
+ self.resolve();
+ }, 0);
+ return promise;
+ },
+ exception: function(onException)
+ {
+ return this.then(null, onException);
+ },
+ finally: function(cb)
+ {
+ var p = new Promise();
+ var self = this;
+
+ var finallyHandler = function(method)
+ {
+ return function()
+ {
+ var args = arguments;
+ try
+ {
+ var result = cb.apply(null, args);
+ if(result && typeof result.then == "function")
+ {
+ var handler = function(){ method.apply(p, args); };
+ result.then(handler).exception(handler);
+ }
+ else
+ {
+ method.apply(p, args);
+ }
+ }
+ catch(e)
+ {
+ method.apply(p, args);
+ }
+ };
+ };
+
+ setTimeout(
+ function(){
+ self.then(finallyHandler(p.succeed), finallyHandler(p.fail));
+ });
+ return p;
+ },
+ delay: function(ms)
+ {
+ var p = new Promise();
+
+ var self = this;
+
+ var delayHandler = function(promise, method)
+ {
+ return function()
+ {
+ var args = arguments;
+ setTimeout(
+ function()
+ {
+ method.apply(promise, args);
+ },
+ ms);
+ };
+ };
+
+ setTimeout(
+ function()
+ {
+ self.then(delayHandler(p, p.succeed),
+ delayHandler(p, p.fail));
+ });
+
+ return p;
+ },
+ resolve: function()
+ {
+ if(this.__state === State.Pending)
+ {
+ return;
+ }
+
+ var obj;
+ while((obj = this.__listeners.pop()))
+ {
+ //
+ // We use a separate function here to capture the listeners
+ // in the loop.
+ //
+ resolveImp(this, obj);
+ }
+ },
+ setState: function(state, args)
+ {
+ if(this.__state === State.Pending && state !== State.Pending)
+ {
+ this.__state = state;
+ this._args = args;
+ //
+ // Use setTimeout so the listeners are not resolved until the call stack is empty.
+ //
+ var self = this;
+ setTimeout(function(){ self.resolve(); }, 0);
+ }
+ },
+ succeed: function()
+ {
+ var args = arguments;
+ this.setState(State.Success, args);
+ return this;
+ },
+ fail: function()
+ {
+ var args = arguments;
+ this.setState(State.Failed, args);
+ return this;
+ },
+ succeeded: function()
+ {
+ return this.__state === State.Success;
+ },
+ failed: function()
+ {
+ return this.__state === State.Failed;
+ },
+ completed: function()
+ {
+ return this.__state !== State.Pending;
+ }
+ });
+
+ //
+ // Create a new promise object that is fulfilled when all the promise arguments
+ // are fulfilled or is rejected when one of the promises is rejected.
+ //
+ Promise.all = function()
+ {
+ // If only one argument is provided, check if the argument is an array
+ if(arguments.length === 1 && arguments[0] instanceof Array)
+ {
+ return Promise.all.apply(this, arguments[0]);
+ }
+
+ var promise = new Promise();
+ var promises = Array.prototype.slice.call(arguments);
+ var results = new Array(arguments.length);
+
+ var pending = promises.length;
+ if(pending === 0)
+ {
+ promise.succeed.apply(promise, results);
+ }
+ for(var i = 0; i < promises.length; ++i)
+ {
+ //
+ // Create an anonymous function to capture the loop index
+ //
+
+ /*jshint -W083 */
+ (function(j)
+ {
+ if(promises[j] && typeof promises[j].then == "function")
+ {
+ promises[j].then(
+ function()
+ {
+ results[j] = arguments;
+ pending--;
+ if(pending === 0)
+ {
+ promise.succeed.apply(promise, results);
+ }
+ },
+ function()
+ {
+ promise.fail.apply(promise, arguments);
+ });
+ }
+ else
+ {
+ results[j] = promises[j];
+ pending--;
+ if(pending === 0)
+ {
+ promise.succeed.apply(promise, results);
+ }
+ }
+ }(i));
+ /*jshint +W083 */
+ }
+ return promise;
+ };
+
+ Promise.try = function(onResponse)
+ {
+ return new Promise().succeed().then(onResponse);
+ };
+
+ Promise.delay = function(ms)
+ {
+ if(arguments.length > 1)
+ {
+ var p = new Promise();
+ var args = Array.prototype.slice.call(arguments);
+ ms = args.pop();
+ return p.succeed.apply(p, args).delay(ms);
+ }
+ else
+ {
+ return new Promise().succeed().delay(ms);
+ }
+ };
+
+ Ice.Promise = Promise;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Properties.js b/js/src/Ice/Properties.js
new file mode 100644
index 00000000000..3f63204a7fa
--- /dev/null
+++ b/js/src/Ice/Properties.js
@@ -0,0 +1,504 @@
+// **********************************************************************
+//
+// 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/StringUtil");
+ require("Ice/HashMap");
+ require("Ice/Promise");
+ require("Ice/PropertyNames");
+ require("Ice/Debug");
+ require("Ice/ProcessLogger");
+ require("Ice/ProcessLogger");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var StringUtil = Ice.StringUtil;
+ var HashMap = Ice.HashMap;
+ var Promise = Ice.Promise;
+ var PropertyNames = Ice.PropertyNames;
+ var Debug = Ice.Debug;
+ var ProcessLogger = Ice.ProcessLogger;
+ var getProcessLogger = Ice.getProcessLogger;
+ var InitializationException = Ice.InitializationException;
+
+ var ParseStateKey = 0;
+ var ParseStateValue = 1;
+ //
+ // Ice.Properties
+ //
+ var Properties = Ice.Class({
+ __init__: function(args, defaults)
+ {
+ this._properties = new HashMap();
+
+ if(defaults !== undefined && defaults !== null)
+ {
+ //
+ // NOTE: we can't just do a shallow copy of the map as the map values
+ // would otherwise be shared between the two PropertiesI object.
+ //
+ //_properties = new HashMap(pi._properties);
+ for(var e = defaults._properties.entries; e !== null; e = e.next)
+ {
+ this._properties.set(e.key, { 'value': e.value.value, 'used': false });
+ }
+ }
+
+ if(args !== undefined && args !== null)
+ {
+ var v = this.parseIceCommandLineOptions(args);
+ args.length = 0;
+ for(var i = 0; i < v.length; ++i)
+ {
+ args.push(v[i]);
+ }
+ }
+ },
+ getProperty: function(key)
+ {
+ return this.getPropertyWithDefault(key, "");
+ },
+ getPropertyWithDefault: function(key, value)
+ {
+ var pv = this._properties.get(key);
+ if(pv !== undefined)
+ {
+ pv.used = true;
+ return pv.value;
+ }
+ else
+ {
+ return value;
+ }
+ },
+ getPropertyAsInt: function(key)
+ {
+ return this.getPropertyAsIntWithDefault(key, 0);
+ },
+ getPropertyAsIntWithDefault: function(key, value)
+ {
+ var pv = this._properties.get(key);
+ if(pv !== undefined)
+ {
+ pv.used = true;
+ return parseInt(pv.value);
+ }
+ else
+ {
+ return value;
+ }
+ },
+ getPropertyAsList: function(key)
+ {
+ return this.getPropertyAsListWithDefault(key, 0);
+ },
+ getPropertyAsListWithDefault: function(key, value)
+ {
+ if(value === undefined || value === null)
+ {
+ value = [];
+ }
+
+ var pv = this._properties.get(key);
+ if(pv !== undefined)
+ {
+ pv.used = true;
+
+ var result = StringUtil.splitString(pv.value, ", \t\r\n");
+ if(result === null)
+ {
+ getProcessLogger().warning("mismatched quotes in property " + key + "'s value, returning default value");
+ return value;
+ }
+ if(result.length === 0)
+ {
+ result = value;
+ }
+ return result;
+ }
+ else
+ {
+ return value;
+ }
+ },
+ getPropertiesForPrefix: function(prefix)
+ {
+ var result = new HashMap();
+ for(var e = this._properties.entries; e !== null; e = e.next)
+ {
+ if(prefix === undefined || prefix === null || e.key.indexOf(prefix) === 0)
+ {
+ e.value.used = true;
+ result.set(e.key, e.value.value);
+ }
+ }
+ return result;
+ },
+ setProperty: function(key, value)
+ {
+ //
+ // Trim whitespace
+ //
+ if(key !== null && key !== undefined)
+ {
+ key = key.trim();
+ }
+
+ //
+ // Check if the property is legal.
+ //
+ var logger = getProcessLogger();
+ if(key === null || key === undefined || key.length === 0)
+ {
+ throw new InitializationException("Attempt to set property with empty key");
+ }
+
+ var dotPos = key.indexOf(".");
+ if(dotPos !== -1)
+ {
+ var prefix = key.substr(0, dotPos);
+ for(var i = 0; i < PropertyNames.validProps.length; ++i)
+ {
+ var pattern = PropertyNames.validProps[i][0].pattern;
+ dotPos = pattern.indexOf(".");
+ //
+ // Each top level prefix describes a non-empty namespace. Having a string without a
+ // prefix followed by a dot is an error.
+ //
+ Debug.assert(dotPos != -1);
+ var propPrefix = pattern.substring(0, dotPos - 1);
+ if(propPrefix != prefix)
+ {
+ continue;
+ }
+
+ var found = false;
+ var mismatchCase = false;
+ var otherKey;
+ for(var j = 0; j < PropertyNames.validProps[i][j].length && !found; ++j)
+ {
+ pattern = PropertyNames.validProps[i][j].pattern();
+ var pComp = new RegExp(pattern);
+ found = pComp.test(key);
+
+ if(found && PropertyNames.validProps[i][j].deprecated)
+ {
+ logger.warning("deprecated property: " + key);
+ if(PropertyNames.validProps[i][j].deprecatedBy !== null)
+ {
+ key = PropertyNames.validProps[i][j].deprecatedBy;
+ }
+ }
+
+ if(found)
+ {
+ break;
+ }
+ else
+ {
+ pComp = new RegExp(pattern.toUpperCase());
+ found = pComp.test(key.toUpperCase());
+ if(found)
+ {
+ mismatchCase = true;
+ otherKey = pattern.substr(2);
+ otherKey = otherKey.substr(0, otherKey.length -1);
+ otherKey = otherKey.replace(/\\/g, "");
+ break;
+ }
+ }
+ }
+
+ if(!found)
+ {
+ logger.warning("unknown property: " + key);
+ }
+ else if(mismatchCase)
+ {
+ logger.warning("unknown property: `" + key + "'; did you mean `" + otherKey + "'");
+ }
+ }
+ }
+
+ //
+ // Set or clear the property.
+ //
+ if(value !== undefined && value !== null && value.length > 0)
+ {
+ var pv = this._properties.get(key);
+ if(pv !== undefined)
+ {
+ pv.value = value;
+ }
+ else
+ {
+ this._properties.set(key, { 'value': value, 'used': false });
+ }
+ }
+ else
+ {
+ this._properties.delete(key);
+ }
+ },
+ getCommandLineOptions: function()
+ {
+ var result = [];
+ for(var e = this._properties.entries; e !== null; e = e.next)
+ {
+ result.push("--" + e.key + "=" + e.pv.value);
+ }
+ return result;
+ },
+ parseCommandLineOptions: function(pfx, options)
+ {
+ if(pfx.length > 0 && pfx.charAt(pfx.length - 1) != ".")
+ {
+ pfx += ".";
+ }
+ pfx = "--" + pfx;
+
+ var result = [];
+
+ var self = this;
+ options.forEach(
+ function(opt)
+ {
+ if(opt.indexOf(pfx) === 0)
+ {
+ if(opt.indexOf('=') === -1)
+ {
+ opt += "=1";
+ }
+
+ self.parseLine(opt.substring(2));
+ }
+ else
+ {
+ result.push(opt);
+ }
+ });
+ return result;
+ },
+ parseIceCommandLineOptions: function(options)
+ {
+ var args = options.slice();
+ for(var i = 0; i < PropertyNames.clPropNames.length; ++i)
+ {
+ args = this.parseCommandLineOptions(PropertyNames.clPropNames[i], args);
+ }
+ return args;
+ },
+ parse: function(data)
+ {
+ var lines = data.match(/[^\r\n]+/g);
+
+ var line;
+
+ while((line = lines.shift()))
+ {
+ this.parseLine(line);
+ }
+ },
+ parseLine: function(line)
+ {
+ var key = "";
+ var value = "";
+
+ var state = ParseStateKey;
+
+ var whitespace = "";
+ var escapedspace = "";
+ var finished = false;
+
+ for(var i = 0; i < line.length; ++i)
+ {
+ var c = line.charAt(i);
+ switch(state)
+ {
+ case ParseStateKey:
+ {
+ switch(c)
+ {
+ case '\\':
+ if(i < line.length - 1)
+ {
+ c = line.charAt(++i);
+ switch(c)
+ {
+ case '\\':
+ case '#':
+ case '=':
+ key += whitespace;
+ whitespace = "";
+ key += c;
+ break;
+
+ case ' ':
+ if(key.length !== 0)
+ {
+ whitespace += c;
+ }
+ break;
+
+ default:
+ key += whitespace;
+ whitespace = "";
+ key += '\\';
+ key += c;
+ break;
+ }
+ }
+ else
+ {
+ key += whitespace;
+ key += c;
+ }
+ break;
+
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ if(key.length !== 0)
+ {
+ whitespace += c;
+ }
+ break;
+
+ case '=':
+ whitespace = "";
+ state = ParseStateValue;
+ break;
+
+ case '#':
+ finished = true;
+ break;
+
+ default:
+ key += whitespace;
+ whitespace = "";
+ key += c;
+ break;
+ }
+ break;
+ }
+
+ case ParseStateValue:
+ {
+ switch(c)
+ {
+ case '\\':
+ if(i < line.length - 1)
+ {
+ c = line.charAt(++i);
+ switch(c)
+ {
+ case '\\':
+ case '#':
+ case '=':
+ value += value.length === 0 ? escapedspace : whitespace;
+ whitespace = "";
+ escapedspace = "";
+ value += c;
+ break;
+
+ case ' ':
+ whitespace += c;
+ escapedspace += c;
+ break;
+
+ default:
+ value += value.length === 0 ? escapedspace : whitespace;
+ whitespace = "";
+ escapedspace = "";
+ value += '\\';
+ value += c;
+ break;
+ }
+ }
+ else
+ {
+ value += value.length === 0 ? escapedspace : whitespace;
+ value += c;
+ }
+ break;
+
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ if(value.length !== 0)
+ {
+ whitespace += c;
+ }
+ break;
+
+ case '#':
+ value += escapedspace;
+ finished = true;
+ break;
+
+ default:
+ value += value.length === 0 ? escapedspace : whitespace;
+ whitespace = "";
+ escapedspace = "";
+ value += c;
+ break;
+ }
+ break;
+ }
+ }
+ if(finished)
+ {
+ break;
+ }
+ }
+ value += escapedspace;
+
+ if((state === ParseStateKey && key.length !== 0) ||
+ (state == ParseStateValue && key.length === 0))
+ {
+ getProcessLogger().warning("invalid config file entry: \"" + line + "\"");
+ return;
+ }
+ else if(key.length === 0)
+ {
+ return;
+ }
+
+ this.setProperty(key, value);
+ },
+ clone: function()
+ {
+ return new Properties(null, this);
+ },
+ getUnusedProperties: function()
+ {
+ var unused = [];
+ for(var e = this._properties.entries; e !== null; e = e.next)
+ {
+ if(!e.pv.used)
+ {
+ unused.push(e.key);
+ }
+ }
+ return unused;
+ }
+ });
+
+ Properties.createProperties = function(args, defaults)
+ {
+ return new Properties(args, defaults);
+ };
+
+ Ice.Properties = Properties;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Property.js b/js/src/Ice/Property.js
new file mode 100644
index 00000000000..3bea3d09caf
--- /dev/null
+++ b/js/src/Ice/Property.js
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+
+ var Property = function Property(pattern, deprecated, deprecatedBy)
+ {
+ this._pattern = pattern;
+ this._deprecated = deprecated;
+ this._deprecatedBy = deprecatedBy;
+ };
+
+ Object.defineProperty(Property.prototype, "pattern",{
+ get: function() { return this._pattern; }
+ });
+
+ Object.defineProperty(Property.prototype, "deprecated",{
+ get: function() { return this._deprecated; }
+ });
+
+ Object.defineProperty(Property.prototype, "deprecatedBy",{
+ get: function() { return this._deprecatedBy; }
+ });
+
+ Ice.Property = Property;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/PropertyNames.js b/js/src/Ice/PropertyNames.js
new file mode 100644
index 00000000000..5537b8c9d14
--- /dev/null
+++ b/js/src/Ice/PropertyNames.js
@@ -0,0 +1,177 @@
+// **********************************************************************
+//
+// 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.
+//
+// **********************************************************************
+
+///* jshint -W044*/
+// Generated by makeprops.py from file PropertyNames.xml, Tue Feb 4 16:00:18 2014
+
+// IMPORTANT: Do not edit this file -- any edits made here will be lost!
+
+(function(global){
+ var Ice = global.Ice || Ice;
+ require("Ice/Property");
+ var PropertyNames = {};
+ var Property = Ice.Property;
+ /* jshint -W044*/
+
+ PropertyNames.IceProps =
+ [
+ new Property("/^Ice\.ACM\.Client/", false, null),
+ new Property("/^Ice\.ACM\.Server/", false, null),
+ new Property("/^Ice\.Admin\.ACM/", false, null),
+ new Property("/^Ice\.Admin\.AdapterId/", false, null),
+ new Property("/^Ice\.Admin\.Endpoints/", false, null),
+ new Property("/^Ice\.Admin\.Locator\.EndpointSelection/", false, null),
+ new Property("/^Ice\.Admin\.Locator\.ConnectionCached/", false, null),
+ new Property("/^Ice\.Admin\.Locator\.PreferSecure/", false, null),
+ new Property("/^Ice\.Admin\.Locator\.LocatorCacheTimeout/", false, null),
+ new Property("/^Ice\.Admin\.Locator\.Locator/", false, null),
+ new Property("/^Ice\.Admin\.Locator\.Router/", false, null),
+ new Property("/^Ice\.Admin\.Locator\.CollocationOptimized/", false, null),
+ new Property("/^Ice\.Admin\.Locator/", false, null),
+ new Property("/^Ice\.Admin\.PublishedEndpoints/", false, null),
+ new Property("/^Ice\.Admin\.ReplicaGroupId/", false, null),
+ new Property("/^Ice\.Admin\.Router\.EndpointSelection/", false, null),
+ new Property("/^Ice\.Admin\.Router\.ConnectionCached/", false, null),
+ new Property("/^Ice\.Admin\.Router\.PreferSecure/", false, null),
+ new Property("/^Ice\.Admin\.Router\.LocatorCacheTimeout/", false, null),
+ new Property("/^Ice\.Admin\.Router\.Locator/", false, null),
+ new Property("/^Ice\.Admin\.Router\.Router/", false, null),
+ new Property("/^Ice\.Admin\.Router\.CollocationOptimized/", false, null),
+ new Property("/^Ice\.Admin\.Router/", false, null),
+ new Property("/^Ice\.Admin\.ProxyOptions/", false, null),
+ new Property("/^Ice\.Admin\.ThreadPool\.Size/", false, null),
+ new Property("/^Ice\.Admin\.ThreadPool\.SizeMax/", false, null),
+ new Property("/^Ice\.Admin\.ThreadPool\.SizeWarn/", false, null),
+ new Property("/^Ice\.Admin\.ThreadPool\.StackSize/", false, null),
+ new Property("/^Ice\.Admin\.ThreadPool\.Serialize/", false, null),
+ new Property("/^Ice\.Admin\.ThreadPool\.ThreadIdleTime/", false, null),
+ new Property("/^Ice\.Admin\.ThreadPool\.ThreadPriority/", false, null),
+ new Property("/^Ice\.Admin\.DelayCreation/", false, null),
+ new Property("/^Ice\.Admin\.Facets/", false, null),
+ new Property("/^Ice\.Admin\.InstanceName/", false, null),
+ new Property("/^Ice\.Admin\.ServerId/", false, null),
+ new Property("/^Ice\.BackgroundLocatorCacheUpdates/", false, null),
+ new Property("/^Ice\.BatchAutoFlush/", false, null),
+ new Property("/^Ice\.ChangeUser/", false, null),
+ new Property("/^Ice\.ClientAccessPolicyProtocol/", false, null),
+ new Property("/^Ice\.Compression\.Level/", false, null),
+ new Property("/^Ice\.Config/", false, null),
+ new Property("/^Ice\.ConsoleListener/", false, null),
+ new Property("/^Ice\.Default\.CollocationOptimized/", false, null),
+ new Property("/^Ice\.Default\.EncodingVersion/", false, null),
+ new Property("/^Ice\.Default\.EndpointSelection/", false, null),
+ new Property("/^Ice\.Default\.Host/", false, null),
+ new Property("/^Ice\.Default\.Locator\.EndpointSelection/", false, null),
+ new Property("/^Ice\.Default\.Locator\.ConnectionCached/", false, null),
+ new Property("/^Ice\.Default\.Locator\.PreferSecure/", false, null),
+ new Property("/^Ice\.Default\.Locator\.LocatorCacheTimeout/", false, null),
+ new Property("/^Ice\.Default\.Locator\.Locator/", false, null),
+ new Property("/^Ice\.Default\.Locator\.Router/", false, null),
+ new Property("/^Ice\.Default\.Locator\.CollocationOptimized/", false, null),
+ new Property("/^Ice\.Default\.Locator/", false, null),
+ new Property("/^Ice\.Default\.LocatorCacheTimeout/", false, null),
+ new Property("/^Ice\.Default\.Package/", false, null),
+ new Property("/^Ice\.Default\.PreferSecure/", false, null),
+ new Property("/^Ice\.Default\.Protocol/", false, null),
+ new Property("/^Ice\.Default\.Router\.EndpointSelection/", false, null),
+ new Property("/^Ice\.Default\.Router\.ConnectionCached/", false, null),
+ new Property("/^Ice\.Default\.Router\.PreferSecure/", false, null),
+ new Property("/^Ice\.Default\.Router\.LocatorCacheTimeout/", false, null),
+ new Property("/^Ice\.Default\.Router\.Locator/", false, null),
+ new Property("/^Ice\.Default\.Router\.Router/", false, null),
+ new Property("/^Ice\.Default\.Router\.CollocationOptimized/", false, null),
+ new Property("/^Ice\.Default\.Router/", false, null),
+ new Property("/^Ice\.Default\.SlicedFormat/", false, null),
+ new Property("/^Ice\.IPv4/", false, null),
+ new Property("/^Ice\.IPv6/", false, null),
+ new Property("/^Ice\.EventLog\.Source/", false, null),
+ new Property("/^Ice\.FactoryAssemblies/", false, null),
+ new Property("/^Ice\.GC\.Interval/", false, null),
+ new Property("/^Ice\.ImplicitContext/", false, null),
+ new Property("/^Ice\.InitPlugins/", false, null),
+ new Property("/^Ice\.LogFile/", false, null),
+ new Property("/^Ice\.MessageSizeMax/", false, null),
+ new Property("/^Ice\.MonitorConnections/", false, null),
+ new Property("/^Ice\.Nohup/", false, null),
+ new Property("/^Ice\.NullHandleAbort/", false, null),
+ new Property("/^Ice\.Override\.CloseTimeout/", false, null),
+ new Property("/^Ice\.Override\.Compress/", false, null),
+ new Property("/^Ice\.Override\.ConnectTimeout/", false, null),
+ new Property("/^Ice\.Override\.Timeout/", false, null),
+ new Property("/^Ice\.Override\.Secure/", false, null),
+ new Property("/^Ice\.Package\../", false, null),
+ new Property("/^Ice\.Plugin\../", false, null),
+ new Property("/^Ice\.PluginLoadOrder/", false, null),
+ new Property("/^Ice\.PreferIPv6Address/", false, null),
+ new Property("/^Ice\.PrintAdapterReady/", false, null),
+ new Property("/^Ice\.PrintProcessId/", false, null),
+ new Property("/^Ice\.PrintStackTraces/", false, null),
+ new Property("/^Ice\.ProgramName/", false, null),
+ new Property("/^Ice\.RetryIntervals/", false, null),
+ new Property("/^Ice\.ServerIdleTime/", false, null),
+ new Property("/^Ice\.SOCKSProxyHost/", false, null),
+ new Property("/^Ice\.SOCKSProxyPort/", false, null),
+ new Property("/^Ice\.StdErr/", false, null),
+ new Property("/^Ice\.StdOut/", false, null),
+ new Property("/^Ice\.SyslogFacility/", false, null),
+ new Property("/^Ice\.ThreadPool\.Client\.Size/", false, null),
+ new Property("/^Ice\.ThreadPool\.Client\.SizeMax/", false, null),
+ new Property("/^Ice\.ThreadPool\.Client\.SizeWarn/", false, null),
+ new Property("/^Ice\.ThreadPool\.Client\.StackSize/", false, null),
+ new Property("/^Ice\.ThreadPool\.Client\.Serialize/", false, null),
+ new Property("/^Ice\.ThreadPool\.Client\.ThreadIdleTime/", false, null),
+ new Property("/^Ice\.ThreadPool\.Client\.ThreadPriority/", false, null),
+ new Property("/^Ice\.ThreadPool\.Server\.Size/", false, null),
+ new Property("/^Ice\.ThreadPool\.Server\.SizeMax/", false, null),
+ new Property("/^Ice\.ThreadPool\.Server\.SizeWarn/", false, null),
+ new Property("/^Ice\.ThreadPool\.Server\.StackSize/", false, null),
+ new Property("/^Ice\.ThreadPool\.Server\.Serialize/", false, null),
+ new Property("/^Ice\.ThreadPool\.Server\.ThreadIdleTime/", false, null),
+ new Property("/^Ice\.ThreadPool\.Server\.ThreadPriority/", false, null),
+ new Property("/^Ice\.ThreadPriority/", false, null),
+ new Property("/^Ice\.Trace\.Admin\.Properties/", false, null),
+ new Property("/^Ice\.Trace\.GC/", false, null),
+ new Property("/^Ice\.Trace\.Locator/", false, null),
+ new Property("/^Ice\.Trace\.Network/", false, null),
+ new Property("/^Ice\.Trace\.Protocol/", false, null),
+ new Property("/^Ice\.Trace\.Retry/", false, null),
+ new Property("/^Ice\.Trace\.Slicing/", false, null),
+ new Property("/^Ice\.Trace\.ThreadPool/", false, null),
+ new Property("/^Ice\.UDP\.RcvSize/", false, null),
+ new Property("/^Ice\.UDP\.SndSize/", false, null),
+ new Property("/^Ice\.TCP\.Backlog/", false, null),
+ new Property("/^Ice\.TCP\.RcvSize/", false, null),
+ new Property("/^Ice\.TCP\.SndSize/", false, null),
+ new Property("/^Ice\.UseApplicationClassLoader/", false, null),
+ new Property("/^Ice\.UseSyslog/", false, null),
+ new Property("/^Ice\.Warn\.AMICallback/", false, null),
+ new Property("/^Ice\.Warn\.Connections/", false, null),
+ new Property("/^Ice\.Warn\.Datagrams/", false, null),
+ new Property("/^Ice\.Warn\.Dispatch/", false, null),
+ new Property("/^Ice\.Warn\.Endpoints/", false, null),
+ new Property("/^Ice\.Warn\.UnknownProperties/", false, null),
+ new Property("/^Ice\.Warn\.UnusedProperties/", false, null),
+ new Property("/^Ice\.CacheMessageBuffers/", false, null),
+ ];
+
+ /* jshint +W044*/
+
+ PropertyNames.validProps =
+ [
+ PropertyNames.IceProps,
+ ];
+
+ PropertyNames.clPropNames =
+ [
+ "Ice",
+ ];
+
+ Ice.PropertyNames = PropertyNames;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Protocol.js b/js/src/Ice/Protocol.js
new file mode 100644
index 00000000000..12d71fdcdae
--- /dev/null
+++ b/js/src/Ice/Protocol.js
@@ -0,0 +1,316 @@
+// **********************************************************************
+//
+// 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/StringUtil");
+ require("Ice/LocalException");
+ require("Ice/Version");
+ require("Ice/Buffer");
+
+ var Ice = global.Ice || {};
+
+ var StringUtil = Ice.StringUtil;
+
+ var Protocol = {};
+
+ Ice.Encoding_1_0 = new Ice.EncodingVersion(1, 0);
+ Ice.Encoding_1_1 = new Ice.EncodingVersion(1, 1);
+
+ Ice.Protocol_1_0 = new Ice.ProtocolVersion(1, 0);
+
+ //
+ // Size of the Ice protocol header
+ //
+ // Magic number (4 bytes)
+ // Protocol version major (Byte)
+ // Protocol version minor (Byte)
+ // Encoding version major (Byte)
+ // Encoding version minor (Byte)
+ // Message type (Byte)
+ // Compression status (Byte)
+ // Message size (Int)
+ //
+ Protocol.headerSize = 14;
+
+ //
+ // The magic number at the front of each message
+ //
+ //Protocol.magic = [ 0x49, 0x63, 0x65, 0x50 ]; // 'I', 'c', 'e', 'P'
+ Protocol.magic = Ice.Buffer.createNative([ 0x49, 0x63, 0x65, 0x50 ]); // 'I', 'c', 'e', 'P'
+
+ //
+ // The current Ice protocol and encoding version
+ //
+ Protocol.protocolMajor = 1;
+ Protocol.protocolMinor = 0;
+ Protocol.protocolEncodingMajor = 1;
+ Protocol.protocolEncodingMinor = 0;
+
+ Protocol.encodingMajor = 1;
+ Protocol.encodingMinor = 1;
+
+ //
+ // The Ice protocol message types
+ //
+ Protocol.requestMsg = 0;
+ Protocol.requestBatchMsg = 1;
+ Protocol.replyMsg = 2;
+ Protocol.validateConnectionMsg = 3;
+ Protocol.closeConnectionMsg = 4;
+
+ //
+ // Reply status
+ //
+ Protocol.replyOK = 0;
+ Protocol.replyUserException = 1;
+ Protocol.replyObjectNotExist = 2;
+ Protocol.replyFacetNotExist = 3;
+ Protocol.replyOperationNotExist = 4;
+ Protocol.replyUnknownLocalException = 5;
+ Protocol.replyUnknownUserException = 6;
+ Protocol.replyUnknownException = 7;
+
+ Protocol.requestHdr = Ice.Buffer.createNative([
+ Protocol.magic[0],
+ Protocol.magic[1],
+ Protocol.magic[2],
+ Protocol.magic[3],
+ Protocol.protocolMajor,
+ Protocol.protocolMinor,
+ Protocol.protocolEncodingMajor,
+ Protocol.protocolEncodingMinor,
+ Protocol.requestMsg,
+ 0, // Compression status.
+ 0, 0, 0, 0, // Message size (placeholder).
+ 0, 0, 0, 0 // Request ID (placeholder).
+ ]);
+
+ Protocol.requestBatchHdr = Ice.Buffer.createNative([
+ Protocol.magic[0],
+ Protocol.magic[1],
+ Protocol.magic[2],
+ Protocol.magic[3],
+ Protocol.protocolMajor,
+ Protocol.protocolMinor,
+ Protocol.protocolEncodingMajor,
+ Protocol.protocolEncodingMinor,
+ Protocol.requestBatchMsg,
+ 0, // Compression status.
+ 0, 0, 0, 0, // Message size (placeholder).
+ 0, 0, 0, 0 // Number of requests in batch (placeholder).
+ ]);
+
+ Protocol.replyHdr = Ice.Buffer.createNative([
+ Protocol.magic[0],
+ Protocol.magic[1],
+ Protocol.magic[2],
+ Protocol.magic[3],
+ Protocol.protocolMajor,
+ Protocol.protocolMinor,
+ Protocol.protocolEncodingMajor,
+ Protocol.protocolEncodingMinor,
+ Protocol.replyMsg,
+ 0, // Compression status.
+ 0, 0, 0, 0 // Message size (placeholder).
+ ]);
+
+ Protocol.currentProtocol = new Ice.ProtocolVersion(Protocol.protocolMajor, Protocol.protocolMinor);
+ Protocol.currentProtocolEncoding = new Ice.EncodingVersion(Protocol.protocolEncodingMajor,
+ Protocol.protocolEncodingMinor);
+
+ Protocol.currentEncoding = new Ice.EncodingVersion(Protocol.encodingMajor, Protocol.encodingMinor);
+
+ Protocol.checkSupportedProtocol = function(v)
+ {
+ if(v.major !== Protocol.currentProtocol.major || v.minor > Protocol.currentProtocol.minor)
+ {
+ throw new Ice.UnsupportedProtocolException("", v, Protocol.currentProtocol);
+ }
+ };
+
+ Protocol.checkSupportedProtocolEncoding = function(v)
+ {
+ if(v.major !== Protocol.currentProtocolEncoding.major ||
+ v.minor > Protocol.currentProtocolEncoding.minor)
+ {
+ throw new Ice.UnsupportedEncodingException("", v, Protocol.currentProtocolEncoding);
+ }
+ };
+
+ Protocol.checkSupportedEncoding = function(v)
+ {
+ if(v.major !== Protocol.currentEncoding.major || v.minor > Protocol.currentEncoding.minor)
+ {
+ throw new Ice.UnsupportedEncodingException("", v, Protocol.currentEncoding);
+ }
+ };
+
+ //
+ // Either return the given protocol if not compatible, or the greatest
+ // supported protocol otherwise.
+ //
+ Protocol.getCompatibleProtocol = function(v)
+ {
+ if(v.major !== Protocol.currentProtocol.major)
+ {
+ return v; // Unsupported protocol, return as is.
+ }
+ else if(v.minor < Protocol.currentProtocol.minor)
+ {
+ return v; // Supported protocol.
+ }
+ else
+ {
+ //
+ // Unsupported but compatible, use the currently supported
+ // protocol, that's the best we can do.
+ //
+ return Protocol.currentProtocol;
+ }
+ };
+
+ //
+ // Either return the given encoding if not compatible, or the greatest
+ // supported encoding otherwise.
+ //
+ Protocol.getCompatibleEncoding = function(v)
+ {
+ if(v.major !== Protocol.currentEncoding.major)
+ {
+ return v; // Unsupported encoding, return as is.
+ }
+ else if(v.minor < Protocol.currentEncoding.minor)
+ {
+ return v; // Supported encoding.
+ }
+ else
+ {
+ //
+ // Unsupported but compatible, use the currently supported
+ // encoding, that's the best we can do.
+ //
+ return Protocol.currentEncoding;
+ }
+ };
+
+ Protocol.isSupported = function(version, supported)
+ {
+ return version.major === supported.major && version.minor <= supported.minor;
+ };
+
+ /**
+ * Converts a string to a protocol version.
+ *
+ * @param version The string to convert.
+ *
+ * @return The converted protocol version.
+ **/
+ Ice.stringToProtocolVersion = function(version)
+ {
+ return new Ice.ProtocolVersion(stringToMajor(version), stringToMinor(version));
+ };
+
+ /**
+ * Converts a string to an encoding version.
+ *
+ * @param version The string to convert.
+ *
+ * @return The converted object identity.
+ **/
+ Ice.stringToEncodingVersion = function(version)
+ {
+ return new Ice.EncodingVersion(stringToMajor(version), stringToMinor(version));
+ };
+
+ /**
+ * Converts a protocol version to a string.
+ *
+ * @param v The protocol version to convert.
+ *
+ * @return The converted string.
+ **/
+ Ice.protocolVersionToString = function(v)
+ {
+ return majorMinorToString(v.major, v.minor);
+ };
+
+ /**
+ * Converts an encoding version to a string.
+ *
+ * @param v The encoding version to convert.
+ *
+ * @return The converted string.
+ **/
+ Ice.encodingVersionToString = function(v)
+ {
+ return majorMinorToString(v.major, v.minor);
+ };
+
+ Ice.Protocol = Protocol;
+ global.Ice = Ice;
+
+ function stringToMajor(str)
+ {
+ var pos = str.indexOf('.');
+ if(pos === -1)
+ {
+ throw new Ice.VersionParseException("malformed version value `" + str + "'");
+ }
+
+ var majStr = str.substring(0, pos);
+ var majVersion;
+ try
+ {
+ majVersion = StringUtil.toInt(majStr);
+ }
+ catch(ex)
+ {
+ throw new Ice.VersionParseException("invalid version value `" + str + "'");
+ }
+
+ if(majVersion < 1 || majVersion > 255)
+ {
+ throw new Ice.VersionParseException("range error in version `" + str + "'");
+ }
+
+ return majVersion;
+ }
+
+ function stringToMinor(str)
+ {
+ var pos = str.indexOf('.');
+ if(pos === -1)
+ {
+ throw new Ice.VersionParseException("malformed version value `" + str + "'");
+ }
+
+ var minStr = str.substring(pos + 1);
+ var minVersion;
+ try
+ {
+ minVersion = StringUtil.toInt(minStr);
+ }
+ catch(ex)
+ {
+ throw new Ice.VersionParseException("invalid version value `" + str + "'");
+ }
+
+ if(minVersion < 0 || minVersion > 255)
+ {
+ throw new Ice.VersionParseException("range error in version `" + str + "'");
+ }
+
+ return minVersion;
+ }
+
+ function majorMinorToString(major, minor)
+ {
+ return major + "." + minor;
+ }
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ProxyBatchOutgoingAsync.js b/js/src/Ice/ProxyBatchOutgoingAsync.js
new file mode 100644
index 00000000000..372ee9dcc3e
--- /dev/null
+++ b/js/src/Ice/ProxyBatchOutgoingAsync.js
@@ -0,0 +1,54 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_FOR_ACTIONSCRIPT_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+(function(global){
+ require("Ice/Class");
+ require("Ice/AsyncResult");
+ require("Ice/AsyncStatus");
+ require("Ice/BatchOutgoingAsync");
+ require("Ice/Protocol");
+
+ var Ice = global.Ice || {};
+
+ var AsyncResult = Ice.AsyncResult;
+ var AsyncStatus = Ice.AsyncStatus;
+ var BatchOutgoingAsync = Ice.BatchOutgoingAsync;
+ var Protocol = Ice.Protocol;
+
+ var ProxyBatchOutgoingAsync = Ice.Class(BatchOutgoingAsync, {
+ __init__: function(prx, operation)
+ {
+ BatchOutgoingAsync.call(this, prx.ice_getCommunicator(), operation);
+ this._proxy = prx;
+ },
+ __send: function()
+ {
+ Protocol.checkSupportedProtocol(this._proxy.__reference().getProtocol());
+
+ //
+ // We don't automatically retry if ice_flushBatchRequests fails. Otherwise, if some batch
+ // requests were queued with the connection, they would be lost without being noticed.
+ //
+ var handler = null;
+ var cnt = -1; // Don't retry.
+ try
+ {
+ handler = this._proxy.__getRequestHandler();
+ handler.flushAsyncBatchRequests(this);
+ }
+ catch(__ex)
+ {
+ cnt = this._proxy.__handleException(handler, __ex, 0, cnt);
+ }
+ }
+ });
+
+ Ice.ProxyBatchOutgoingAsync = ProxyBatchOutgoingAsync;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ProxyFactory.js b/js/src/Ice/ProxyFactory.js
new file mode 100644
index 00000000000..5c62625a772
--- /dev/null
+++ b/js/src/Ice/ProxyFactory.js
@@ -0,0 +1,291 @@
+// **********************************************************************
+//
+// 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/Debug");
+ require("Ice/ExUtil");
+ require("Ice/HashMap");
+ require("Ice/ObjectPrx");
+ require("Ice/StringUtil");
+ require("Ice/Identity");
+ require("Ice/Reference");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var Debug = Ice.Debug;
+ var ExUtil = Ice.ExUtil;
+ var HashMap = Ice.HashMap;
+ var ObjectPrx = Ice.ObjectPrx;
+ var StringUtil = Ice.StringUtil;
+ var Identity = Ice.Identity;
+
+ //
+ // Only for use by Instance.
+ //
+ var ProxyFactory = Ice.Class({
+ __init__: function(instance)
+ {
+ this._instance = instance;
+
+ var arr = this._instance.initializationData().properties.getPropertyAsList("Ice.RetryIntervals");
+
+ if(arr.length > 0)
+ {
+ this._retryIntervals = [];
+
+ for(var i = 0; i < arr.length; i++)
+ {
+ var v;
+
+ try
+ {
+ v = StringUtil.toInt(arr[i]);
+ }
+ catch(ex)
+ {
+ v = 0;
+ }
+
+ //
+ // If -1 is the first value, no retry and wait intervals.
+ //
+ if(i === 0 && v === -1)
+ {
+ this._retryIntervals = [ 0 ];
+ break;
+ }
+
+ this._retryIntervals[i] = v > 0 ? v : 0;
+ }
+ }
+ else
+ {
+ this._retryIntervals = [ 0 ];
+ }
+ },
+ stringToProxy: function(str)
+ {
+ var ref = this._instance.referenceFactory().createFromString(str, null);
+ return this.referenceToProxy(ref);
+ },
+ proxyToString: function(proxy)
+ {
+ if(proxy !== null)
+ {
+ return proxy.__reference().toString();
+ }
+ else
+ {
+ return "";
+ }
+ },
+ propertyToProxy: function(prefix)
+ {
+ var proxy = this._instance.initializationData().properties.getProperty(prefix);
+ var ref = this._instance.referenceFactory().createFromString(proxy, prefix);
+ return this.referenceToProxy(ref);
+ },
+ proxyToProperty: function(proxy, prefix)
+ {
+ if(proxy !== null)
+ {
+ return proxy.__reference().toProperty(prefix);
+ }
+ else
+ {
+ return new HashMap();
+ }
+ },
+ streamToProxy: function(s, type)
+ {
+ var ident = new Identity();
+ ident.__read(s);
+
+ var ref = this._instance.referenceFactory().createFromStream(ident, s);
+ return this.referenceToProxy(ref, type);
+ },
+ referenceToProxy: function(ref, type)
+ {
+ if(ref !== null)
+ {
+ var proxy = type ? new type() : new ObjectPrx();
+ proxy.__setup(ref);
+ return proxy;
+ }
+ else
+ {
+ return null;
+ }
+ },
+ proxyToStream: function(proxy, s)
+ {
+ if(proxy !== null)
+ {
+ var ref = proxy.__reference();
+ ref.getIdentity().__write(s);
+ ref.streamWrite(s);
+ }
+ else
+ {
+ var ident = new Identity("", "");
+ ident.__write(s);
+ }
+ },
+ checkRetryAfterException: function(ex, ref, sleepInterval, cnt)
+ {
+ var traceLevels = this._instance.traceLevels();
+ var logger = this._instance.initializationData().logger;
+
+ //
+ // We don't retry batch requests because the exception might have caused
+ // the all the requests batched with the connection to be aborted and we
+ // want the application to be notified.
+ //
+ if(ref.getMode() === Ice.Reference.ModeBatchOneway || ref.getMode() === Ice.Reference.ModeBatchDatagram)
+ {
+ throw ex;
+ }
+
+ if(ex instanceof Ice.ObjectNotExistException)
+ {
+ var one = ex;
+
+ if(ref.getRouterInfo() !== null && one.operation === "ice_add_proxy")
+ {
+ //
+ // If we have a router, an ObjectNotExistException with an
+ // operation name "ice_add_proxy" indicates to the client
+ // that the router isn't aware of the proxy (for example,
+ // because it was evicted by the router). In this case, we
+ // must *always* retry, so that the missing proxy is added
+ // to the router.
+ //
+
+ ref.getRouterInfo().clearCache(ref);
+
+ if(traceLevels.retry >= 1)
+ {
+ logger.trace(traceLevels.retryCat, "retrying operation call to add proxy to router\n" +
+ ExUtil.toString(ex));
+ }
+
+ if(sleepInterval !== null)
+ {
+ sleepInterval.value = 0;
+ }
+ return cnt; // We must always retry, so we don't look at the retry count.
+ }
+ else if(ref.isIndirect())
+ {
+ //
+ // We retry ObjectNotExistException if the reference is
+ // indirect.
+ //
+
+ if(ref.isWellKnown())
+ {
+ var li = ref.getLocatorInfo();
+ if(li !== null)
+ {
+ li.clearCache(ref);
+ }
+ }
+ }
+ else
+ {
+ //
+ // For all other cases, we don't retry ObjectNotExistException.
+ //
+ throw ex;
+ }
+ }
+ else if(ex instanceof Ice.RequestFailedException)
+ {
+ //
+ // For all other cases, we don't retry ObjectNotExistException
+ //
+ throw ex;
+ }
+
+ //
+ // There is no point in retrying an operation that resulted in a
+ // MarshalException. This must have been raised locally (because
+ // if it happened in a server it would result in an
+ // UnknownLocalException instead), which means there was a problem
+ // in this process that will not change if we try again.
+ //
+ // The most likely cause for a MarshalException is exceeding the
+ // maximum message size, which is represented by the the subclass
+ // MemoryLimitException. For example, a client can attempt to send
+ // a message that exceeds the maximum memory size, or accumulate
+ // enough batch requests without flushing that the maximum size is
+ // reached.
+ //
+ // This latter case is especially problematic, because if we were
+ // to retry a batch request after a MarshalException, we would in
+ // fact silently discard the accumulated requests and allow new
+ // batch requests to accumulate. If the subsequent batched
+ // requests do not exceed the maximum message size, it appears to
+ // the client that all of the batched requests were accepted, when
+ // in reality only the last few are actually sent.
+ //
+ if(ex instanceof Ice.MarshalException)
+ {
+ throw ex;
+ }
+
+ ++cnt;
+ Debug.assert(cnt > 0);
+
+ var interval;
+ if(cnt === (this._retryIntervals.length + 1) && ex instanceof Ice.CloseConnectionException)
+ {
+ //
+ // A close connection exception is always retried at least once, even if the retry
+ // limit is reached.
+ //
+ interval = 0;
+ }
+ else if(cnt > this._retryIntervals.length)
+ {
+ if(traceLevels.retry >= 1)
+ {
+ logger.trace(traceLevels.retryCat, "cannot retry operation call because retry limit has been exceeded\n" +
+ ExUtil.toString(ex));
+ }
+ throw ex;
+ }
+ else
+ {
+ interval = this._retryIntervals[cnt - 1];
+ }
+
+ if(traceLevels.retry >= 1)
+ {
+ var msg = "retrying operation call";
+ if(interval > 0)
+ {
+ msg += " in " + interval + "ms";
+ }
+ msg += " because of exception\n" + ExUtil.toString(ex);
+ logger.trace(traceLevels.retryCat, msg);
+ }
+
+ Debug.assert(sleepInterval !== null);
+ sleepInterval.value = interval;
+
+ return cnt;
+ }
+ });
+
+ Ice.ProxyFactory = ProxyFactory;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Reference.js b/js/src/Ice/Reference.js
new file mode 100644
index 00000000000..54f0927a49d
--- /dev/null
+++ b/js/src/Ice/Reference.js
@@ -0,0 +1,2345 @@
+// **********************************************************************
+//
+// 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/ArrayUtil");
+ require("Ice/Debug");
+ require("Ice/HashMap");
+ require("Ice/HashUtil");
+ require("Ice/ExUtil");
+ require("Ice/OpaqueEndpointI");
+ require("Ice/Promise");
+ require("Ice/Protocol");
+ require("Ice/ReferenceMode");
+ require("Ice/StringUtil");
+ require("Ice/BuiltinSequences");
+ require("Ice/EndpointTypes");
+ require("Ice/Identity");
+ require("Ice/Router");
+ require("Ice/Locator");
+ require("Ice/LocalException");
+ require("Ice/Version");
+ require("Ice/PropertyNames");
+
+ var Ice = global.Ice || {};
+
+ var ArrayUtil = Ice.ArrayUtil;
+ var Debug = Ice.Debug;
+ var HashMap = Ice.HashMap;
+ var HashUtil = Ice.HashUtil;
+ var ExUtil = Ice.ExUtil;
+ var OpaqueEndpointI = Ice.OpaqueEndpointI;
+ var Promise = Ice.Promise;
+ var Protocol = Ice.Protocol;
+ var RefMode = Ice.ReferenceMode;
+ var StringUtil = Ice.StringUtil;
+ var StringSeqHelper = Ice.StringSeqHelper;
+ var EndpointSelectionType = Ice.EndpointSelectionType;
+ var Identity = Ice.Identity;
+ var RouterPrx = Ice.RouterPrx;
+ var LocatorPrx = Ice.LocatorPrx;
+ var PropertyNames = Ice.PropertyNames;
+
+ var Class = Ice.Class;
+
+ var suffixes =
+ [
+ "EndpointSelection",
+ "ConnectionCached",
+ "PreferSecure",
+ "EncodingVersion",
+ "LocatorCacheTimeout",
+ "Locator",
+ "Router",
+ "CollocationOptimized"
+ ];
+
+ //
+ // Only for use by Instance
+ //
+ var ReferenceFactory = Class({
+ __init__: function(instance, communicator)
+ {
+ this._instance = instance;
+ this._communicator = communicator;
+ this._defaultRouter = null;
+ this._defaultLocator = null;
+ },
+ create: function(ident, facet, tmpl, endpoints)
+ {
+ if(ident.name.length === 0 && ident.category.length === 0)
+ {
+ return null;
+ }
+
+ return this.createImpl(ident, facet, tmpl.getMode(), tmpl.getSecure(), tmpl.getProtocol(), tmpl.getEncoding(),
+ endpoints, null, null);
+ },
+ createWithAdapterId: function(ident, facet, tmpl, adapterId)
+ {
+ if(ident.name.length === 0 && ident.category.length === 0)
+ {
+ return null;
+ }
+
+ return this.createImpl(ident, facet, tmpl.getMode(), tmpl.getSecure(), tmpl.getProtocol(), tmpl.getEncoding(),
+ null, adapterId, null);
+ },
+ createFixed: function(ident, fixedConnection)
+ {
+ if(ident.name.length === 0 && ident.category.length === 0)
+ {
+ return null;
+ }
+
+ //
+ // Create new reference
+ //
+ var ref = new FixedReference(
+ this._instance,
+ this._communicator,
+ ident,
+ "", // Facet
+ fixedConnection.endpoint().datagram() ? RefMode.ModeDatagram : RefMode.ModeTwoway,
+ fixedConnection.endpoint().secure(),
+ this._instance.defaultsAndOverrides().defaultEncoding,
+ fixedConnection);
+ return ref;
+ },
+ copy: function(r)
+ {
+ var ident = r.getIdentity();
+ if(ident.name.length === 0 && ident.category.length === 0)
+ {
+ return null;
+ }
+ return r.clone();
+ },
+ createFromString: function(s, propertyPrefix)
+ {
+ if(s === undefined || s === null || s.length === 0)
+ {
+ return null;
+ }
+
+ var delim = " \t\n\r";
+
+ var beg;
+ var end = 0;
+
+ beg = StringUtil.findFirstNotOf(s, delim, end);
+ if(beg == -1)
+ {
+ throw new Ice.ProxyParseException("no non-whitespace characters found in `" + s + "'");
+ }
+
+ //
+ // Extract the identity, which may be enclosed in single
+ // or double quotation marks.
+ //
+ var idstr = null;
+ end = StringUtil.checkQuote(s, beg);
+ if(end === -1)
+ {
+ throw new Ice.ProxyParseException("mismatched quotes around identity in `" + s + "'");
+ }
+ else if(end === 0)
+ {
+ end = StringUtil.findFirstOf(s, delim + ":@", beg);
+ if(end === -1)
+ {
+ end = s.length;
+ }
+ idstr = s.substring(beg, end);
+ }
+ else
+ {
+ beg++; // Skip leading quote
+ idstr = s.substring(beg, end);
+ end++; // Skip trailing quote
+ }
+
+ if(beg === end)
+ {
+ throw new Ice.ProxyParseException("no identity in `" + s + "'");
+ }
+
+ //
+ // Parsing the identity may raise IdentityParseException.
+ //
+ var ident = this._instance.stringToIdentity(idstr);
+
+ if(ident.name.length === 0)
+ {
+ //
+ // An identity with an empty name and a non-empty
+ // category is illegal.
+ //
+ if(ident.category.length > 0)
+ {
+ throw new Ice.IllegalIdentityException(ident);
+ }
+ //
+ // Treat a stringified proxy containing two double
+ // quotes ("") the same as an empty string, i.e.,
+ // a null proxy, but only if nothing follows the
+ // quotes.
+ //
+ else if(StringUtil.findFirstNotOf(s, delim, end) != -1)
+ {
+ throw new Ice.ProxyParseException("invalid characters after identity in `" + s + "'");
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ var facet = "";
+ var mode = RefMode.ModeTwoway;
+ var secure = false;
+ var encoding = this._instance.defaultsAndOverrides().defaultEncoding;
+ var protocol = Ice.Protocol_1_0;
+ var adapter = "";
+
+ while(true)
+ {
+ beg = StringUtil.findFirstNotOf(s, delim, end);
+ if(beg === -1)
+ {
+ break;
+ }
+
+ if(s.charAt(beg) == ':' || s.charAt(beg) == '@')
+ {
+ break;
+ }
+
+ end = StringUtil.findFirstOf(s, delim + ":@", beg);
+ if(end == -1)
+ {
+ end = s.length;
+ }
+
+ if(beg == end)
+ {
+ break;
+ }
+
+ var option = s.substring(beg, end);
+ if(option.length != 2 || option.charAt(0) != '-')
+ {
+ throw new Ice.ProxyParseException("expected a proxy option but found `" + option + "' in `" + s + "'");
+ }
+
+ //
+ // Check for the presence of an option argument. The
+ // argument may be enclosed in single or double
+ // quotation marks.
+ //
+ var argument = null;
+ var argumentBeg = StringUtil.findFirstNotOf(s, delim, end);
+ if(argumentBeg != -1)
+ {
+ var ch = s.charAt(argumentBeg);
+ if(ch != "@" && ch != ":" && ch != "-")
+ {
+ beg = argumentBeg;
+ end = StringUtil.checkQuote(s, beg);
+ if(end == -1)
+ {
+ throw new Ice.ProxyParseException("mismatched quotes around value for " + option +
+ " option in `" + s + "'");
+ }
+ else if(end === 0)
+ {
+ end = StringUtil.findFirstOf(s, delim + ":@", beg);
+ if(end === -1)
+ {
+ end = s.length;
+ }
+ argument = s.substring(beg, end);
+ }
+ else
+ {
+ beg++; // Skip leading quote
+ argument = s.substring(beg, end);
+ end++; // Skip trailing quote
+ }
+ }
+ }
+
+ //
+ // If any new options are added here,
+ // IceInternal::Reference::toString() and its derived classes must be updated as well.
+ //
+ switch(option.charAt(1))
+ {
+ case 'f':
+ {
+ if(argument === null)
+ {
+ throw new Ice.ProxyParseException("no argument provided for -f option in `" + s + "'");
+ }
+
+ try
+ {
+ facet = StringUtil.unescapeString(argument, 0, argument.length);
+ }
+ catch(ex)
+ {
+ throw new Ice.ProxyParseException("invalid facet in `" + s + "': " + ex.message);
+ }
+
+ break;
+ }
+
+ case 't':
+ {
+ if(argument !== null)
+ {
+ throw new Ice.ProxyParseException("unexpected argument `" + argument +
+ "' provided for -t option in `" + s + "'");
+ }
+ mode = RefMode.ModeTwoway;
+ break;
+ }
+
+ case 'o':
+ {
+ if(argument !== null)
+ {
+ throw new Ice.ProxyParseException("unexpected argument `" + argument +
+ "' provided for -o option in `" + s + "'");
+ }
+ mode = RefMode.ModeOneway;
+ break;
+ }
+
+ case 'O':
+ {
+ if(argument !== null)
+ {
+ throw new Ice.ProxyParseException("unexpected argument `" + argument +
+ "' provided for -O option in `" + s + "'");
+ }
+ mode = RefMode.ModeBatchOneway;
+ break;
+ }
+
+ case 'd':
+ {
+ if(argument !== null)
+ {
+ throw new Ice.ProxyParseException("unexpected argument `" + argument +
+ "' provided for -d option in `" + s + "'");
+ }
+ mode = RefMode.ModeDatagram;
+ break;
+ }
+
+ case 'D':
+ {
+ if(argument !== null)
+ {
+ throw new Ice.ProxyParseException("unexpected argument `" + argument +
+ "' provided for -D option in `" + s + "'");
+ }
+ mode = RefMode.ModeBatchDatagram;
+ break;
+ }
+
+ case 's':
+ {
+ if(argument !== null)
+ {
+ throw new Ice.ProxyParseException("unexpected argument `" + argument +
+ "' provided for -s option in `" + s + "'");
+ }
+ secure = true;
+ break;
+ }
+
+ case 'e':
+ {
+ if(argument === null)
+ {
+ throw new Ice.ProxyParseException("no argument provided for -e option in `" + s + "'");
+ }
+
+ try
+ {
+ encoding = Ice.stringToEncodingVersion(argument);
+ }
+ catch(e) // VersionParseException
+ {
+ throw new Ice.ProxyParseException("invalid encoding version `" + argument + "' in `" + s +
+ "':\n" + e.str);
+ }
+ break;
+ }
+
+ case 'p':
+ {
+ if(argument === null)
+ {
+ throw new Ice.ProxyParseException("no argument provided for -p option in `" + s + "'");
+ }
+
+ try
+ {
+ protocol = Ice.stringToProtocolVersion(argument);
+ }
+ catch(e) // VersionParseException
+ {
+ throw new Ice.ProxyParseException("invalid protocol version `" + argument + "' in `" + s +
+ "':\n" + e.str);
+ }
+ break;
+ }
+
+ default:
+ {
+ throw new Ice.ProxyParseException("unknown option `" + option + "' in `" + s + "'");
+ }
+ }
+ }
+
+ if(beg === -1)
+ {
+ return this.createImpl(ident, facet, mode, secure, protocol, encoding, null, null, propertyPrefix);
+ }
+
+ var endpoints = [];
+
+ if(s.charAt(beg) == ':')
+ {
+ var unknownEndpoints = [];
+ end = beg;
+
+ while(end < s.length && s.charAt(end) == ':')
+ {
+ beg = end + 1;
+
+ end = beg;
+ while(true)
+ {
+ end = s.indexOf(':', end);
+ if(end == -1)
+ {
+ end = s.length;
+ break;
+ }
+ else
+ {
+ var quoted = false;
+ var quote = beg;
+ while(true)
+ {
+ quote = s.indexOf("\"", quote);
+ if(quote == -1 || end < quote)
+ {
+ break;
+ }
+ else
+ {
+ quote = s.indexOf('\"', ++quote);
+ if(quote == -1)
+ {
+ break;
+ }
+ else if(end < quote)
+ {
+ quoted = true;
+ break;
+ }
+ ++quote;
+ }
+ }
+ if(!quoted)
+ {
+ break;
+ }
+ ++end;
+ }
+ }
+
+ var es = s.substring(beg, end);
+ var endp = this._instance.endpointFactoryManager().create(es, false);
+ if(endp !== null)
+ {
+ endpoints.push(endp);
+ }
+ else
+ {
+ unknownEndpoints.push(es);
+ }
+ }
+ if(endpoints.length === 0)
+ {
+ Debug.assert(unknownEndpoints.length > 0);
+ throw new Ice.EndpointParseException("invalid endpoint `" + unknownEndpoints[0] + "' in `" + s + "'");
+ }
+ else if(unknownEndpoints.length !== 0 &&
+ this._instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Endpoints", 1) > 0)
+ {
+ var msg = [];
+ msg.push("Proxy contains unknown endpoints:");
+ for(var i = 0; i < unknownEndpoints.length; ++i)
+ {
+ msg.push(" `");
+ msg.push(unknownEndpoints[i]);
+ msg.push("'");
+ }
+ this._instance.initializationData().logger.warning(msg.join(""));
+ }
+
+ return this.createImpl(ident, facet, mode, secure, protocol, encoding, endpoints, null, propertyPrefix);
+ }
+ else if(s.charAt(beg) == '@')
+ {
+ beg = StringUtil.findFirstNotOf(s, delim, beg + 1);
+ if(beg == -1)
+ {
+ throw new Ice.ProxyParseException("missing adapter id in `" + s + "'");
+ }
+
+ var adapterstr = null;
+ end = StringUtil.checkQuote(s, beg);
+ if(end === -1)
+ {
+ throw new Ice.ProxyParseException("mismatched quotes around adapter id in `" + s + "'");
+ }
+ else if(end === 0)
+ {
+ end = StringUtil.findFirstOf(s, delim, beg);
+ if(end === -1)
+ {
+ end = s.length;
+ }
+ adapterstr = s.substring(beg, end);
+ }
+ else
+ {
+ beg++; // Skip leading quote
+ adapterstr = s.substring(beg, end);
+ end++; // Skip trailing quote
+ }
+
+ if(end !== s.length && StringUtil.findFirstNotOf(s, delim, end) !== -1)
+ {
+ throw new Ice.ProxyParseException("invalid trailing characters after `" + s.substring(0, end + 1) +
+ "' in `" + s + "'");
+ }
+
+ try
+ {
+ adapter = StringUtil.unescapeString(adapterstr, 0, adapterstr.length);
+ }
+ catch(ex)
+ {
+ throw new Ice.ProxyParseException("invalid adapter id in `" + s + "': " + ex.message);
+ }
+ if(adapter.length === 0)
+ {
+ throw new Ice.ProxyParseException("empty adapter id in `" + s + "'");
+ }
+ return this.createImpl(ident, facet, mode, secure, protocol, encoding, null, adapter, propertyPrefix);
+ }
+
+ throw new Ice.ProxyParseException("malformed proxy `" + s + "'");
+ },
+ createFromStream: function(ident, s)
+ {
+ //
+ // Don't read the identity here. Operations calling this
+ // constructor read the identity, and pass it as a parameter.
+ //
+
+ if(ident.name.length === 0 && ident.category.length === 0)
+ {
+ return null;
+ }
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ var facetPath = StringSeqHelper.read(s); // String[]
+ var facet;
+ if(facetPath.length > 0)
+ {
+ if(facetPath.length > 1)
+ {
+ throw new Ice.ProxyUnmarshalException();
+ }
+ facet = facetPath[0];
+ }
+ else
+ {
+ facet = "";
+ }
+
+ var mode = s.readByte();
+ if(mode < 0 || mode > RefMode.ModeLast)
+ {
+ throw new Ice.ProxyUnmarshalException();
+ }
+
+ var secure = s.readBool();
+
+ var protocol = null;
+ var encoding = null;
+ if(!s.getReadEncoding().equals(Ice.Encoding_1_0))
+ {
+ protocol = new Ice.ProtocolVersion();
+ protocol.__read(s);
+ encoding = new Ice.EncodingVersion();
+ encoding.__read(s);
+ }
+ else
+ {
+ protocol = Ice.Protocol_1_0;
+ encoding = Ice.Encoding_1_0;
+ }
+
+ var endpoints = null; // EndpointI[]
+ var adapterId = null;
+
+ var sz = s.readSize();
+ if(sz > 0)
+ {
+ endpoints = [];
+ for(var i = 0; i < sz; i++)
+ {
+ endpoints[i] = this._instance.endpointFactoryManager().read(s);
+ }
+ }
+ else
+ {
+ adapterId = s.readString();
+ }
+
+ return this.createImpl(ident, facet, mode, secure, protocol, encoding, endpoints, adapterId, null);
+ },
+ setDefaultRouter: function(defaultRouter)
+ {
+ if(this._defaultRouter === null ? defaultRouter === null : this._defaultRouter.equals(defaultRouter))
+ {
+ return this;
+ }
+
+ var factory = new ReferenceFactory(this._instance, this._communicator);
+ factory._defaultLocator = this._defaultLocator;
+ factory._defaultRouter = defaultRouter;
+ return factory;
+ },
+ getDefaultRouter: function()
+ {
+ return this._defaultRouter;
+ },
+ setDefaultLocator: function(defaultLocator)
+ {
+ if(this._defaultLocator === null ? defaultLocator === null : this._defaultLocator.equals(defaultLocator))
+ {
+ return this;
+ }
+
+ var factory = new ReferenceFactory(this._instance, this._communicator);
+ factory._defaultRouter = this._defaultRouter;
+ factory._defaultLocator = defaultLocator;
+ return factory;
+ },
+ getDefaultLocator: function()
+ {
+ return this._defaultLocator;
+ },
+ checkForUnknownProperties: function(prefix)
+ {
+ var unknownProps = [], i, length;
+ //
+ // Do not warn about unknown properties for Ice prefixes (Ice, Glacier2, etc.)
+ //
+ for(i = 0; i < PropertyNames.clPropNames.length; ++i)
+ {
+ if(prefix.indexOf(PropertyNames.clPropNames[i] + ".") === 0)
+ {
+ return;
+ }
+ }
+
+ var props = this._instance.initializationData().properties.getPropertiesForPrefix(prefix + ".");
+ for(var e = props.entries; e !== null; e = e.next)
+ {
+ var valid = false;
+ for(i = 0, length = suffixes.length; i < length; ++i)
+ {
+ if(e.key === prefix + "." + suffixes[i])
+ {
+ valid = true;
+ break;
+ }
+ }
+
+ if(!valid)
+ {
+ unknownProps.push(e.key);
+ }
+ }
+
+ if(unknownProps.length > 0)
+ {
+ var message = [];
+ message.push("found unknown properties for proxy '");
+ message.push(prefix);
+ message.push("':");
+ for(i = 0, length = unknownProps.length; i < length; ++i)
+ {
+ message.push("\n ");
+ message.push(unknownProps[i]);
+ }
+ this._instance.initializationData().logger.warning(message.join(""));
+ }
+ },
+ createImpl: function(ident, facet, mode, secure, protocol, encoding, endpoints, adapterId,
+ propertyPrefix)
+ {
+ var defaultsAndOverrides = this._instance.defaultsAndOverrides();
+
+ //
+ // Default local proxy options.
+ //
+ var locatorInfo = null;
+ if(this._defaultLocator !== null)
+ {
+ if(!this._defaultLocator.__reference().getEncoding().equals(encoding))
+ {
+ locatorInfo = this._instance.locatorManager().find(this._defaultLocator.ice_encodingVersion(encoding));
+ }
+ else
+ {
+ locatorInfo = this._instance.locatorManager().find(this._defaultLocator);
+ }
+ }
+ var routerInfo = this._instance.routerManager().find(this._defaultRouter);
+ var cacheConnection = true;
+ var preferSecure = defaultsAndOverrides.defaultPreferSecure;
+ var endpointSelection = defaultsAndOverrides.defaultEndpointSelection;
+ var locatorCacheTimeout = defaultsAndOverrides.defaultLocatorCacheTimeout;
+
+ //
+ // Override the defaults with the proxy properties if a property prefix is defined.
+ //
+ if(propertyPrefix !== null && propertyPrefix.length > 0)
+ {
+ var properties = this._instance.initializationData().properties;
+
+ //
+ // Warn about unknown properties.
+ //
+ if(properties.getPropertyAsIntWithDefault("Ice.Warn.UnknownProperties", 1) > 0)
+ {
+ this.checkForUnknownProperties(propertyPrefix);
+ }
+
+ var property;
+
+ property = propertyPrefix + ".Locator";
+ var locator = LocatorPrx.uncheckedCast(this._communicator.propertyToProxy(property));
+ if(locator !== null)
+ {
+ if(!locator.__reference().getEncoding().equals(encoding))
+ {
+ locatorInfo = this._instance.locatorManager().find(locator.ice_encodingVersion(encoding));
+ }
+ else
+ {
+ locatorInfo = this._instance.locatorManager().find(locator);
+ }
+ }
+
+ property = propertyPrefix + ".Router";
+ var router = RouterPrx.uncheckedCast(this._communicator.propertyToProxy(property));
+ if(router !== null)
+ {
+ var match = ".Router";
+ if(propertyPrefix.lastIndexOf(match) == propertyPrefix.length - match.length)
+ {
+ var s = "`" + property + "=" + properties.getProperty(property) +
+ "': cannot set a router on a router; setting ignored";
+ this._instance.initializationData().logger.warning(s);
+ }
+ else
+ {
+ routerInfo = this._instance.routerManager().find(router);
+ }
+ }
+
+ property = propertyPrefix + ".ConnectionCached";
+ cacheConnection = properties.getPropertyAsIntWithDefault(property, cacheConnection ? 1 : 0) > 0;
+
+ property = propertyPrefix + ".PreferSecure";
+ preferSecure = properties.getPropertyAsIntWithDefault(property, preferSecure ? 1 : 0) > 0;
+
+ property = propertyPrefix + ".EndpointSelection";
+ if(properties.getProperty(property).length > 0)
+ {
+ var type = properties.getProperty(property);
+ if(type == "Random")
+ {
+ endpointSelection = EndpointSelectionType.Random;
+ }
+ else if(type == "Ordered")
+ {
+ endpointSelection = EndpointSelectionType.Ordered;
+ }
+ else
+ {
+ throw new Ice.EndpointSelectionTypeParseException("illegal value `" + type +
+ "'; expected `Random' or `Ordered'");
+ }
+ }
+
+ property = propertyPrefix + ".LocatorCacheTimeout";
+ locatorCacheTimeout = properties.getPropertyAsIntWithDefault(property, locatorCacheTimeout);
+ }
+
+ //
+ // Create new reference
+ //
+ return new RoutableReference(this._instance,
+ this._communicator,
+ ident,
+ facet,
+ mode,
+ secure,
+ protocol,
+ encoding,
+ endpoints,
+ adapterId,
+ locatorInfo,
+ routerInfo,
+ cacheConnection,
+ preferSecure,
+ endpointSelection,
+ locatorCacheTimeout);
+ }
+ });
+
+ Ice.ReferenceFactory = ReferenceFactory;
+
+ var Reference = Class({
+ __init__: function(instance, communicator, identity, facet, mode, secure, protocol, encoding)
+ {
+ //
+ // Validate string arguments.
+ //
+ Debug.assert(identity === undefined || identity.name !== null);
+ Debug.assert(identity === undefined || identity.category !== null);
+ Debug.assert(facet === undefined || facet !== null);
+
+ this._instance = instance;
+ this._communicator = communicator;
+ this._mode = mode;
+ this._secure = secure;
+ this._identity = identity;
+ this._context = Reference._emptyContext;
+ this._facet = facet;
+ this._protocol = protocol;
+ this._encoding = encoding;
+ this._hashInitialized = false;
+ this._overrideCompress = false;
+ this._compress = false; // Only used if _overrideCompress == true
+ },
+ getMode: function()
+ {
+ return this._mode;
+ },
+ getSecure: function()
+ {
+ return this._secure;
+ },
+ getProtocol: function()
+ {
+ return this._protocol;
+ },
+ getEncoding: function()
+ {
+ return this._encoding;
+ },
+ getIdentity: function()
+ {
+ return this._identity;
+ },
+ getFacet: function()
+ {
+ return this._facet;
+ },
+ getInstance: function()
+ {
+ return this._instance;
+ },
+ getContext: function()
+ {
+ return this._context; // HashMap
+ },
+ getCommunicator: function()
+ {
+ return this._communicator;
+ },
+ getEndpoints: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ getAdapterId: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return "";
+ },
+ getRouterInfo: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ getLocatorInfo: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ getCacheConnection: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return false;
+ },
+ getPreferSecure: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return false;
+ },
+ getEndpointSelection: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ getLocatorCacheTimeout: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return 0;
+ },
+ getConnectionId: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return "";
+ },
+ //
+ // The change* methods (here and in derived classes) create
+ // a new reference based on the existing one, with the
+ // corresponding value changed.
+ //
+ changeContext: function(newContext)
+ {
+ if(newContext === undefined || newContext === null)
+ {
+ newContext = Reference._emptyContext;
+ }
+ var r = this._instance.referenceFactory().copy(this);
+ if(newContext.size === 0)
+ {
+ r._context = Reference._emptyContext;
+ }
+ else
+ {
+ r._context = new HashMap(newContext);
+ }
+ return r;
+ },
+ changeMode: function(newMode)
+ {
+ if(newMode === this._mode)
+ {
+ return this;
+ }
+ var r = this._instance.referenceFactory().copy(this);
+ r._mode = newMode;
+ return r;
+ },
+ changeSecure: function(newSecure)
+ {
+ if(newSecure === this._secure)
+ {
+ return this;
+ }
+ var r = this._instance.referenceFactory().copy(this);
+ r._secure = newSecure;
+ return r;
+ },
+ changeIdentity: function(newIdentity)
+ {
+ if(newIdentity.equals(this._identity))
+ {
+ return this;
+ }
+ var r = this._instance.referenceFactory().copy(this);
+ r._identity = new Identity(newIdentity.name, newIdentity.category);
+ return r;
+ },
+ changeFacet: function(newFacet)
+ {
+ if(newFacet === this._facet)
+ {
+ return this;
+ }
+ var r = this._instance.referenceFactory().copy(this);
+ r._facet = newFacet;
+ return r;
+ },
+ changeEncoding: function(newEncoding)
+ {
+ if(newEncoding.equals(this._encoding))
+ {
+ return this;
+ }
+ var r = this._instance.referenceFactory().copy(this);
+ r._encoding = newEncoding;
+ return r;
+ },
+ changeCompress: function(newCompress)
+ {
+ if(this._overrideCompress && this._compress === newCompress)
+ {
+ return this;
+ }
+ var r = this._instance.referenceFactory().copy(this);
+ r._compress = newCompress;
+ r._overrideCompress = true;
+ return r;
+ },
+ changeAdapterId: function(newAdapterId)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ changeEndpoints: function(newEndpoints)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ changeLocator: function(newLocator)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ changeRouter: function(newRouter)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ changeCacheConnection: function(newCache)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ changePreferSecure: function(newPreferSecure)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ changeEndpointSelection: function(newType)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ changeLocatorCacheTimeout: function(newTimeout)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ changeTimeout: function(newTimeout)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ changeConnectionId: function(connectionId)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ hashCode: function()
+ {
+ if(this._hashInitialized)
+ {
+ return this._hashValue;
+ }
+
+ var h = 5381;
+ h = HashUtil.addNumber(h, this._mode);
+ h = HashUtil.addBoolean(h, this._secure);
+ h = HashUtil.addHashable(h, this._identity);
+ if(this._context !== null && this._context !== undefined)
+ {
+ for(var e = this._context.entries; e !== null; e = e.next)
+ {
+ h = HashUtil.addString(h, e.key);
+ h = HashUtil.addString(h, e.value);
+ }
+ }
+ h = HashUtil.addString(h, this._facet);
+ h = HashUtil.addBoolean(h, this._overrideCompress);
+ if(this._overrideCompress)
+ {
+ h = HashUtil.addBoolean(h, this._compress);
+ }
+ h = HashUtil.addHashable(h, this._protocol);
+ h = HashUtil.addHashable(h, this._encoding);
+
+ this._hashValue = h;
+ this._hashInitialized = true;
+
+ return this._hashValue;
+ },
+ //
+ // Utility methods
+ //
+ isIndirect: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return false;
+ },
+ isWellKnown: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return false;
+ },
+ //
+ // Marshal the reference.
+ //
+ streamWrite: function(s)
+ {
+ //
+ // Don't write the identity here. Operations calling streamWrite
+ // write the identity.
+ //
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ if(this._facet.length === 0)
+ {
+ s.writeSize(0); // Empty string sequence
+ }
+ else
+ {
+ s.writeSize(1); // String sequence with one element
+ s.writeString(this._facet);
+ }
+
+ s.writeByte(this._mode);
+
+ s.writeBool(this._secure);
+
+ if(!s.getWriteEncoding().equals(Ice.Encoding_1_0))
+ {
+ this._protocol.__write(s);
+ this._encoding.__write(s);
+ }
+
+ // Derived class writes the remainder of the reference.
+ },
+ //
+ // Convert the reference to its string form.
+ //
+ toString: function()
+ {
+ //
+ // WARNING: Certain features, such as proxy validation in Glacier2,
+ // depend on the format of proxy strings. Changes to toString() and
+ // methods called to generate parts of the reference string could break
+ // these features. Please review for all features that depend on the
+ // format of proxyToString() before changing this and related code.
+ //
+ var s = [];
+
+ //
+ // If the encoded identity string contains characters which
+ // the reference parser uses as separators, then we enclose
+ // the identity string in quotes.
+ //
+ var id = this._instance.identityToString(this._identity);
+ if(id.search(/[ :@]/) != -1)
+ {
+ s.push('"');
+ s.push(id);
+ s.push('"');
+ }
+ else
+ {
+ s.push(id);
+ }
+
+ if(this._facet.length > 0)
+ {
+ //
+ // If the encoded facet string contains characters which
+ // the reference parser uses as separators, then we enclose
+ // the facet string in quotes.
+ //
+ s.push(" -f ");
+ var fs = StringUtil.escapeString(this._facet, "");
+ if(fs.search(/[ :@]/) != -1)
+ {
+ s.push('"');
+ s.push(fs);
+ s.push('"');
+ }
+ else
+ {
+ s.push(fs);
+ }
+ }
+
+ switch(this._mode)
+ {
+ case RefMode.ModeTwoway:
+ {
+ s.push(" -t");
+ break;
+ }
+
+ case RefMode.ModeOneway:
+ {
+ s.push(" -o");
+ break;
+ }
+
+ case RefMode.ModeBatchOneway:
+ {
+ s.push(" -O");
+ break;
+ }
+
+ case RefMode.ModeDatagram:
+ {
+ s.push(" -d");
+ break;
+ }
+
+ case RefMode.ModeBatchDatagram:
+ {
+ s.push(" -D");
+ break;
+ }
+ }
+
+ if(this._secure)
+ {
+ s.push(" -s");
+ }
+
+ if(!this._protocol.equals(Ice.Protocol_1_0))
+ {
+ //
+ // We only print the protocol if it's not 1.0. It's fine as
+ // long as we don't add Ice.Default.ProtocolVersion, a
+ // stringified proxy will convert back to the same proxy with
+ // stringToProxy.
+ //
+ s.push(" -p ");
+ s.push(Ice.protocolVersionToString(this._protocol));
+ }
+
+ //
+ // Always print the encoding version to ensure a stringified proxy
+ // will convert back to a proxy with the same encoding with
+ // stringToProxy (and won't use Ice.Default.EncodingVersion).
+ //
+ s.push(" -e ");
+ s.push(Ice.encodingVersionToString(this._encoding));
+
+ return s.join("");
+
+ // Derived class writes the remainder of the string.
+ },
+ //
+ // Convert the reference to its property form.
+ //
+ toProperty: function(prefix)
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ getConnection: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ },
+ equals: function(r)
+ {
+ //
+ // Note: if(this === r) and type test are performed by each non-abstract derived class.
+ //
+
+ if(this._mode !== r._mode)
+ {
+ return false;
+ }
+
+ if(this._secure !== r._secure)
+ {
+ return false;
+ }
+
+ if(!this._identity.equals(r._identity))
+ {
+ return false;
+ }
+
+ if(!this._context.equals(r._context))
+ {
+ return false;
+ }
+
+ if(this._facet !== r._facet)
+ {
+ return false;
+ }
+
+ if(this._overrideCompress !== r._overrideCompress)
+ {
+ return false;
+ }
+ if(this._overrideCompress && this._compress !== r._compress)
+ {
+ return false;
+ }
+
+ if(!this._protocol.equals(r._protocol))
+ {
+ return false;
+ }
+
+ if(!this._encoding.equals(r._encoding))
+ {
+ return false;
+ }
+
+ return true;
+ },
+ clone: function()
+ {
+ // Abstract
+ Debug.assert(false);
+ return null;
+ },
+ copyMembers: function(r)
+ {
+ //
+ // Copy the members that are not passed to the constructor.
+ //
+ r._context = this._context;
+ r._overrideCompress = this._overrideCompress;
+ r._compress = this._compress;
+ }
+ });
+
+ Reference._emptyContext = new HashMap();
+ Reference._emptyEndpoints = [];
+
+ Ice.Reference = Reference;
+
+ var FixedReference = Class(Reference, {
+ __init__: function(instance, communicator, identity, facet, mode, secure, encoding, connection)
+ {
+ Reference.call(this, instance, communicator, identity, facet, mode, secure, Ice.Protocol_1_0, encoding);
+ this._fixedConnection = connection;
+ },
+ getEndpoints: function()
+ {
+ return Reference._emptyEndpoints;
+ },
+ getAdapterId: function()
+ {
+ return "";
+ },
+ getRouterInfo: function()
+ {
+ return null;
+ },
+ getLocatorInfo: function()
+ {
+ return null;
+ },
+ getCacheConnection: function()
+ {
+ return false;
+ },
+ getPreferSecure: function()
+ {
+ return false;
+ },
+ getEndpointSelection: function()
+ {
+ return EndpointSelectionType.Random;
+ },
+ getLocatorCacheTimeout: function()
+ {
+ return 0;
+ },
+ getConnectionId: function()
+ {
+ return "";
+ },
+ changeAdapterId: function(newAdapterId)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ changeEndpoints: function(newEndpoints)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ changeLocator: function(newLocator)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ changeRouter: function(newRouter)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ changeCacheConnection: function(newCache)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ changePreferSecure: function(prefSec)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ changeEndpointSelection: function(newType)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ changeLocatorCacheTimeout: function(newTimeout)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ changeTimeout: function(newTimeout)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ changeConnectionId: function(connectionId)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ isIndirect: function()
+ {
+ return false;
+ },
+ isWellKnown: function()
+ {
+ return false;
+ },
+ streamWrite: function(s)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ toString: function()
+ {
+ throw new Ice.FixedProxyException();
+ },
+ toProperty: function(prefix)
+ {
+ throw new Ice.FixedProxyException();
+ },
+ clone: function()
+ {
+ var r = new FixedReference(this.getInstance(), this.getCommunicator(), this.getIdentity(), this.getFacet(),
+ this.getMode(), this.getSecure(), this.getEncoding(), this._fixedConnection);
+ this.copyMembers(r);
+ return r;
+ },
+ getConnectionInternal: function(compress)
+ {
+ switch(this.getMode())
+ {
+ case RefMode.ModeTwoway:
+ case RefMode.ModeOneway:
+ case RefMode.ModeBatchOneway:
+ {
+ if(this._fixedConnection.endpoint().datagram())
+ {
+ throw new Ice.NoEndpointException("");
+ }
+ break;
+ }
+
+ case RefMode.ModeDatagram:
+ case RefMode.ModeBatchDatagram:
+ {
+ if(!this._fixedConnection.endpoint().datagram())
+ {
+ throw new Ice.NoEndpointException("");
+ }
+ break;
+ }
+ }
+
+ //
+ // If a secure connection is requested or secure overrides is set,
+ // check if the connection is secure.
+ //
+ var secure;
+ var defaultsAndOverrides = this.getInstance().defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideSecure)
+ {
+ secure = defaultsAndOverrides.overrideSecureValue;
+ }
+ else
+ {
+ secure = this.getSecure();
+ }
+ if(secure && !this._fixedConnection.endpoint().secure())
+ {
+ throw new Ice.NoEndpointException("");
+ }
+
+ this._fixedConnection.throwException(); // Throw in case our connection is already destroyed.
+
+ if(defaultsAndOverrides.overrideCompress)
+ {
+ compress.value = defaultsAndOverrides.overrideCompressValue;
+ }
+ else if(this._overrideCompress)
+ {
+ compress.value = this._compress;
+ }
+ else
+ {
+ compress.value = this._fixedConnection.endpoint().compress();
+ }
+ return this._fixedConnection;
+ },
+ getConnection: function()
+ {
+ var promise = new Promise(); // success callback receives (connection, compress)
+ try
+ {
+ var compress = { 'value': false };
+ var connection = this.getConnectionInternal(compress);
+ promise.succeed(connection, compress.value);
+ }
+ catch(ex)
+ {
+ promise.fail(ex);
+ }
+ return promise;
+ },
+ equals: function(rhs)
+ {
+ if(this === rhs)
+ {
+ return true;
+ }
+ if(!(rhs instanceof FixedReference))
+ {
+ return false;
+ }
+ if(!Reference.prototype.equals.call(this, rhs))
+ {
+ return false;
+ }
+ return this._fixedConnection.equals(rhs._fixedConnection);
+ }
+ });
+
+ Ice.FixedReference = FixedReference;
+
+ var RoutableReference = Class(Reference, {
+ __init__: function(instance, communicator, identity, facet, mode, secure, protocol, encoding, endpoints,
+ adapterId, locatorInfo, routerInfo, cacheConnection, preferSecure, endpointSelection,
+ locatorCacheTimeout)
+ {
+ Reference.call(this, instance, communicator, identity, facet, mode, secure, protocol, encoding);
+ this._endpoints = endpoints;
+ this._adapterId = adapterId;
+ this._locatorInfo = locatorInfo;
+ this._routerInfo = routerInfo;
+ this._cacheConnection = cacheConnection;
+ this._preferSecure = preferSecure;
+ this._endpointSelection = endpointSelection;
+ this._locatorCacheTimeout = locatorCacheTimeout;
+ this._overrideTimeout = false;
+ this._timeout = -1;
+
+ if(this._endpoints === null)
+ {
+ this._endpoints = Reference._emptyEndpoints;
+ }
+ if(this._adapterId === null)
+ {
+ this._adapterId = "";
+ }
+ this._connectionId = "";
+ Debug.assert(this._adapterId.length === 0 || this._endpoints.length === 0);
+ },
+ getEndpoints: function()
+ {
+ return this._endpoints;
+ },
+ getAdapterId: function()
+ {
+ return this._adapterId;
+ },
+ getRouterInfo: function()
+ {
+ return this._routerInfo;
+ },
+ getLocatorInfo: function()
+ {
+ return this._locatorInfo;
+ },
+ getCacheConnection: function()
+ {
+ return this._cacheConnection;
+ },
+ getPreferSecure: function()
+ {
+ return this._preferSecure;
+ },
+ getEndpointSelection: function()
+ {
+ return this._endpointSelection;
+ },
+ getLocatorCacheTimeout: function()
+ {
+ return this._locatorCacheTimeout;
+ },
+ getConnectionId: function()
+ {
+ return this._connectionId;
+ },
+ changeEncoding: function(newEncoding)
+ {
+ var r = Reference.prototype.changeEncoding.call(this, newEncoding);
+ if(r !== this)
+ {
+ var locInfo = r._locatorInfo;
+ if(locInfo !== null && !locInfo.getLocator().ice_getEncodingVersion().equals(newEncoding))
+ {
+ r._locatorInfo = this.getInstance().locatorManager().find(
+ locInfo.getLocator().ice_encodingVersion(newEncoding));
+ }
+ }
+ return r;
+ },
+ changeCompress: function(newCompress)
+ {
+ var r = Reference.prototype.changeCompress.call(this, newCompress);
+ if(r !== this && this._endpoints.length > 0) // Also override the compress flag on the endpoints if it was updated.
+ {
+ var newEndpoints = [];
+ for(var i = 0; i < this._endpoints.length; i++)
+ {
+ newEndpoints[i] = this._endpoints[i].changeCompress(newCompress);
+ }
+ r._endpoints = newEndpoints;
+ }
+ return r;
+ },
+ changeAdapterId: function(newAdapterId)
+ {
+ if(this._adapterId === newAdapterId)
+ {
+ return this;
+ }
+ var r = this.getInstance().referenceFactory().copy(this);
+ r._adapterId = newAdapterId;
+ r._endpoints = Reference._emptyEndpoints;
+ return r;
+ },
+ changeEndpoints: function(newEndpoints)
+ {
+ if(ArrayUtil.equals(newEndpoints, this._endpoints, function(e1, e2) { return e1.equals(e2); }))
+ {
+ return this;
+ }
+ var r = this.getInstance().referenceFactory().copy(this);
+ r._endpoints = newEndpoints;
+ r._adapterId = "";
+ r.applyOverrides(r._endpoints);
+ return r;
+ },
+ changeLocator: function(newLocator)
+ {
+ var newLocatorInfo = this.getInstance().locatorManager().find(newLocator);
+ if(newLocatorInfo !== null && this._locatorInfo !== null && newLocatorInfo.equals(this._locatorInfo))
+ {
+ return this;
+ }
+ var r = this.getInstance().referenceFactory().copy(this);
+ r._locatorInfo = newLocatorInfo;
+ return r;
+ },
+ changeRouter: function(newRouter)
+ {
+ var newRouterInfo = this.getInstance().routerManager().find(newRouter);
+ if(newRouterInfo !== null && this._routerInfo !== null && newRouterInfo.equals(this._routerInfo))
+ {
+ return this;
+ }
+ var r = this.getInstance().referenceFactory().copy(this);
+ r._routerInfo = newRouterInfo;
+ return r;
+ },
+ changeCacheConnection: function(newCache)
+ {
+ if(newCache === this._cacheConnection)
+ {
+ return this;
+ }
+ var r = this.getInstance().referenceFactory().copy(this);
+ r._cacheConnection = newCache;
+ return r;
+ },
+ changePreferSecure: function(newPreferSecure)
+ {
+ if(newPreferSecure === this._preferSecure)
+ {
+ return this;
+ }
+ var r = this.getInstance().referenceFactory().copy(this);
+ r._preferSecure = newPreferSecure;
+ return r;
+ },
+ changeEndpointSelection: function(newType)
+ {
+ if(newType === this._endpointSelection)
+ {
+ return this;
+ }
+ var r = this.getInstance().referenceFactory().copy(this);
+ r._endpointSelection = newType;
+ return r;
+ },
+ changeLocatorCacheTimeout: function(newTimeout)
+ {
+ if(this._locatorCacheTimeout === newTimeout)
+ {
+ return this;
+ }
+ var r = this.getInstance().referenceFactory().copy(this);
+ r._locatorCacheTimeout = newTimeout;
+ return r;
+ },
+ changeTimeout: function(newTimeout)
+ {
+ if(this._overrideTimeout && this._timeout === newTimeout)
+ {
+ return this;
+ }
+ var r = this.getInstance().referenceFactory().copy(this);
+ r._timeout = newTimeout;
+ r._overrideTimeout = true;
+ if(this._endpoints.length > 0)
+ {
+ var newEndpoints = [];
+ for(var i = 0; i < this._endpoints.length; i++)
+ {
+ newEndpoints[i] = this._endpoints[i].changeTimeout(newTimeout);
+ }
+ r._endpoints = newEndpoints;
+ }
+ return r;
+ },
+ changeConnectionId: function(id)
+ {
+ if(this._connectionId === id)
+ {
+ return this;
+ }
+ var r = this.getInstance().referenceFactory().copy(this);
+ r._connectionId = id;
+ if(this._endpoints.length > 0)
+ {
+ var newEndpoints = [];
+ for(var i = 0; i < this._endpoints.length; i++)
+ {
+ newEndpoints[i] = this._endpoints[i].changeConnectionId(id);
+ }
+ r._endpoints = newEndpoints;
+ }
+ return r;
+ },
+ isIndirect: function()
+ {
+ return this._endpoints.length === 0;
+ },
+ isWellKnown: function()
+ {
+ return this._endpoints.length === 0 && this._adapterId.length === 0;
+ },
+ streamWrite: function(s)
+ {
+ Reference.prototype.streamWrite.call(this, s);
+
+ s.writeSize(this._endpoints.length);
+ if(this._endpoints.length > 0)
+ {
+ Debug.assert(this._adapterId.length === 0);
+ for(var i = 0; i < this._endpoints.length; ++i)
+ {
+ this._endpoints[i].streamWrite(s);
+ }
+ }
+ else
+ {
+ s.writeString(this._adapterId); // Adapter id.
+ }
+ },
+ toString: function()
+ {
+ //
+ // WARNING: Certain features, such as proxy validation in Glacier2,
+ // depend on the format of proxy strings. Changes to toString() and
+ // methods called to generate parts of the reference string could break
+ // these features. Please review for all features that depend on the
+ // format of proxyToString() before changing this and related code.
+ //
+ var s = [];
+ s.push(Reference.prototype.toString.call(this));
+ if(this._endpoints.length > 0)
+ {
+ for(var i = 0; i < this._endpoints.length; ++i)
+ {
+ var endp = this._endpoints[i].toString();
+ if(endp !== null && endp.length > 0)
+ {
+ s.push(':');
+ s.push(endp);
+ }
+ }
+ }
+ else if(this._adapterId.length > 0)
+ {
+ s.push(" @ ");
+
+ //
+ // If the encoded adapter id string contains characters which
+ // the reference parser uses as separators, then we enclose
+ // the adapter id string in quotes.
+ //
+ var a = StringUtil.escapeString(this._adapterId, null);
+ if(a.search(/[ :@]/) != -1)
+ {
+ s.push('"');
+ s.push(a);
+ s.push('"');
+ }
+ else
+ {
+ s.push(a);
+ }
+ }
+ return s.join("");
+ },
+ toProperty: function(prefix)
+ {
+ var properties = new HashMap(), e;
+
+ properties.set(prefix, this.toString());
+ properties.set(prefix + ".CollocationOptimized", "0");
+ properties.set(prefix + ".ConnectionCached", this._cacheConnection ? "1" : "0");
+ properties.set(prefix + ".PreferSecure", this._preferSecure ? "1" : "0");
+ properties.set(prefix + ".EndpointSelection",
+ this._endpointSelection === EndpointSelectionType.Random ? "Random" : "Ordered");
+
+ properties.set(prefix + ".LocatorCacheTimeout", "" + this._locatorCacheTimeout);
+
+ if(this._routerInfo !== null)
+ {
+ var h = this._routerInfo.getRouter();
+ var routerProperties = h.__reference().toProperty(prefix + ".Router");
+ for(e = routerProperties.entries; e !== null; e = e.next)
+ {
+ properties.set(e.key, e.value);
+ }
+ }
+
+ if(this._locatorInfo !== null)
+ {
+ var p = this._locatorInfo.getLocator();
+ var locatorProperties = p.__reference().toProperty(prefix + ".Locator");
+ for(e = locatorProperties.entries; e !== null; e = e.next)
+ {
+ properties.set(e.key, e.value);
+ }
+ }
+
+ return properties;
+ },
+ hashCode: function()
+ {
+ if(!this._hashInitialized)
+ {
+ Reference.prototype.hashCode.call(this); // Initializes _hashValue.
+ this._hashValue = HashUtil.addString(this._hashValue, this._adapterId);
+ }
+ return this._hashValue;
+ },
+ equals: function(rhs)
+ {
+ if(this === rhs)
+ {
+ return true;
+ }
+ if(!(rhs instanceof RoutableReference))
+ {
+ return false;
+ }
+
+ if(!Reference.prototype.equals.call(this, rhs))
+ {
+ return false;
+ }
+
+ if(this._locatorInfo === null ? rhs._locatorInfo !== null : !this._locatorInfo.equals(rhs._locatorInfo))
+ {
+ return false;
+ }
+ if(this._routerInfo === null ? rhs._routerInfo !== null : !this._routerInfo.equals(rhs._routerInfo))
+ {
+ return false;
+ }
+ if(this._cacheConnection !== rhs._cacheConnection)
+ {
+ return false;
+ }
+ if(this._preferSecure !== rhs._preferSecure)
+ {
+ return false;
+ }
+ if(this._endpointSelection !== rhs._endpointSelection)
+ {
+ return false;
+ }
+ if(this._locatorCacheTimeout !== rhs._locatorCacheTimeout)
+ {
+ return false;
+ }
+ if(this._connectionId !== rhs._connectionId)
+ {
+ return false;
+ }
+ if(this._overrideTimeout !== rhs._overrideTimeout)
+ {
+ return false;
+ }
+ if(this._overrideTimeout && this._timeout !== rhs._timeout)
+ {
+ return false;
+ }
+ if(!ArrayUtil.equals(this._endpoints, rhs._endpoints, function(e1, e2) { return e1.equals(e2); }))
+ {
+ return false;
+ }
+ if(this._adapterId !== rhs._adapterId)
+ {
+ return false;
+ }
+ return true;
+ },
+ getConnection: function()
+ {
+ var promise = new Promise(); // success callback receives (connection, compress)
+
+ if(this._routerInfo !== null)
+ {
+ //
+ // If we route, we send everything to the router's client
+ // proxy endpoints.
+ //
+ var self = this;
+ this._routerInfo.getClientEndpoints().then(
+ function(endpts)
+ {
+ if(endpts.length > 0)
+ {
+ self.applyOverrides(endpts);
+ self.createConnection(endpts).then(
+ function(connection, compress)
+ {
+ promise.succeed(connection, compress);
+ },
+ function(ex)
+ {
+ promise.fail(ex);
+ });
+ }
+ else
+ {
+ self.getConnectionNoRouterInfo(promise);
+ }
+ }).exception(
+ function(ex)
+ {
+ promise.fail(ex);
+ });
+ }
+ else
+ {
+ this.getConnectionNoRouterInfo(promise);
+ }
+
+ return promise;
+ },
+ getConnectionNoRouterInfo: function(promise)
+ {
+ if(this._endpoints.length > 0)
+ {
+ this.createConnection(this._endpoints).then(
+ function(connection, compress)
+ {
+ promise.succeed(connection, compress);
+ }).exception(
+ function(ex)
+ {
+ promise.fail(ex);
+ });
+ return;
+ }
+
+ var self = this;
+ if(this._locatorInfo !== null)
+ {
+ this._locatorInfo.getEndpoints(this, null, this._locatorCacheTimeout).then(
+ function(endpoints, cached)
+ {
+ if(endpoints.length === 0)
+ {
+ promise.fail(new Ice.NoEndpointException(self.toString()));
+ return;
+ }
+
+ self.applyOverrides(endpoints);
+ self.createConnection(endpoints).then(
+ function(connection, compress)
+ {
+ promise.succeed(connection, compress);
+ },
+ function(ex)
+ {
+ if(ex instanceof Ice.NoEndpointException)
+ {
+ //
+ // No need to retry if there's no endpoints.
+ //
+ promise.fail(ex);
+ }
+ else
+ {
+ Debug.assert(self._locatorInfo !== null);
+ self.getLocatorInfo().clearCache(self);
+ if(cached)
+ {
+ var traceLevels = self.getInstance().traceLevels();
+ if(traceLevels.retry >= 2)
+ {
+ var s = "connection to cached endpoints failed\n" +
+ "removing endpoints from cache and trying one more time\n" +
+ ExUtil.toString(ex);
+ self.getInstance().initializationData().logger.trace(
+ traceLevels.retryCat, s);
+ }
+ self.getConnectionNoRouterInfo(promise); // Retry.
+ return;
+ }
+ promise.fail(ex);
+ }
+ });
+ }).exception(
+ function(ex)
+ {
+ promise.fail(ex);
+ });
+ }
+ else
+ {
+ promise.fail(new Ice.NoEndpointException(this.toString()));
+ }
+ },
+ clone: function()
+ {
+ var r = new RoutableReference(this.getInstance(), this.getCommunicator(), this.getIdentity(), this.getFacet(),
+ this.getMode(), this.getSecure(), this.getProtocol(), this.getEncoding(),
+ this._endpoints, this._adapterId, this._locatorInfo, this._routerInfo,
+ this._cacheConnection, this._preferSecure, this._endpointSelection,
+ this._locatorCacheTimeout);
+ this.copyMembers(r);
+ return r;
+ },
+ copyMembers: function(rhs)
+ {
+ //
+ // Copy the members that are not passed to the constructor.
+ //
+ Reference.prototype.copyMembers.call(this, rhs);
+ rhs._overrideTimeout = this._overrideTimeout;
+ rhs._timeout = this._timeout;
+ rhs._connectionId = this._connectionId;
+ },
+ applyOverrides: function(endpts)
+ {
+ //
+ // Apply the endpoint overrides to each endpoint.
+ //
+ for(var i = 0; i < endpts.length; ++i)
+ {
+ endpts[i] = endpts[i].changeConnectionId(this._connectionId);
+ if(this._overrideCompress)
+ {
+ endpts[i] = endpts[i].changeCompress(this._compress);
+ }
+ if(this._overrideTimeout)
+ {
+ endpts[i] = endpts[i].changeTimeout(this._timeout);
+ }
+ }
+ },
+ filterEndpoints: function(allEndpoints)
+ {
+ var endpoints = [];
+
+ //
+ // Filter out opaque endpoints.
+ //
+ for(var i = 0; i < allEndpoints.length; ++i)
+ {
+ if(!(allEndpoints[i] instanceof OpaqueEndpointI))
+ {
+ endpoints.push(allEndpoints[i]);
+ }
+ }
+
+ //
+ // Filter out endpoints according to the mode of the reference.
+ //
+ switch(this.getMode())
+ {
+ case RefMode.ModeTwoway:
+ case RefMode.ModeOneway:
+ case RefMode.ModeBatchOneway:
+ {
+ //
+ // Filter out datagram endpoints.
+ //
+ endpoints = ArrayUtil.filter(endpoints, function(e, index, arr) { return !e.datagram(); });
+ break;
+ }
+
+ case RefMode.ModeDatagram:
+ case RefMode.ModeBatchDatagram:
+ {
+ //
+ // Filter out non-datagram endpoints.
+ //
+ endpoints = ArrayUtil.filter(endpoints, function(e, index, arr) { return e.datagram(); });
+ break;
+ }
+ }
+
+ //
+ // Sort the endpoints according to the endpoint selection type.
+ //
+ switch(this.getEndpointSelection())
+ {
+ case EndpointSelectionType.Random:
+ {
+ //
+ // Shuffle the endpoints.
+ //
+ ArrayUtil.shuffle(endpoints);
+ break;
+ }
+ case EndpointSelectionType.Ordered:
+ {
+ // Nothing to do.
+ break;
+ }
+ default:
+ {
+ Debug.assert(false);
+ break;
+ }
+ }
+
+ //
+ // If a secure connection is requested or secure overrides is
+ // set, remove all non-secure endpoints. Otherwise if preferSecure is set
+ // make secure endpoints prefered. By default make non-secure
+ // endpoints preferred over secure endpoints.
+ //
+ var overrides = this.getInstance().defaultsAndOverrides();
+ if(overrides.overrideSecure ? overrides.overrideSecureValue : this.getSecure())
+ {
+ endpoints = ArrayUtil.filter(endpoints, function(e, index, arr) { return e.secure(); });
+ }
+ else
+ {
+ var preferSecure = this.getPreferSecure();
+ var compare = function(e1, e2)
+ {
+ var ls = e1.secure();
+ var rs = e2.secure();
+ if((ls && rs) || (!ls && !rs))
+ {
+ return 0;
+ }
+ else if(!ls && rs)
+ {
+ return preferSecure ? 1 : -1;
+ }
+ else
+ {
+ return preferSecure ? -1 : 1;
+ }
+ };
+ endpoints.sort(compare);
+ }
+ return endpoints;
+ },
+ createConnection: function(allEndpoints)
+ {
+ var endpoints = this.filterEndpoints(allEndpoints);
+ if(endpoints.length === 0)
+ {
+ return new Promise().fail(new Ice.NoEndpointException(this.toString()));
+ }
+
+ //
+ // Finally, create the connection.
+ //
+ var promise = new Promise();
+ var factory = this.getInstance().outgoingConnectionFactory();
+ var cb;
+ if(this.getCacheConnection() || endpoints.length == 1)
+ {
+ //
+ // Get an existing connection or create one if there's no
+ // existing connection to one of the given endpoints.
+ //
+ cb = new CreateConnectionCallback(this, null, promise);
+ factory.create(endpoints, false, this.getEndpointSelection()).then(
+ function(connection, compress)
+ {
+ cb.setConnection(connection, compress);
+ }).exception(
+ function(ex)
+ {
+ cb.setException(ex);
+ });
+ }
+ else
+ {
+ //
+ // Go through the list of endpoints and try to create the
+ // connection until it succeeds. This is different from just
+ // calling create() with the given endpoints since this might
+ // create a new connection even if there's an existing
+ // connection for one of the endpoints.
+ //
+ var v = [ endpoints[0] ];
+ cb = new CreateConnectionCallback(this, endpoints, promise);
+ factory.create(v, true, this.getEndpointSelection()).then(
+ function(connection, compress)
+ {
+ cb.setConnection(connection, compress);
+ }).exception(
+ function(ex)
+ {
+ cb.setException(ex);
+ });
+ }
+
+ return promise;
+ }
+ });
+
+ Ice.RoutableReference = RoutableReference;
+ global.Ice = Ice;
+
+ var CreateConnectionCallback = Class({
+ __init__: function(r, endpoints, promise)
+ {
+ this.ref = r;
+ this.endpoints = endpoints;
+ this.promise = promise;
+ this.i = 0;
+ this.exception = null;
+ },
+ setConnection: function(connection, compress)
+ {
+ //
+ // If we have a router, set the object adapter for this router
+ // (if any) to the new connection, so that callbacks from the
+ // router can be received over this new connection.
+ //
+ if(this.ref.getRouterInfo() !== null && this.ref.getRouterInfo().getAdapter() !== null)
+ {
+ connection.setAdapter(this.ref.getRouterInfo().getAdapter());
+ }
+ this.promise.succeed(connection, compress);
+ },
+ setException: function(ex)
+ {
+ if(this.exception === null)
+ {
+ this.exception = ex;
+ }
+
+ if(this.endpoints === null || ++this.i === this.endpoints.length)
+ {
+ this.promise.fail(this.exception);
+ return;
+ }
+
+ var more = this.i != this.endpoints.length - 1;
+ var arr = [ this.endpoints[this.i] ];
+ var self = this;
+ this.ref.getInstance().outgoingConnectionFactory().create(arr, more, this.ref.getEndpointSelection()).then(
+ function(connection, compress)
+ {
+ self.setConnection(connection, compress);
+ }).exception(
+ function(ex)
+ {
+ self.setException(ex);
+ });
+ }
+ });
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ReferenceMode.js b/js/src/Ice/ReferenceMode.js
new file mode 100644
index 00000000000..4a6de00fd7a
--- /dev/null
+++ b/js/src/Ice/ReferenceMode.js
@@ -0,0 +1,30 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+
+ //
+ // Using a separate module for these constants so that ObjectPrx does
+ // not need to include Reference.
+ //
+ var ReferenceMode =
+ {
+ ModeTwoway: 0,
+ ModeOneway: 1,
+ ModeBatchOneway: 2,
+ ModeDatagram: 3,
+ ModeBatchDatagram: 4,
+ ModeLast: 4
+ };
+
+ Ice.ReferenceMode = ReferenceMode;
+
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/RetryQueue.js b/js/src/Ice/RetryQueue.js
new file mode 100644
index 00000000000..5462933c15f
--- /dev/null
+++ b/js/src/Ice/RetryQueue.js
@@ -0,0 +1,83 @@
+// **********************************************************************
+//
+// 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/Debug");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var Debug = Ice.Debug;
+
+ var Class = Ice.Class;
+
+ var RetryQueue = Class({
+ __init__: function(instance)
+ {
+ this._instance = instance;
+ this._requests = [];
+ },
+ add: function(outAsync, interval)
+ {
+ var task = new RetryTask(this, outAsync);
+ this._instance.timer().schedule(function()
+ {
+ task.run();
+ }, interval);
+ this._requests.push(task);
+ },
+ destroy: function()
+ {
+ for(var i = 0; i < this._requests.length; ++i)
+ {
+ this._requests[i].destroy();
+ }
+ this._requests = [];
+ },
+ remove: function(task)
+ {
+ var idx = this._requests.indexOf(task);
+ if(idx >= 0)
+ {
+ this._requests.splice(idx, 1);
+ return true;
+ }
+ return false;
+ }
+ });
+ Ice.RetryQueue = RetryQueue;
+
+ var RetryTask = Class({
+ __init__: function(queue, outAsync, interval)
+ {
+ this.queue = queue;
+ this.outAsync = outAsync;
+ },
+ run: function()
+ {
+ if(this.queue.remove(this))
+ {
+ try
+ {
+ this.outAsync.__send();
+ }
+ catch(ex)
+ {
+ this.outAsync.__exception(ex);
+ }
+ }
+ },
+ destroy: function()
+ {
+ this.outAsync.__exception(new Ice.CommunicatorDestroyedException());
+ }
+ });
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/RouterInfo.js b/js/src/Ice/RouterInfo.js
new file mode 100644
index 00000000000..1a15ee3c414
--- /dev/null
+++ b/js/src/Ice/RouterInfo.js
@@ -0,0 +1,229 @@
+// **********************************************************************
+//
+// 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/ArrayUtil");
+ require("Ice/Debug");
+ require("Ice/HashMap");
+ require("Ice/Promise");
+ require("Ice/LocalException");
+ require("Ice/Exception");
+
+ var Ice = global.Ice || {};
+
+ var ArrayUtil = Ice.ArrayUtil;
+ var Debug = Ice.Debug;
+ var HashMap = Ice.HashMap;
+ var Promise = Ice.Promise;
+
+ var RouterInfo = Ice.Class({
+ __init__: function(router)
+ {
+ this._router = router;
+
+ Debug.assert(this._router !== null);
+
+ this._clientEndpoints = null;
+ this._serverEndpoints = null;
+ this._adapter = null;
+ this._identities = new HashMap(); // Set<Identity> = Map<Identity, 1>
+ this._identities.keyComparator = HashMap.compareEquals;
+ this._evictedIdentities = [];
+ },
+ destroy: function()
+ {
+ this._clientEndpoints = [];
+ this._serverEndpoints = [];
+ this._adapter = null;
+ this._identities.clear();
+ },
+ equals: function(rhs)
+ {
+ if(this === rhs)
+ {
+ return true;
+ }
+
+ if(rhs instanceof RouterInfo)
+ {
+ return this._router.equals(rhs._router);
+ }
+
+ return false;
+ },
+ hashCode: function()
+ {
+ return this._router.hashCode();
+ },
+ getRouter: function()
+ {
+ //
+ // No mutex lock necessary, _router is immutable.
+ //
+ return this._router;
+ },
+ getClientEndpoints: function()
+ {
+ var promise = new Promise();
+
+ if(this._clientEndpoints !== null)
+ {
+ promise.succeed(this._clientEndpoints);
+ }
+ else
+ {
+ var self = this;
+ this._router.getClientProxy().then(
+ function(clientProxy)
+ {
+ self.setClientEndpoints(clientProxy, promise);
+ }).exception(
+ function(ex)
+ {
+ promise.fail(ex);
+ });
+ }
+
+ return promise;
+ },
+ getServerEndpoints: function()
+ {
+ if(this._serverEndpoints !== null) // Lazy initialization.
+ {
+ return new Promise().succeed(this._serverEndpoints);
+ }
+ else
+ {
+ var self = this;
+ return this._router.getServerProxy().then(
+ function(proxy)
+ {
+ return self.setServerEndpoints(proxy);
+ });
+ }
+ },
+ addProxy: function(proxy)
+ {
+ Debug.assert(proxy !== null);
+
+ if(this._identities.has(proxy.ice_getIdentity()))
+ {
+ //
+ // Only add the proxy to the router if it's not already in our local map.
+ //
+ return new Promise().succeed();
+ }
+ else
+ {
+ var self = this;
+ return this._router.addProxies([ proxy ]).then(
+ function(evictedProxies)
+ {
+ self.addAndEvictProxies(proxy, evictedProxies);
+ });
+ }
+ },
+ setAdapter: function(adapter)
+ {
+ this._adapter = adapter;
+ },
+ getAdapter: function()
+ {
+ return this._adapter;
+ },
+ clearCache: function(ref)
+ {
+ this._identities.delete(ref.getIdentity());
+ },
+ setClientEndpoints: function(clientProxy, promise)
+ {
+ if(this._clientEndpoints === null)
+ {
+ if(clientProxy === null)
+ {
+ //
+ // If getClientProxy() return nil, use router endpoints.
+ //
+ this._clientEndpoints = this._router.__reference().getEndpoints();
+ promise.succeed(this._clientEndpoints);
+ }
+ else
+ {
+ clientProxy = clientProxy.ice_router(null); // The client proxy cannot be routed.
+
+ //
+ // In order to avoid creating a new connection to the
+ // router, we must use the same timeout as the already
+ // existing connection.
+ //
+ var self = this;
+ this._router.ice_getConnection().then(
+ function(con)
+ {
+ var proxy = clientProxy.ice_timeout(con.timeout());
+ self._clientEndpoints = proxy.__reference().getEndpoints();
+ promise.succeed(self._clientEndpoints);
+ }).exception(
+ function(ex)
+ {
+ promise.fail(ex);
+ });
+ }
+ }
+ else
+ {
+ promise.succeed(this._clientEndpoints);
+ }
+ },
+ setServerEndpoints: function(serverProxy)
+ {
+ if(serverProxy === null)
+ {
+ throw new Ice.NoEndpointException();
+ }
+
+ serverProxy = serverProxy.ice_router(null); // The server proxy cannot be routed.
+ this._serverEndpoints = serverProxy.__reference().getEndpoints();
+ return this._serverEndpoints;
+ },
+ addAndEvictProxies: function(proxy, evictedProxies)
+ {
+ //
+ // Check if the proxy hasn't already been evicted by a
+ // concurrent addProxies call. If it's the case, don't
+ // add it to our local map.
+ //
+ var index = ArrayUtil.indexOf(this._evictedIdentities, proxy.ice_getIdentity(),
+ function(i1, i2) { return i1.equals(i2); });
+ if(index >= 0)
+ {
+ this._evictedIdentities.splice(index, 1);
+ }
+ else
+ {
+ //
+ // If we successfully added the proxy to the router,
+ // we add it to our local map.
+ //
+ this._identities.set(proxy.ice_getIdentity(), 1);
+ }
+
+ //
+ // We also must remove whatever proxies the router evicted.
+ //
+ for(var i = 0; i < evictedProxies.length; ++i)
+ {
+ this._identities.delete(evictedProxies[i].ice_getIdentity());
+ }
+ }
+ });
+ Ice.RouterInfo = RouterInfo;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/RouterManager.js b/js/src/Ice/RouterManager.js
new file mode 100644
index 00000000000..74156908bdd
--- /dev/null
+++ b/js/src/Ice/RouterManager.js
@@ -0,0 +1,77 @@
+// **********************************************************************
+//
+// 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/HashMap");
+ require("Ice/RouterInfo");
+ require("Ice/Router");
+
+ var Ice = global.Ice || {};
+
+ var HashMap = Ice.HashMap;
+ var RouterInfo = Ice.RouterInfo;
+ var RouterPrx = Ice.RouterPrx;
+
+ var RouterManager = Ice.Class({
+ __init__: function()
+ {
+ this._table = new HashMap(); // Map<Ice.RouterPrx, RouterInfo>
+ this._table.keyComparator = HashMap.compareEquals;
+ },
+ destroy: function()
+ {
+ for(var e = this._table.entries; e !== null; e = e.next)
+ {
+ e.value.destroy();
+ }
+ this._table.clear();
+ },
+ //
+ // Returns router info for a given router. Automatically creates
+ // the router info if it doesn't exist yet.
+ //
+ find: function(rtr)
+ {
+ if(rtr === null)
+ {
+ return null;
+ }
+
+ //
+ // The router cannot be routed.
+ //
+ var router = RouterPrx.uncheckedCast(rtr.ice_router(null));
+
+ var info = this._table.get(router);
+ if(info === undefined)
+ {
+ info = new RouterInfo(router);
+ this._table.set(router, info);
+ }
+
+ return info;
+ },
+ erase: function(rtr)
+ {
+ var info = null;
+ if(rtr !== null)
+ {
+ // The router cannot be routed.
+ var router = RouterPrx.uncheckedCast(rtr.ice_router(null));
+
+ info = this._table.get(router);
+ this._table.delete(router);
+ }
+ return info;
+ }
+ });
+ Ice.RouterManager = RouterManager;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/ServantManager.js b/js/src/Ice/ServantManager.js
new file mode 100644
index 00000000000..fef9f26c0e2
--- /dev/null
+++ b/js/src/Ice/ServantManager.js
@@ -0,0 +1,297 @@
+// **********************************************************************
+//
+// 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/Debug");
+ require("Ice/ExUtil");
+ require("Ice/HashMap");
+ require("Ice/LocalException");
+ require("Ice/StringUtil");
+
+ var Ice = global.Ice || {};
+
+ var Debug = Ice.Debug;
+ var ExUtil = Ice.ExUtil;
+ var HashMap = Ice.HashMap;
+ var StringUtil = Ice.StringUtil;
+
+ //
+ // Only for use by Ice.ObjectAdatperI.
+ //
+ var ServantManager = Ice.Class({
+ __init__: function(instance, adapterName)
+ {
+ this._instance = instance;
+ this._adapterName = adapterName;
+ this._servantMapMap = new HashMap(); // Map<Ice.Identity, Map<String, Ice.Object> >
+ this._servantMapMap.keyComparator = HashMap.compareEquals;
+ this._defaultServantMap = new HashMap(); // Map<String, Ice.Object>
+ this._locatorMap = new HashMap(); // Map<String, Ice.ServantLocator>
+ },
+ addServant: function(servant, ident, facet)
+ {
+ Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ if(facet === null)
+ {
+ facet = "";
+ }
+
+ var m = this._servantMapMap.get(ident);
+ if(m === undefined)
+ {
+ m = new HashMap();
+ this._servantMapMap.set(ident, m);
+ }
+ else
+ {
+ if(m.has(facet))
+ {
+ var ex = new Ice.AlreadyRegisteredException();
+ ex.id = this._instance.identityToString(ident);
+ ex.kindOfObject = "servant";
+ if(facet.length > 0)
+ {
+ ex.id += " -f " + StringUtil.escapeString(facet, "");
+ }
+ throw ex;
+ }
+ }
+
+ m.set(facet, servant);
+ },
+ addDefaultServant: function(servant, category)
+ {
+ Debug.assert(this._instance !== null); // Must not be called after destruction
+
+ var obj = this._defaultServantMap.get(category);
+ if(obj !== undefined)
+ {
+ var ex = new Ice.AlreadyRegisteredException();
+ ex.kindOfObject = "default servant";
+ ex.id = category;
+ throw ex;
+ }
+
+ this._defaultServantMap.set(category, servant);
+ },
+ removeServant: function(ident, facet)
+ {
+ Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ if(facet === null)
+ {
+ facet = "";
+ }
+
+ var m = this._servantMapMap.get(ident);
+ if(m === undefined || !m.has(facet))
+ {
+ var ex = new Ice.NotRegisteredException();
+ ex.id = this._instance.identityToString(ident);
+ ex.kindOfObject = "servant";
+ if(facet.length > 0)
+ {
+ ex.id += " -f " + StringUtil.escapeString(facet, "");
+ }
+ throw ex;
+ }
+
+ var obj = m.get(facet);
+ m.delete(facet);
+
+ if(m.size === 0)
+ {
+ this._servantMapMap.delete(ident);
+ }
+
+ return obj;
+ },
+ removeDefaultServant: function(category)
+ {
+ Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ var obj = this._defaultServantMap.get(category);
+ if(obj === undefined)
+ {
+ var ex = new Ice.NotRegisteredException();
+ ex.kindOfObject = "default servant";
+ ex.id = category;
+ throw ex;
+ }
+
+ this._defaultServantMap.delete(category);
+ return obj;
+ },
+ removeAllFacets: function(ident)
+ {
+ Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ var m = this._servantMapMap.get(ident);
+ if(m === undefined)
+ {
+ var ex = new Ice.NotRegisteredException();
+ ex.id = this._instance.identityToString(ident);
+ ex.kindOfObject = "servant";
+ throw ex;
+ }
+
+ this._servantMapMap.delete(ident);
+
+ return m;
+ },
+ findServant: function(ident, facet)
+ {
+ //
+ // This assert is not valid if the adapter dispatch incoming
+ // requests from bidir connections. This method might be called if
+ // requests are received over the bidir connection after the
+ // adapter was deactivated.
+ //
+ //Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ if(facet === null)
+ {
+ facet = "";
+ }
+
+ var m = this._servantMapMap.get(ident);
+ var obj = null;
+ if(m === undefined)
+ {
+ obj = this._defaultServantMap.get(ident.category);
+ if(obj === undefined)
+ {
+ obj = this._defaultServantMap.get("");
+ }
+ }
+ else
+ {
+ obj = m.get(facet);
+ }
+
+ return obj === undefined ? null : obj;
+ },
+ findDefaultServant: function(category)
+ {
+ Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ var ds = this._defaultServantMap.get(category);
+ return ds === undefined ? null : ds;
+ },
+ findAllFacets: function(ident)
+ {
+ Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ var m = this._servantMapMap.get(ident);
+ if(m !== undefined)
+ {
+ return m.clone();
+ }
+
+ return new HashMap();
+ },
+ hasServant: function(ident)
+ {
+ //
+ // This assert is not valid if the adapter dispatch incoming
+ // requests from bidir connections. This method might be called if
+ // requests are received over the bidir connection after the
+ // adapter was deactivated.
+ //
+ //Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ var m = this._servantMapMap.get(ident);
+ if(m === undefined)
+ {
+ return false;
+ }
+ else
+ {
+ Debug.assert(m.size > 0);
+ return true;
+ }
+ },
+ addServantLocator: function(locator, category)
+ {
+ Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ var l = this._locatorMap.get(category);
+ if(l !== undefined)
+ {
+ var ex = new Ice.AlreadyRegisteredException();
+ ex.id = StringUtil.escapeString(category, "");
+ ex.kindOfObject = "servant locator";
+ throw ex;
+ }
+
+ this._locatorMap.set(category, locator);
+ },
+ removeServantLocator: function(category)
+ {
+ Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ var l = this._locatorMap.get(category);
+ if(l === undefined)
+ {
+ var ex = new Ice.NotRegisteredException();
+ ex.id = StringUtil.escapeString(category, "");
+ ex.kindOfObject = "servant locator";
+ throw ex;
+ }
+ this._locatorMap.delete(category);
+ return l;
+ },
+ findServantLocator: function(category)
+ {
+ //
+ // This assert is not valid if the adapter dispatch incoming
+ // requests from bidir connections. This method might be called if
+ // requests are received over the bidir connection after the
+ // adapter was deactivated.
+ //
+ //Debug.assert(this._instance !== null); // Must not be called after destruction.
+
+ var l = this._locatorMap.get(category);
+ return l === undefined ? null : l;
+ },
+ //
+ // Only for use by Ice.ObjectAdapterI.
+ //
+ destroy: function()
+ {
+ Debug.assert(this._instance !== null); // Must not be called after destruction.
+ var logger = this._instance.initializationData().logger;
+ this._servantMapMap.clear();
+
+ var locatorMap = this._locatorMap.clone();
+ this._locatorMap.clear();
+ this._instance = null;
+
+ for(var e = locatorMap.entries; e !== null; e = e.next)
+ {
+ var locator = e.value;
+ try
+ {
+ locator.deactivate(e.key);
+ }
+ catch(ex)
+ {
+ var s = "exception during locator deactivation:\n" + "object adapter: `" + this._adapterName +
+ "'\n" + "locator category: `" + e.key + "'\n" + ExUtil.toString(ex);
+ logger.error(s);
+ }
+ }
+ }
+ });
+
+ Ice.ServantManager = ServantManager;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/SocketOperation.js b/js/src/Ice/SocketOperation.js
new file mode 100644
index 00000000000..6e45a494dcf
--- /dev/null
+++ b/js/src/Ice/SocketOperation.js
@@ -0,0 +1,23 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+
+ var SocketOperation =
+ {
+ None: 0,
+ Read: 1,
+ Write: 2,
+ Connect: 2 // Same as Write
+ };
+
+ Ice.SocketOperation = SocketOperation;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/StreamHelpers.js b/js/src/Ice/StreamHelpers.js
new file mode 100644
index 00000000000..6fcce91a4d0
--- /dev/null
+++ b/js/src/Ice/StreamHelpers.js
@@ -0,0 +1,327 @@
+// **********************************************************************
+//
+// 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/HashMap");
+ require("Ice/OptionalFormat");
+
+ var Ice = global.Ice || {};
+
+ var Class = Ice.Class;
+ var defineProperty = Object.defineProperty;
+
+ var HashMap = Ice.HashMap;
+ var OptionalFormat = Ice.OptionalFormat;
+
+ var StreamHelpers = {};
+
+ StreamHelpers.FSizeOptHelper = function()
+ {
+ this.writeOpt = function(os, tag, v)
+ {
+ if(v !== undefined && os.writeOpt(tag, OptionalFormat.FSize))
+ {
+ var pos = os.startSize();
+ this.write(os, v);
+ os.endSize(pos);
+ }
+ };
+
+ this.readOpt = function(is, tag)
+ {
+ var v;
+ if(is.readOpt(tag, OptionalFormat.FSize))
+ {
+ is.skip(4);
+ v = this.read(is);
+ }
+ return v;
+ };
+ };
+
+ StreamHelpers.VSizeOptHelper = function()
+ {
+ this.writeOpt = function(os, tag, v)
+ {
+ if(v !== undefined && os.writeOpt(tag, OptionalFormat.VSize))
+ {
+ os.writeSize(this.minWireSize);
+ this.write(os, v);
+ }
+ };
+
+ this.readOpt = function(is, tag)
+ {
+ var v;
+ if(is.readOpt(tag, OptionalFormat.VSize))
+ {
+ is.skipSize();
+ v = this.read(is);
+ }
+ return v;
+ };
+ };
+
+ StreamHelpers.VSizeContainerOptHelper = function(elementSize)
+ {
+ this.writeOpt = function(os, tag, v)
+ {
+ if(v !== undefined && os.writeOpt(tag, OptionalFormat.VSize))
+ {
+ var sz = this.size(v);
+ os.writeSize(sz > 254 ? sz * elementSize + 5 : sz * elementSize + 1);
+ this.write(os, v);
+ }
+ };
+
+ this.readOpt = function(is, tag)
+ {
+ var v;
+ if(is.readOpt(tag, OptionalFormat.VSize))
+ {
+ is.skipSize();
+ v = this.read(is);
+ }
+ return v;
+ };
+ };
+
+ StreamHelpers.VSizeContainer1OptHelper = function()
+ {
+ this.writeOpt = function(os, tag, v)
+ {
+ if(v !== undefined && os.writeOpt(tag, OptionalFormat.VSize))
+ {
+ this.write(os, v);
+ }
+ };
+
+ this.readOpt = function(is, tag)
+ {
+ var v;
+ if(is.readOpt(tag, OptionalFormat.VSize))
+ {
+ v = this.read(is);
+ }
+ return v;
+ };
+ };
+
+ //
+ // Sequence helper to write sequences
+ //
+ var SequenceHelper = Class({
+ write: function(os, v)
+ {
+ if(v === null || v.length === 0)
+ {
+ os.writeSize(0);
+ }
+ else
+ {
+ var helper = this.elementHelper;
+ os.writeSize(v.length);
+ for(var i = 0; i < v.length; ++i)
+ {
+ helper.write(os, v[i]);
+ }
+ }
+ },
+ read: function(is)
+ {
+ var helper = this.elementHelper; // Cache the element helper.
+ var sz = is.readAndCheckSeqSize(helper.minWireSize);
+ var v = [];
+ v.length = sz;
+ for(var i = 0; i < sz; ++i)
+ {
+ v[i] = helper.read(is);
+ }
+ return v;
+ },
+ size: function(v)
+ {
+ return (v === null || v === undefined) ? 0 : v.length;
+ }
+ });
+
+ defineProperty(SequenceHelper.prototype, "minWireSize", {
+ get: function(){ return 1; }
+ });
+
+ // Speacialization optimized for ByteSeq
+ var byteSeqHelper = new SequenceHelper();
+ byteSeqHelper.write = function(os, v) { return os.writeByteSeq(v); };
+ byteSeqHelper.read = function(is) { return is.readByteSeq(); };
+ defineProperty(byteSeqHelper, "elementHelper", {
+ get: function(){ return Ice.ByteHelper; }
+ });
+ StreamHelpers.VSizeContainer1OptHelper.call(byteSeqHelper);
+
+ // Read method for object sequences
+ var objectSequenceHelperRead = function(is)
+ {
+ var sz = is.readAndCheckSeqSize(1);
+ var v = [];
+ v.length = sz;
+ var elementType = this.elementType;
+ var readObjectAtIndex = function(idx)
+ {
+ is.readObject(function(obj) { v[idx] = obj; }, elementType);
+ };
+
+ for(var i = 0; i < sz; ++i)
+ {
+ readObjectAtIndex(i);
+ }
+ return v;
+ };
+
+ StreamHelpers.generateSeqHelper = function(elementHelper, fixed, elementType)
+ {
+ if(elementHelper === Ice.ByteHelper)
+ {
+ return byteSeqHelper;
+ }
+
+ var helper = new SequenceHelper();
+ if(fixed)
+ {
+ if(elementHelper.minWireSize === 1)
+ {
+ StreamHelpers.VSizeContainer1OptHelper.call(helper);
+ }
+ else
+ {
+ StreamHelpers.VSizeContainerOptHelper.call(helper, elementHelper.minWireSize);
+ }
+ }
+ else
+ {
+ StreamHelpers.FSizeOptHelper.call(helper);
+ }
+
+ defineProperty(helper, "elementHelper", {
+ get: function(){ return elementHelper; }
+ });
+
+ if(elementHelper == Ice.ObjectHelper)
+ {
+ defineProperty(helper, "elementType", {
+ get: function(){ return elementType; }
+ });
+ helper.read = objectSequenceHelperRead;
+ }
+
+ return helper;
+ };
+
+ //
+ // Dictionary helper to write dictionaries
+ //
+ var DictionaryHelper = Class({
+ write: function(os, v)
+ {
+ if(v === null || v.size === 0)
+ {
+ os.writeSize(0);
+ }
+ else
+ {
+ var keyHelper = this.keyHelper;
+ var valueHelper = this.valueHelper;
+ os.writeSize(v.size);
+ for(var e = v.entries; e !== null; e = e.next)
+ {
+ keyHelper.write(os, e.key);
+ valueHelper.write(os, e.value);
+ }
+ }
+ },
+ read: function(is)
+ {
+ var mapType = this.mapType;
+ var v = new mapType();
+ var sz = is.readSize();
+ var keyHelper = this.keyHelper;
+ var valueHelper = this.valueHelper;
+ for(var i = 0; i < sz; ++i)
+ {
+ v.set(keyHelper.read(is), valueHelper.read(is));
+ }
+ return v;
+ },
+ size: function(v)
+ {
+ return (v === null || v === undefined) ? 0 : v.size;
+ }
+ });
+
+ Object.defineProperty(DictionaryHelper.prototype, "minWireSize", {
+ get: function(){ return 1; }
+ });
+
+ // Read method for dictionaries of objects
+ var objectDictionaryHelperRead = function(is)
+ {
+ var sz = is.readSize();
+ var mapType = this.mapType;
+ var v = new mapType();
+ var valueType = this.valueType;
+
+ var readObjectForKey = function(key)
+ {
+ is.readObject(function(obj) { v.set(key, obj); }, valueType);
+ };
+
+ var keyHelper = this.keyHelper;
+ for(var i = 0; i < sz; ++i)
+ {
+ readObjectForKey(keyHelper.read(is));
+ }
+ return v;
+ };
+
+ StreamHelpers.generateDictHelper = function(keyHelper, valueHelper, fixed, valueType, mapType)
+ {
+ var helper = new DictionaryHelper();
+ if(fixed)
+ {
+ StreamHelpers.VSizeContainerOptHelper.call(helper, keyHelper.minWireSize + valueHelper.minWireSize);
+ }
+ else
+ {
+ StreamHelpers.FSizeOptHelper.call(helper);
+ }
+ defineProperty(helper, "mapType", {
+ get: function(){ return mapType; }
+ });
+ defineProperty(helper, "keyHelper", {
+ get: function(){ return keyHelper; }
+ });
+ defineProperty(helper, "valueHelper", {
+ get: function(){ return valueHelper; }
+ });
+
+ if(valueHelper == Ice.ObjectHelper)
+ {
+ defineProperty(helper, "valueType", {
+ get: function(){ return valueType; }
+ });
+ helper.read = objectDictionaryHelperRead;
+ }
+
+ return helper;
+ };
+
+ Ice.StreamHelpers = StreamHelpers;
+
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/StringUtil.js b/js/src/Ice/StringUtil.js
new file mode 100644
index 00000000000..f7866d3d92a
--- /dev/null
+++ b/js/src/Ice/StringUtil.js
@@ -0,0 +1,490 @@
+// **********************************************************************
+//
+// 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/Debug");
+
+ var Ice = global.Ice || {};
+
+ var Debug = Ice.Debug;
+
+ var StringUtil = {};
+
+ //
+ // Return the index of the first character in str to
+ // appear in match, starting from start. Returns -1 if none is
+ // found.
+ //
+ StringUtil.findFirstOf = function(str, match, start)
+ {
+ start = start === undefined ? 0 : start;
+
+ var len = str.length;
+ for(var i = start; i < len; i++)
+ {
+ var ch = str.charAt(i);
+ if(match.indexOf(ch) != -1)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ };
+
+ //
+ // Return the index of the first character in str which does
+ // not appear in match, starting from start. Returns -1 if none is
+ // found.
+ //
+ StringUtil.findFirstNotOf = function(str, match, start)
+ {
+ start = start === undefined ? 0 : start;
+
+ var len = str.length;
+ for(var i = start; i < len; i++)
+ {
+ var ch = str.charAt(i);
+ if(match.indexOf(ch) == -1)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ };
+
+ //
+ // Write the byte b as an escape sequence if it isn't a printable ASCII
+ // character and append the escape sequence to sb. Additional characters
+ // that should be escaped can be passed in special. If b is any of these
+ // characters, b is preceded by a backslash in sb.
+ //
+ function encodeChar(b, sb, special)
+ {
+ switch(b)
+ {
+ case 92: // '\\'
+ {
+ sb.push("\\\\");
+ break;
+ }
+ case 39: // '\''
+ {
+ sb.push("\\'");
+ break;
+ }
+ case 34: // '"'
+ {
+ sb.push("\\\"");
+ break;
+ }
+ case 8: // '\b'
+ {
+ sb.push("\\b");
+ break;
+ }
+ case 12: // '\f'
+ {
+ sb.push("\\f");
+ break;
+ }
+ case 10: // '\n'
+ {
+ sb.push("\\n");
+ break;
+ }
+ case 13: // '\r'
+ {
+ sb.push("\\r");
+ break;
+ }
+ case 9: // '\t'
+ {
+ sb.push("\\t");
+ break;
+ }
+ default:
+ {
+ if(!(b >= 32 && b <= 126))
+ {
+ sb.push('\\');
+ var octal = b.toString(8);
+ //
+ // Add leading zeroes so that we avoid problems during
+ // decoding. For example, consider the encoded string
+ // \0013 (i.e., a character with value 1 followed by
+ // the character '3'). If the leading zeroes were omitted,
+ // the result would be incorrectly interpreted by the
+ // decoder as a single character with value 11.
+ //
+ for(var j = octal.length; j < 3; j++)
+ {
+ sb.push('0');
+ }
+ sb.push(octal);
+ }
+ else
+ {
+ var c = String.fromCharCode(b);
+ if(special !== null && special.indexOf(c) !== -1)
+ {
+ sb.push('\\');
+ sb.push(c);
+ }
+ else
+ {
+ sb.push(c);
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Add escape sequences (such as "\n", or "\007") to make a string
+ // readable in ASCII. Any characters that appear in special are
+ // prefixed with a backlash in the returned string.
+ //
+ StringUtil.escapeString = function(s, special)
+ {
+ special = special === undefined ? null : special;
+
+ var i, length;
+ if(special !== null)
+ {
+ for(i = 0, length = special.length; i < length; ++i)
+ {
+ if(special.charCodeAt(i) < 32 || special.charCodeAt(i) > 126)
+ {
+ throw new Error("special characters must be in ASCII range 32-126");
+ }
+ }
+ }
+
+ var result = [], c;
+ for(i = 0, length = s.length; i < length; ++i)
+ {
+ c = s.charCodeAt(i);
+ if(c < 128)
+ {
+ encodeChar(c, result, special);
+ }
+ else if(c > 127 && c < 2048)
+ {
+ encodeChar((c >> 6) | 192, result, special);
+ encodeChar((c & 63) | 128, result, special);
+ }
+ else
+ {
+ encodeChar((c >> 12) | 224, result, special);
+ encodeChar(((c >> 6) & 63) | 128, result, special);
+ encodeChar((c & 63) | 128, result, special);
+ }
+ }
+
+ return result.join("");
+ };
+
+ function checkChar(s, pos)
+ {
+ var n = s.charCodeAt(pos);
+ if(!(n >= 32 && n <= 126))
+ {
+ var msg;
+ if(pos > 0)
+ {
+ msg = "character after `" + s.substring(0, pos) + "'";
+ }
+ else
+ {
+ msg = "first character";
+ }
+ msg += " is not a printable ASCII character (ordinal " + n + ")";
+ throw new Error(msg);
+ }
+ return n;
+ }
+
+ //
+ // Decode the character or escape sequence starting at start and return it.
+ // nextStart is set to the index of the first character following the decoded
+ // character or escape sequence.
+ //
+ function decodeChar(s, start, end, nextStart)
+ {
+ Debug.assert(start >= 0);
+ Debug.assert(end <= s.length);
+
+ if(start >= end)
+ {
+ throw new Error("EOF while decoding string");
+ }
+
+ var c;
+
+ if(s.charAt(start) != '\\')
+ {
+ c = checkChar(s, start++);
+ }
+ else
+ {
+ if(start + 1 == end)
+ {
+ throw new Error("trailing backslash");
+ }
+ switch(s.charAt(++start))
+ {
+ case '\\':
+ case '\'':
+ case '"':
+ {
+ c = s.charCodeAt(start++);
+ break;
+ }
+ case 'b':
+ {
+ ++start;
+ c = "\b".charCodeAt(0);
+ break;
+ }
+ case 'f':
+ {
+ ++start;
+ c = "\f".charCodeAt(0);
+ break;
+ }
+ case 'n':
+ {
+ ++start;
+ c = "\n".charCodeAt(0);
+ break;
+ }
+ case 'r':
+ {
+ ++start;
+ c = "\r".charCodeAt(0);
+ break;
+ }
+ case 't':
+ {
+ ++start;
+ c = "\t".charCodeAt(0);
+ break;
+ }
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ var octalChars = "01234567";
+ var val = 0;
+ for(var j = 0; j < 3 && start < end; ++j)
+ {
+ var ch = s.charAt(start++);
+ if(octalChars.indexOf(ch) == -1)
+ {
+ --start;
+ break;
+ }
+ val = val * 8 + parseInt(ch);
+ }
+ if(val > 255)
+ {
+ var msg = "octal value \\" + val.toString(8) + " (" + val + ") is out of range";
+ throw new Error(msg);
+ }
+ c = val;
+ break;
+ }
+ default:
+ {
+ c = checkChar(s, start++);
+ break;
+ }
+ }
+ }
+ nextStart.value = start;
+ return c;
+ }
+
+ //
+ // Remove escape sequences from s and append the result to sb.
+ // Return true if successful, false otherwise.
+ //
+ function decodeString(s, start, end, arr)
+ {
+ var nextStart = { 'value': 0 }, c, c2, c3;
+ while(start < end)
+ {
+ c = decodeChar(s, start, end, nextStart);
+ start = nextStart.value;
+
+ if(c < 128)
+ {
+ arr.push(String.fromCharCode(c));
+ }
+ else if(c > 191 && c < 224)
+ {
+ c2 = decodeChar(s, start, end, nextStart);
+ start = nextStart.value;
+ arr.push(String.fromCharCode(((c & 31) << 6) | (c2 & 63)));
+ }
+ else
+ {
+ c2 = decodeChar(s, start, end, nextStart);
+ start = nextStart.value;
+ c3 = decodeChar(s, start, end, nextStart);
+ start = nextStart.value;
+ arr.push(String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)));
+ }
+ }
+ }
+
+ //
+ // Remove escape sequences added by escapeString. Throws Error
+ // for an invalid input string.
+ //
+ StringUtil.unescapeString = function(s, start, end)
+ {
+ start = start === undefined ? 0 : start;
+ end = end === undefined ? s.length : end;
+
+ Debug.assert(start >= 0 && start <= end && end <= s.length);
+
+ var arr = [];
+ decodeString(s, start, end, arr);
+
+ return arr.join("");
+ };
+
+ //
+ // Split string helper; returns null for unmatched quotes
+ //
+ StringUtil.splitString = function(str, delim)
+ {
+ var v = [];
+ var s = "";
+ var pos = 0;
+
+ var quoteChar = null;
+ while(pos < str.length)
+ {
+ if(quoteChar === null && (str.charAt(pos) === '"' || str.charAt(pos) === '\''))
+ {
+ quoteChar = str.charAt(pos++);
+ continue; // Skip the quote.
+ }
+ else if(quoteChar === null && str.charAt(pos) === '\\' && pos + 1 < str.length &&
+ (str.charAt(pos + 1) === '"' || str.charAt(pos + 1) === '\''))
+ {
+ ++pos; // Skip the backslash
+ }
+ else if(quoteChar !== null && str.charAt(pos) === '\\' && pos + 1 < str.length &&
+ str.charAt(pos + 1) === quoteChar)
+ {
+ ++pos; // Skip the backslash
+ }
+ else if(quoteChar !== null && str.charAt(pos) === quoteChar)
+ {
+ ++pos;
+ quoteChar = null;
+ continue; // Skip the quote.
+ }
+ else if(delim.indexOf(str.charAt(pos)) !== -1)
+ {
+ if(quoteChar === null)
+ {
+ ++pos;
+ if(s.length > 0)
+ {
+ v.push(s);
+ s = "";
+ }
+ continue;
+ }
+ }
+
+ if(pos < str.length)
+ {
+ s += str.charAt(pos++);
+ }
+ }
+
+ if(s.length > 0)
+ {
+ v.push(s);
+ }
+ if(quoteChar !== null)
+ {
+ return null; // Unmatched quote.
+ }
+
+ return v;
+ };
+
+ //
+ // If a single or double quotation mark is found at the start position,
+ // then the position of the matching closing quote is returned. If no
+ // quotation mark is found at the start position, then 0 is returned.
+ // If no matching closing quote is found, then -1 is returned.
+ //
+ StringUtil.checkQuote = function(s, start)
+ {
+ start = start === undefined ? 0 : start;
+
+ var quoteChar = s.charAt(start);
+ if(quoteChar == '"' || quoteChar == '\'')
+ {
+ start++;
+ var len = s.length;
+ var pos;
+ while(start < len && (pos = s.indexOf(quoteChar, start)) != -1)
+ {
+ if(s.charAt(pos - 1) != '\\')
+ {
+ return pos;
+ }
+ start = pos + 1;
+ }
+ return -1; // Unmatched quote
+ }
+ return 0; // Not quoted
+ };
+
+ StringUtil.hashCode = function(s)
+ {
+ var hash = 0;
+ var n = s.length;
+
+ for(var i = 0; i < n; i++)
+ {
+ hash = 31 * hash + s.charCodeAt(i);
+ }
+
+ return hash;
+ };
+
+ StringUtil.toInt = function(s)
+ {
+ var n = parseInt(s, 10);
+ if(isNaN(n))
+ {
+ throw new Error("conversion of `" + s + "' to int failed");
+ }
+ return n;
+ };
+
+ Ice.StringUtil = StringUtil;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Struct.js b/js/src/Ice/Struct.js
new file mode 100644
index 00000000000..99a882089c5
--- /dev/null
+++ b/js/src/Ice/Struct.js
@@ -0,0 +1,207 @@
+// **********************************************************************
+//
+// 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/HashUtil");
+ require("Ice/ArrayUtil");
+ require("Ice/HashMap");
+ require("Ice/StreamHelpers");
+
+ var Slice = global.Slice || {};
+ var Ice = global.Ice || {};
+
+ var ArrayUtil = Ice.ArrayUtil;
+
+ var eq = function(e1, e2)
+ {
+ if(e1 === e2)
+ {
+ return true; // If identity compare equals members are equal.
+ }
+ else if(e1 === null || e1 === undefined || e2 === null || e2 === undefined)
+ {
+ return false;
+ }
+ else if(e1.prototype !== e2.prototype)
+ {
+ return false;
+ }
+ else if(e1 instanceof Ice.HashMap)
+ {
+ return e1.equals(e2);
+ }
+ else if(typeof e1.equals == "function")
+ {
+ return e1.equals(e2);
+ }
+ else if(e1 instanceof Array)
+ {
+ return ArrayUtil.equals(e1, e2, eq);
+ }
+ return false;
+ };
+
+ var equals = function(other)
+ {
+ if(this === other)
+ {
+ return true;
+ }
+
+ if(other === null || other === undefined)
+ {
+ return false;
+ }
+
+ if(this.prototype !== other.prototype)
+ {
+ return false;
+ }
+
+ var e1, e2;
+ for(var key in this)
+ {
+
+ e1 = this[key];
+ e2 = other[key];
+ if(typeof e1 == "function")
+ {
+ continue; // Don't need to compare functions
+ }
+ else if(!eq(e1, e2))
+ {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ var clone = function()
+ {
+ var other = new this.constructor();
+ var e;
+ for(var key in this)
+ {
+ e = this[key];
+ if(e === undefined || e === null)
+ {
+ other[key] = e;
+ }
+ else if(typeof e == "function")
+ {
+ continue;
+ }
+ else if(typeof e.clone == "function")
+ {
+ other[key] = e.clone();
+ }
+ else if(e instanceof Array)
+ {
+ other[key] = ArrayUtil.clone(e);
+ }
+ else
+ {
+ other[key] = e;
+ }
+ }
+ return other;
+ };
+
+ var memberHashCode = function(h, e)
+ {
+ if(typeof e.hashCode == "function")
+ {
+ return Ice.HashUtil.addHashable(h, e);
+ }
+ else if(e instanceof Array)
+ {
+ return Ice.HashUtil.addArray(h, e, memberHashCode);
+ }
+ else
+ {
+ var t = typeof(e);
+ if(e instanceof String || t == "string")
+ {
+ return Ice.HashUtil.addString(h, e);
+ }
+ else if(e instanceof Number || t == "number")
+ {
+ return Ice.HashUtil.addNumber(h, e);
+ }
+ else if(e instanceof Boolean || t == "boolean")
+ {
+ return Ice.HashUtil.addBoolean(h, e);
+ }
+ }
+ };
+
+ var hashCode = function()
+ {
+ var __h = 5381;
+ var e;
+ for(var key in this)
+ {
+ e = this[key];
+ if(e === undefined || e === null || typeof e == "function")
+ {
+ continue;
+ }
+ __h = memberHashCode(__h, e);
+ }
+ return __h;
+ };
+
+ Slice.defineStruct = function(constructor, legalKeyType, writeImpl, readImpl, minWireSize, fixed)
+ {
+ var obj = constructor;
+
+ obj.prototype.clone = clone;
+
+ obj.prototype.equals = equals;
+
+ //
+ // Only generate hashCode if this structure type is a legal dictionary key type.
+ //
+ if(legalKeyType)
+ {
+ obj.prototype.hashCode = hashCode;
+ }
+
+ if(readImpl && writeImpl)
+ {
+ obj.prototype.__write = writeImpl;
+ obj.prototype.__read = readImpl;
+ obj.write = function(os, v)
+ {
+ v.__write(os);
+ };
+ obj.read = function(is)
+ {
+ var v = new this();
+ v.__read(is);
+ return v;
+ };
+ Object.defineProperty(obj, "minWireSize", {
+ get: function() { return minWireSize; }
+ });
+ if(fixed)
+ {
+ Ice.StreamHelpers.VSizeOptHelper.call(obj);
+ }
+ else
+ {
+ Ice.StreamHelpers.FSizeOptHelper.call(obj);
+ }
+ }
+ return obj;
+ };
+
+ global.Slice = Slice;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/TcpEndpointFactory.js b/js/src/Ice/TcpEndpointFactory.js
new file mode 100644
index 00000000000..d459685efb5
--- /dev/null
+++ b/js/src/Ice/TcpEndpointFactory.js
@@ -0,0 +1,49 @@
+// **********************************************************************
+//
+// 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/TcpEndpointI");
+ require("Ice/Endpoint");
+
+ var Ice = global.Ice || {};
+
+ var TcpEndpointI = Ice.TcpEndpointI;
+ var TCPEndpointType = Ice.TCPEndpointType;
+
+ var TcpEndpointFactory = Ice.Class({
+ __init__: function(instance)
+ {
+ this._instance = instance;
+ },
+ type: function()
+ {
+ return TCPEndpointType;
+ },
+ protocol: function()
+ {
+ return "tcp";
+ },
+ create: function(str, oaEndpoint)
+ {
+ return TcpEndpointI.fromString(this._instance, str, oaEndpoint);
+ },
+ read: function(s)
+ {
+ return TcpEndpointI.fromStream(s);
+ },
+ destroy: function()
+ {
+ this._instance = null;
+ }
+ });
+
+ Ice.TcpEndpointFactory = TcpEndpointFactory;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/TcpEndpointI.js b/js/src/Ice/TcpEndpointI.js
new file mode 100644
index 00000000000..97851850877
--- /dev/null
+++ b/js/src/Ice/TcpEndpointI.js
@@ -0,0 +1,496 @@
+// **********************************************************************
+//
+// 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/Address");
+ require("Ice/HashUtil");
+ require("Ice/StringUtil");
+ require("Ice/TcpTransceiver");
+ require("Ice/Endpoint");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var Address = Ice.Address;
+ var HashUtil = Ice.HashUtil;
+ var StringUtil = Ice.StringUtil;
+ var TcpTransceiver = Ice.TcpTransceiver;
+
+ var Class = Ice.Class;
+ var TcpEndpointI = Class(Ice.Endpoint, {
+ __init__: function(instance, ho, po, ti, conId, co)
+ {
+ this._instance = instance;
+ this._host = ho;
+ this._port = po;
+ this._timeout = ti;
+ this._connectionId = conId;
+ this._compress = co;
+ this.calcHashValue();
+ },
+ //
+ // Convert the endpoint to its string form
+ //
+ toString: function()
+ {
+ //
+ // WARNING: Certain features, such as proxy validation in Glacier2,
+ // depend on the format of proxy strings. Changes to toString() and
+ // methods called to generate parts of the reference string could break
+ // these features. Please review for all features that depend on the
+ // format of proxyToString() before changing this and related code.
+ //
+ var s = "tcp";
+
+ if(this._host !== null && this._host.length > 0)
+ {
+ s += " -h ";
+ var addQuote = this._host.indexOf(':') != -1;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ s += this._host;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ }
+
+ s += " -p " + this._port;
+
+ if(this._timeout != -1)
+ {
+ s += " -t " + this._timeout;
+ }
+ if(this._compress)
+ {
+ s += " -z";
+ }
+ return s;
+ },
+ //
+ // Return the endpoint information.
+ //
+ getInfo: function()
+ {
+ return new TCPEndpointInfoI(this._timeout, this._compress, this._host, this._port);
+ },
+ //
+ // Marshal the endpoint
+ //
+ streamWrite: function(s)
+ {
+ s.writeShort(Ice.TCPEndpointType);
+ s.startWriteEncaps();
+ s.writeString(this._host);
+ s.writeInt(this._port);
+ s.writeInt(this._timeout);
+ s.writeBool(this._compress);
+ s.endWriteEncaps();
+ },
+ //
+ // Return the endpoint type
+ //
+ type: function()
+ {
+ return Ice.TCPEndpointType;
+ },
+ //
+ // Return the timeout for the endpoint in milliseconds. 0 means
+ // non-blocking, -1 means no timeout.
+ //
+ timeout: function()
+ {
+ return this._timeout;
+ },
+ //
+ // Return a new endpoint with a different timeout value, provided
+ // that timeouts are supported by the endpoint. Otherwise the same
+ // endpoint is returned.
+ //
+ changeTimeout: function(timeout)
+ {
+ if(timeout === this._timeout)
+ {
+ return this;
+ }
+ else
+ {
+ return new TcpEndpointI(this._instance, this._host, this._port, timeout, this._connectionId,
+ this._compress);
+ }
+ },
+ //
+ // Return a new endpoint with a different connection id.
+ //
+ changeConnectionId: function(connectionId)
+ {
+ if(connectionId === this._connectionId)
+ {
+ return this;
+ }
+ else
+ {
+ return new TcpEndpointI(this._instance, this._host, this._port, this._timeout, connectionId,
+ this._compress);
+ }
+ },
+ //
+ // Return true if the endpoints support bzip2 compress, or false
+ // otherwise.
+ //
+ compress: function()
+ {
+ return this._compress;
+ },
+ //
+ // Return a new endpoint with a different compression value,
+ // provided that compression is supported by the
+ // endpoint. Otherwise the same endpoint is returned.
+ //
+ changeCompress: function(compress)
+ {
+ if(compress === this._compress)
+ {
+ return this;
+ }
+ else
+ {
+ return new TcpEndpointI(this._instance, this._host, this._port, this._timeout, this._connectionId,
+ compress);
+ }
+ },
+ //
+ // Return true if the endpoint is datagram-based.
+ //
+ datagram: function()
+ {
+ return false;
+ },
+ //
+ // Return true if the endpoint is secure.
+ //
+ secure: function()
+ {
+ return false;
+ },
+ //
+ // Return a server side transceiver for this endpoint, or null if a
+ // transceiver can only be created by an acceptor. In case a
+ // transceiver is created, this operation also returns a new
+ // "effective" endpoint, which might differ from this endpoint,
+ // for example, if a dynamic port number is assigned.
+ //
+ transceiver: function(endpoint)
+ {
+ endpoint.value = this;
+ return null;
+ },
+ connect: function()
+ {
+ if(this._instance.traceLevels().network >= 2)
+ {
+ var msg = "trying to establish tcp connection to " + this._host + ":" + this._port;
+ this._instance.initializationData().logger.trace(this._instance.traceLevels().networkCat, msg);
+ }
+
+ return TcpTransceiver.createOutgoing(this._instance, new Address(this._host, this._port));
+ },
+ hashCode: function()
+ {
+ return this._hashCode;
+ },
+ //
+ // Compare endpoints for sorting purposes
+ //
+ equals: function(p)
+ {
+ if(!(p instanceof TcpEndpointI))
+ {
+ return false;
+ }
+
+ if(this === p)
+ {
+ return true;
+ }
+
+ if(this._host !== p._host)
+ {
+ return false;
+ }
+
+ if(this._port !== p._port)
+ {
+ return false;
+ }
+
+ if(this._timeout !== p._timeout)
+ {
+ return false;
+ }
+
+ if(this._connectionId !== p._connectionId)
+ {
+ return false;
+ }
+
+ if(this._compress !== p._compress)
+ {
+ return false;
+ }
+
+ return true;
+ },
+ compareTo: function(p)
+ {
+ if(this === p)
+ {
+ return 0;
+ }
+
+ if(p === null)
+ {
+ return 1;
+ }
+
+ if(!(p instanceof TcpEndpointI))
+ {
+ return this.type() < p.type() ? -1 : 1;
+ }
+
+ if(this._port < p._port)
+ {
+ return -1;
+ }
+ else if(p._port < this._port)
+ {
+ return 1;
+ }
+
+ if(this._timeout < p._timeout)
+ {
+ return -1;
+ }
+ else if(p._timeout < this._timeout)
+ {
+ return 1;
+ }
+
+ if(this._connectionId != p._connectionId)
+ {
+ return this._connectionId < p._connectionId ? -1 : 1;
+ }
+
+ if(!this._compress && p._compress)
+ {
+ return -1;
+ }
+ else if(!p._compress && this._compress)
+ {
+ return 1;
+ }
+
+ if(this._host == p._host)
+ {
+ return 0;
+ }
+ else
+ {
+ return this._host < p._host ? -1 : 1;
+ }
+ },
+ calcHashValue: function()
+ {
+ var h = 5381;
+ h = HashUtil.addNumber(h, Ice.TCPEndpointType);
+ h = HashUtil.addString(h, this._host);
+ h = HashUtil.addNumber(h, this._port);
+ h = HashUtil.addNumber(h, this._timeout);
+ h = HashUtil.addString(h, this._connectionId);
+ h = HashUtil.addBoolean(h, this._compress);
+ this._hashCode = h;
+ }
+ });
+
+ TcpEndpointI.fromString = function(instance, str, oaEndpoint)
+ {
+ var host = null;
+ var port = 0;
+ var timeout = -1;
+ var compress = false;
+
+ var arr = str.split(/[ \t\n\r]+/);
+
+ var i = 0;
+ while(i < arr.length)
+ {
+ if(arr[i].length === 0)
+ {
+ i++;
+ continue;
+ }
+
+ var option = arr[i++];
+ if(option.length != 2 && option.charAt(0) != '-')
+ {
+ throw new Ice.EndpointParseException("expected an endpoint option but found `" + option +
+ "' in endpoint `tcp " + str + "'");
+ }
+
+ var argument = null;
+ if(i < arr.length && arr[i].charAt(0) != '-')
+ {
+ argument = arr[i++];
+ if(argument.charAt(0) == '\"' && argument.charAt(argument.length - 1) == '\"')
+ {
+ argument = argument.substring(1, argument.length - 1);
+ }
+ }
+
+ switch(option.charAt(1))
+ {
+ case 'h':
+ {
+ if(argument === null)
+ {
+ throw new Ice.EndpointParseException(
+ "no argument provided for -h option in endpoint `tcp " + str + "'");
+ }
+
+ host = argument;
+ break;
+ }
+
+ case 'p':
+ {
+ if(argument === null)
+ {
+ throw new Ice.EndpointParseException(
+ "no argument provided for -p option in endpoint `tcp " + str + "'");
+ }
+
+ try
+ {
+ port = StringUtil.toInt(argument);
+ }
+ catch(ex)
+ {
+ throw new Ice.EndpointParseException("invalid port value `" + argument +
+ "' in endpoint `tcp " + str + "'");
+ }
+
+ if(port < 0 || port > 65535)
+ {
+ throw new Ice.EndpointParseException("port value `" + argument +
+ "' out of range in endpoint `tcp " + str + "'");
+ }
+
+ break;
+ }
+
+ case 't':
+ {
+ if(argument === null)
+ {
+ throw new Ice.EndpointParseException(
+ "no argument provided for -t option in endpoint `tcp " + str + "'");
+ }
+
+ try
+ {
+ timeout = StringUtil.toInt(argument);
+ }
+ catch(ex)
+ {
+ throw new Ice.EndpointParseException(
+ "invalid timeout value `" + argument + "' in endpoint `tcp " + str + "'");
+ }
+
+ break;
+ }
+
+ case 'z':
+ {
+ if(argument !== null)
+ {
+ throw new Ice.EndpointParseException("unexpected argument `" + argument +
+ "' provided for -z option in `tcp " + str + "'");
+ }
+
+ compress = true;
+ break;
+ }
+
+ default:
+ {
+ throw new Ice.EndpointParseException("unknown option `" + option + "' in `tcp " + str + "'");
+ }
+ }
+ }
+
+ if(host === null)
+ {
+ host = instance.defaultsAndOverrides().defaultHost;
+ }
+ else if(host == "*")
+ {
+ if(oaEndpoint)
+ {
+ host = null;
+ }
+ else
+ {
+ throw new Ice.EndpointParseException("`-h *' not valid for proxy endpoint `tcp " + str + "'");
+ }
+ }
+
+ if(host === null)
+ {
+ host = "";
+ }
+
+ return new TcpEndpointI(instance, host, port, timeout, "", compress);
+ };
+
+ TcpEndpointI.fromStream = function(s)
+ {
+ s.startReadEncaps();
+ var host = s.readString();
+ var port = s.readInt();
+ var timeout = s.readInt();
+ var compress = s.readBool();
+ s.endReadEncaps();
+ return new TcpEndpointI(s.instance, host, port, timeout, "", compress);
+ };
+
+ Ice.TcpEndpointI = TcpEndpointI;
+ global.Ice = Ice;
+
+ var TCPEndpointInfoI = Class(Ice.TCPEndpointInfo, {
+ __init__: function(timeout, compress, host, port)
+ {
+ Ice.TCPEndpointInfo.call(this, timeout, compress, host, port);
+ },
+ type: function()
+ {
+ return Ice.TCPEndpointType;
+ },
+ datagram: function()
+ {
+ return false;
+ },
+ secure: function()
+ {
+ return false;
+ }
+ });
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/TcpTransceiver.js b/js/src/Ice/TcpTransceiver.js
new file mode 100644
index 00000000000..a6a4615297c
--- /dev/null
+++ b/js/src/Ice/TcpTransceiver.js
@@ -0,0 +1,458 @@
+// **********************************************************************
+//
+// 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){
+ var net = require("net");
+
+ require("Ice/Class");
+ require("Ice/Debug");
+ require("Ice/ExUtil");
+ require("Ice/SocketOperation");
+ require("Ice/Connection");
+ require("Ice/Exception");
+ require("Ice/LocalException");
+
+ var Ice = global.Ice || {};
+
+ var Debug = Ice.Debug;
+ var ExUtil = Ice.ExUtil;
+ var Network = Ice.Network;
+ var SocketOperation = Ice.SocketOperation;
+ var LocalException = Ice.LocalException;
+ var SocketException = Ice.SocketException;
+
+ var StateNeedConnect = 0;
+ var StateConnectPending = 1;
+ var StateProxyConnectRequest = 2;
+ var StateProxyConnectRequestPending = 3;
+ var StateConnected = 4;
+ var StateClosed = 5;
+
+ var TcpTransceiver = Ice.Class({
+ __init__: function(instance)
+ {
+ this._traceLevels = instance.traceLevels();
+ this._logger = instance.initializationData().logger;
+ this._readBuffers = [];
+ this._readPosition = 0;
+ },
+ setCallbacks: function(connectedCallback, bytesAvailableCallback, bytesWrittenCallback)
+ {
+ this._connectedCallback = connectedCallback;
+ this._bytesAvailableCallback = bytesAvailableCallback;
+ this._bytesWrittenCallback = bytesWrittenCallback;
+
+ var self = this;
+ this._fd.on("connect", function() { self.socketConnected(); });
+ this._fd.on("close", function(err) { self.socketClosed(err); });
+ this._fd.on("error", function(err) { self.socketError(err); });
+ this._fd.on("data", function(buf) { self.socketBytesAvailable(buf); });
+ },
+ //
+ // Returns SocketOperation.None when initialization is complete.
+ //
+ initialize: function(readBuffer, writeBuffer)
+ {
+ try
+ {
+ if(this._exception)
+ {
+ throw this._exception;
+ }
+
+ if(this._state === StateNeedConnect)
+ {
+ this._state = StateConnectPending;
+ this._fd.connect(this._addr.port, this._addr.host);
+ return SocketOperation.Connect; // Waiting for connect to complete.
+ }
+ else if(this._state === StateConnectPending)
+ {
+ //
+ // Socket is connected.
+ //
+ this._desc = fdToString(this._fd, this._proxy, this._addr);
+ this._state = StateConnected;
+ }
+ else if(this._state === StateProxyConnectRequest)
+ {
+ //
+ // Write completed.
+ //
+ this._proxy.endWriteConnectRequest(writeBuffer);
+ this._state = StateProxyConnectRequestPending; // Wait for proxy response
+ return SocketOperation.Read;
+ }
+ else if(this._state === StateProxyConnectRequestPending)
+ {
+ //
+ // Read completed.
+ //
+ this._proxy.endReadConnectRequestResponse(readBuffer);
+ this._state = StateConnected;
+ }
+ }
+ catch(err)
+ {
+ if(!this._exception)
+ {
+ this._exception = translateError(this._state, err);
+ }
+
+ if(this._traceLevels.network >= 2)
+ {
+ var s = [];
+ s.push("failed to establish tcp connection\n");
+ s.push(fdToString(this._fd, this._proxy, this._addr.host, this._addr.port));
+ this._logger.trace(this._traceLevels.networkCat, s.join(""));
+ }
+
+ throw this._exception;
+ }
+
+ Debug.assert(this._state === StateConnected);
+ if(this._traceLevels.network >= 1)
+ {
+ var s = "tcp connection established\n" + this._desc;
+ this._logger.trace(this._traceLevels.networkCat, s);
+ }
+
+ return SocketOperation.None;
+ },
+ register: function()
+ {
+ this._registered = true;
+ this._fd.resume();
+ if(this._exception)
+ {
+ this._bytesAvailableCallback();
+ }
+ },
+ unregister: function()
+ {
+ this._registered = false;
+ this._fd.pause();
+ },
+ close: function()
+ {
+ if(this._state > StateConnectPending && this._traceLevels.network >= 1)
+ {
+ this._logger.trace(this._traceLevels.networkCat, "closing " + this.type() + " connection\n" +
+ this._desc);
+ }
+
+ Debug.assert(this._fd !== null);
+ try
+ {
+ this._fd.destroy();
+ }
+ catch(ex)
+ {
+ throw translateError(this._state, ex);
+ }
+ finally
+ {
+ this._fd = null;
+ }
+ },
+ //
+ // Returns true if all of the data was flushed to the kernel buffer.
+ //
+ write: function(byteBuffer)
+ {
+ if(this._exception)
+ {
+ throw this._exception;
+ }
+
+ var remaining = byteBuffer.remaining;
+ Debug.assert(remaining > 0);
+
+ //
+ // Create a slice of the source buffer representing the remaining data to be written.
+ //
+ var slice = byteBuffer.b.slice(byteBuffer.position, byteBuffer.position + remaining);
+
+ //
+ // The socket will accept all of the data.
+ //
+ byteBuffer.position = byteBuffer.position + remaining;
+
+ var self = this;
+
+ var sync = true;
+ sync = this._fd.write(slice, null, function() {
+ if(self._traceLevels.network >= 3)
+ {
+ var msg = "sent " + remaining + " bytes via " + self.type() + "\n" + self._desc;
+ self._logger.trace(self._traceLevels.networkCat, msg);
+ }
+ if(!sync)
+ {
+ self._bytesWrittenCallback();
+ }
+ });
+ return sync;
+ },
+ read: function(byteBuffer, moreData)
+ {
+ if(this._exception)
+ {
+ throw this._exception;
+ }
+
+ moreData.value = false;
+
+ if(this._readBuffers.length === 0)
+ {
+ return false; // No data available.
+ }
+
+ var avail = this._readBuffers[0].length - this._readPosition;
+ Debug.assert(avail > 0);
+ var remaining = byteBuffer.remaining;
+
+ while(byteBuffer.remaining > 0)
+ {
+ if(avail > byteBuffer.remaining)
+ {
+ avail = byteBuffer.remaining;
+ }
+
+ this._readBuffers[0].copy(byteBuffer.b, byteBuffer.position, this._readPosition,
+ this._readPosition + avail);
+
+ byteBuffer.position += avail;
+ this._readPosition += avail;
+ if(this._readPosition === this._readBuffers[0].length)
+ {
+ //
+ // We've exhausted the current read buffer.
+ //
+ this._readPosition = 0;
+ this._readBuffers.shift();
+ if(this._readBuffers.length === 0)
+ {
+ break; // No more data - we're done.
+ }
+ else
+ {
+ avail = this._readBuffers[0].length;
+ }
+ }
+ }
+
+ var n = remaining - byteBuffer.remaining;
+ if(n > 0 && this._traceLevels.network >= 3)
+ {
+ var msg = "received " + n + " of " + remaining + " bytes via " + this.type() + "\n" + this._desc;
+ this._logger.trace(this._traceLevels.networkCat, msg);
+ }
+
+ moreData.value = this._readBuffers.length > 0;
+
+ return byteBuffer.remaining === 0;
+ },
+ type: function()
+ {
+ return "tcp";
+ },
+ getInfo: function()
+ {
+ Debug.assert(this._fd !== null);
+ var info = this.createInfo();
+ info.localAddress = this._fd.localAddress;
+ info.localPort = this._fd.localPort;
+ info.remoteAddress = this._fd.remoteAddress;
+ info.remotePort = this._fd.remotePort;
+ return info;
+ },
+ createInfo: function()
+ {
+ return new Ice.TCPConnectionInfo();
+ },
+ checkSendSize: function(stream, messageSizeMax)
+ {
+ if(stream.size > messageSizeMax)
+ {
+ ExUtil.throwMemoryLimitException(stream.size, messageSizeMax);
+ }
+ },
+ toString: function()
+ {
+ return this._desc;
+ },
+ socketConnected: function()
+ {
+ Debug.assert(this._connectedCallback !== null);
+ this._connectedCallback();
+ },
+ socketBytesAvailable: function(buf)
+ {
+ Debug.assert(this._bytesAvailableCallback !== null);
+
+ //
+ // TODO: Should we set a limit on how much data we can read?
+ // We can call _fd.pause() to temporarily stop reading.
+ //
+ if(buf.length > 0)
+ {
+ this._readBuffers.push(buf);
+ this._bytesAvailableCallback();
+ }
+ },
+ socketClosed: function(err)
+ {
+ //
+ // Don't call the closed callback if an error occurred; the error callback
+ // will be called.
+ //
+ if(!err)
+ {
+ this.socketError(null);
+ }
+ },
+ socketError: function(err)
+ {
+ this._exception = translateError(this._state, err)
+ if(this._state < StateConnected)
+ {
+ this._connectedCallback();
+ }
+ else if(this._registered)
+ {
+ this._bytesAvailableCallback();
+ }
+ }
+ });
+
+ function fdToString(fd, targetAddr)
+ {
+ if(fd === null)
+ {
+ return "<closed>";
+ }
+
+ return addressesToString(fd.localAddress, fd.localPort, fd.remoteAddress, fd.remotePort, targetAddr);
+ }
+
+ function translateError(state, err)
+ {
+ if(!err)
+ {
+ return new Ice.ConnectionLostException();
+ }
+ else if(state < StateConnected)
+ {
+ if(connectionRefused(err.code))
+ {
+ return new Ice.ConnectionRefusedException(err.code, err);
+ }
+ else if(connectionFailed(err.code))
+ {
+ return new Ice.ConnectFailedException(err.code, err);
+ }
+ }
+ else if(connectionLost(err.code))
+ {
+ return new Ice.ConnectionLostException(err.code, err);
+ }
+ return new Ice.SocketException(err.code, err);
+ }
+
+ function addressesToString(localHost, localPort, remoteHost, remotePort, targetAddr)
+ {
+ remoteHost = remoteHost === undefined ? null : remoteHost;
+ targetAddr = targetAddr === undefined ? null : targetAddr;
+
+ var s = [];
+ s.push("local address = ");
+ s.push(localHost + ":" + localPort);
+
+ if(remoteHost === null && targetAddr !== null)
+ {
+ remoteHost = targetAddr.host;
+ remotePort = targetAddr.port;
+ }
+
+ if(remoteHost === null)
+ {
+ s.push("\nremote address = <not connected>");
+ }
+ else
+ {
+ s.push("\nremote address = ");
+ s.push(remoteHost + ":" + remotePort);
+ }
+
+ return s.join("");
+ };
+
+ TcpTransceiver.createOutgoing = function(instance, addr)
+ {
+ var transceiver = new TcpTransceiver(instance);
+
+ transceiver._fd = new net.Socket();
+ transceiver._addr = addr;
+ transceiver._desc = "remote address: " + addr.host + ":" + addr.port + " <not connected>";
+ transceiver._state = StateNeedConnect;
+ transceiver._registered = false;
+ transceiver._exception = null;
+
+ return transceiver;
+ };
+
+ TcpTransceiver.createIncoming = function(instance, fd)
+ {
+ var transceiver = new TcpTransceiver(instance);
+
+ transceiver._fd = fd;
+ transceiver._addr = null;
+ transceiver._desc = fdToString(fd);
+ transceiver._state = StateConnected;
+ transceiver._registered = false;
+ transceiver._exception = null;
+
+ return transceiver;
+ };
+
+
+ var ECONNABORTED = "ECONNABORTED";
+ var ECONNREFUSED = "ECONNREFUSED";
+ var ECONNRESET = "ECONNRESET"
+ var EHOSTUNREACH = "EHOSTUNREACH";
+ var ENETUNREACH = "ENETUNREACH";
+ var ENOTCONN = "ENOTCONN";
+ var EPIPE = "EPIPE";
+ var ESHUTDOWN = "ESHUTDOWN"
+ var ETIMEDOUT = "ETIMEDOUT";
+
+ function connectionRefused(err)
+ {
+ return err == ECONNREFUSED;
+ }
+
+ function connectionFailed(err)
+ {
+ return err == ECONNREFUSED || err == ETIMEDOUT ||
+ err == ENETUNREACH || err == EHOSTUNREACH ||
+ err == ECONNRESET || err == ESHUTDOWN ||
+ err == ECONNABORTED;
+ }
+
+ function connectionLost(err)
+ {
+ return err == ECONNRESET || err == ENOTCONN ||
+ err == ESHUTDOWN || err == ECONNABORTED ||
+ err == EPIPE;
+ }
+
+ Ice.TcpTransceiver = TcpTransceiver;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/TimeUtil.js b/js/src/Ice/TimeUtil.js
new file mode 100644
index 00000000000..ad152cd7f09
--- /dev/null
+++ b/js/src/Ice/TimeUtil.js
@@ -0,0 +1,19 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+ var TimeUtil = {};
+ TimeUtil.now = function()
+ {
+ return new Date().getTime();
+ };
+ Ice.TimeUtil = TimeUtil;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/Timer.js b/js/src/Ice/Timer.js
new file mode 100644
index 00000000000..0c489726d98
--- /dev/null
+++ b/js/src/Ice/Timer.js
@@ -0,0 +1,123 @@
+// **********************************************************************
+//
+// 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/HashMap");
+ require("Ice/LocalException");
+ require("Ice/Class");
+
+ var Ice = global.Ice || {};
+
+ var HashMap = Ice.HashMap;
+ var CommunicatorDestroyedException = Ice.CommunicatorDestroyedException;
+
+ var Timer = Ice.Class({
+ __init__: function(instance)
+ {
+ this._instance = instance;
+ this._destroyed = false;
+ this._tokenId = 0;
+ this._tokens = new HashMap();
+ },
+ destroy: function()
+ {
+ var self = this;
+ this._tokens.forEach(function(key, value){
+ self.cancel(key);
+ });
+ this._destroyed = true;
+ this._tokens.clear();
+ },
+ schedule: function(callback, delay)
+ {
+ if(this._destroyed)
+ {
+ throw new CommunicatorDestroyedException();
+ }
+
+ var token = this._tokenId++;
+ var self = this;
+
+ var id = setTimeout(function() { self.handleTimeout(token); }, delay);
+ this._tokens.set(token, { callback: callback, id: id, isInterval: false });
+
+ return token;
+ },
+ scheduleRepeated: function(callback, period)
+ {
+ if(this._destroyed)
+ {
+ throw new CommunicatorDestroyedException();
+ }
+
+ var token = this._tokenId++;
+ var self = this;
+
+ var id = setInterval(function() { self.handleInterval(token); }, period);
+ this._tokens.set(token, { callback: callback, id: id, isInterval: true });
+
+ return token;
+ },
+ cancel: function(id)
+ {
+ if(this._destroyed)
+ {
+ return false;
+ }
+
+ var token = this._tokens.get(id);
+ if(token === undefined)
+ {
+ return false;
+ }
+
+ this._tokens.delete(id);
+ if(token.isInterval)
+ {
+ clearInterval(token.id);
+ }
+ else
+ {
+ clearTimeout(token.id);
+ }
+
+ return true;
+ },
+ handleTimeout: function(id)
+ {
+ if(this._destroyed)
+ {
+ return;
+ }
+
+ var token = this._tokens.get(id);
+ if(token !== undefined)
+ {
+ this._tokens.delete(id);
+ token.callback();
+ }
+ },
+ handleInterval: function(id)
+ {
+ if(this._destroyed)
+ {
+ return;
+ }
+
+ var token = this._tokens.get(id);
+ if(token !== undefined)
+ {
+ token.callback();
+ }
+ }
+ });
+
+ Ice.Timer = Timer;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/TraceLevels.js b/js/src/Ice/TraceLevels.js
new file mode 100644
index 00000000000..512813d8b18
--- /dev/null
+++ b/js/src/Ice/TraceLevels.js
@@ -0,0 +1,66 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+
+ var TraceLevels = function(properties)
+ {
+ var networkCat = "Network";
+ var protocolCat = "Protocol";
+ var retryCat = "Retry";
+ var locationCat = "Locator";
+ var slicingCat = "Slicing";
+
+ var keyBase = "Ice.Trace.";
+
+ var network = properties.getPropertyAsInt(keyBase + networkCat);
+ var protocol = properties.getPropertyAsInt(keyBase + protocolCat);
+ var retry = properties.getPropertyAsInt(keyBase + retryCat);
+ var location = properties.getPropertyAsInt(keyBase + locationCat);
+ var slicing = properties.getPropertyAsInt(keyBase + slicingCat);
+ properties.getPropertyAsInt(keyBase + "ThreadPool"); // Avoid an "unused property" warning.
+
+ return Object.create(null, {
+ 'network': {
+ get: function() { return network; }
+ },
+ 'networkCat': {
+ get: function() { return networkCat; }
+ },
+ 'protocol': {
+ get: function() { return protocol; }
+ },
+ 'protocolCat': {
+ get: function() { return protocolCat; }
+ },
+ 'retry': {
+ get: function() { return retry; }
+ },
+ 'retryCat': {
+ get: function() { return retryCat; }
+ },
+ 'location': {
+ get: function() { return location; }
+ },
+ 'locationCat': {
+ get: function() { return locationCat; }
+ },
+ 'slicing': {
+ get: function() { return slicing; }
+ },
+ 'slicingCat': {
+ get: function() { return slicingCat; }
+ }
+ });
+ };
+
+ Ice.TraceLevels = TraceLevels;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/TraceUtil.js b/js/src/Ice/TraceUtil.js
new file mode 100644
index 00000000000..2e119ca6dcf
--- /dev/null
+++ b/js/src/Ice/TraceUtil.js
@@ -0,0 +1,474 @@
+// **********************************************************************
+//
+// 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/Debug");
+ require("Ice/HashMap");
+ require("Ice/Protocol");
+ require("Ice/StringUtil");
+ require("Ice/Current");
+ require("Ice/Identity");
+
+ var Ice = global.Ice || {};
+
+ //
+ // Local aliases.
+ //
+ var Debug = Ice.Debug;
+ var HashMap = Ice.HashMap;
+ var Protocol = Ice.Protocol;
+ var StringUtil = Ice.StringUtil;
+ var OperationMode = Ice.OperationMode;
+ var Identity = Ice.Identity;
+
+ var TraceUtil = {};
+
+ TraceUtil.traceSend = function(stream, logger, traceLevels)
+ {
+ if(traceLevels.protocol >= 1)
+ {
+ var p = stream.pos;
+ stream.pos = 0;
+
+ var s = [];
+ var type = printMessage(s, stream);
+
+ logger.trace(traceLevels.protocolCat, "sending " + getMessageTypeAsString(type) + " " + s.join(""));
+
+ stream.pos = p;
+ }
+ };
+
+ TraceUtil.traceRecv = function(stream, logger, traceLevels)
+ {
+ if(traceLevels.protocol >= 1)
+ {
+ var p = stream.pos;
+ stream.pos = 0;
+
+ var s = [];
+ var type = printMessage(s, stream);
+
+ logger.trace(traceLevels.protocolCat, "received " + getMessageTypeAsString(type) + " " + s.join(""));
+
+ stream.pos = p;
+ }
+ };
+
+ TraceUtil.trace = function(heading, stream, logger, traceLevels)
+ {
+ if(traceLevels.protocol >= 1)
+ {
+ var p = stream.pos;
+ stream.pos = 0;
+
+ var s = [];
+ s.push(heading);
+ printMessage(s, stream);
+
+ logger.trace(traceLevels.protocolCat, s.join(""));
+ stream.pos = p;
+ }
+ };
+
+ var slicingIds = new HashMap();
+
+ function traceSlicing(kind, typeId, slicingCat, logger)
+ {
+ if(!slicingIds.has(typeId))
+ {
+ var s = "unknown " + kind + " type `" + typeId + "'";
+ logger.trace(slicingCat, s);
+ slicingIds.set(typeId, 1);
+ }
+ }
+
+ TraceUtil.dumpStream = function(stream)
+ {
+ var pos = stream.pos;
+ stream.pos = 0;
+
+ var data = stream.readBlob(stream.size());
+ TraceUtil.dumpOctets(data);
+
+ stream.pos = pos;
+ };
+
+ TraceUtil.dumpOctets = function(data)
+ {
+ var inc = 8;
+ var buf = [];
+
+ for(var i = 0; i < data.length; i += inc)
+ {
+ var j;
+ for(j = i; j - i < inc; j++)
+ {
+ if(j < data.length)
+ {
+ var n = data[j];
+ if(n < 0)
+ {
+ n += 256;
+ }
+ var s;
+ if(n < 10)
+ {
+ s = " " + n;
+ }
+ else if(n < 100)
+ {
+ s = " " + n;
+ }
+ else
+ {
+ s = "" + n;
+ }
+ buf.push(s + " ");
+ }
+ else
+ {
+ buf.push(" ");
+ }
+ }
+
+ buf.push('"');
+
+ for(j = i; j < data.length && j - i < inc; j++)
+ {
+ if(data[j] >= 32 && data[j] < 127)
+ {
+ buf.push(String.fromCharCode(data[j]));
+ }
+ else
+ {
+ buf.push('.');
+ }
+ }
+
+ buf.push("\"\n");
+ }
+
+ console.log(buf.join(""));
+ };
+
+ Ice.TraceUtil = TraceUtil;
+ global.Ice = Ice;
+
+ function printIdentityFacetOperation(s, stream)
+ {
+ var identity = new Identity();
+ identity.__read(stream);
+ s.push("\nidentity = " + stream.instance.identityToString(identity));
+
+ var facet = Ice.StringSeqHelper.read(stream);
+ s.push("\nfacet = ");
+ if(facet.length > 0)
+ {
+ s.push(StringUtil.escapeString(facet[0], ""));
+ }
+
+ var operation = stream.readString();
+ s.push("\noperation = " + operation);
+ }
+
+ function printRequest(s, stream)
+ {
+ var requestId = stream.readInt();
+ s.push("\nrequest id = " + requestId);
+ if(requestId === 0)
+ {
+ s.push(" (oneway)");
+ }
+
+ printRequestHeader(s, stream);
+ }
+
+ function printBatchRequest(s, stream)
+ {
+ var batchRequestNum = stream.readInt();
+ s.push("\nnumber of requests = " + batchRequestNum);
+
+ for(var i = 0; i < batchRequestNum; ++i)
+ {
+ s.push("\nrequest #" + i + ':');
+ printRequestHeader(s, stream);
+ }
+ }
+
+ function printReply(s, stream)
+ {
+ var requestId = stream.readInt();
+ s.push("\nrequest id = " + requestId);
+
+ var replyStatus = stream.readByte();
+ s.push("\nreply status = " + replyStatus + ' ');
+
+ switch(replyStatus)
+ {
+ case Protocol.replyOK:
+ {
+ s.push("(ok)");
+ break;
+ }
+
+ case Protocol.replyUserException:
+ {
+ s.push("(user exception)");
+ break;
+ }
+
+ case Protocol.replyObjectNotExist:
+ case Protocol.replyFacetNotExist:
+ case Protocol.replyOperationNotExist:
+ {
+ switch(replyStatus)
+ {
+ case Protocol.replyObjectNotExist:
+ {
+ s.push("(object not exist)");
+ break;
+ }
+
+ case Protocol.replyFacetNotExist:
+ {
+ s.push("(facet not exist)");
+ break;
+ }
+
+ case Protocol.replyOperationNotExist:
+ {
+ s.push("(operation not exist)");
+ break;
+ }
+
+ default:
+ {
+ Debug.assert(false);
+ break;
+ }
+ }
+
+ printIdentityFacetOperation(s, stream);
+ break;
+ }
+
+ case Protocol.replyUnknownException:
+ case Protocol.replyUnknownLocalException:
+ case Protocol.replyUnknownUserException:
+ {
+ switch(replyStatus)
+ {
+ case Protocol.replyUnknownException:
+ {
+ s.push("(unknown exception)");
+ break;
+ }
+
+ case Protocol.replyUnknownLocalException:
+ {
+ s.push("(unknown local exception)");
+ break;
+ }
+
+ case Protocol.replyUnknownUserException:
+ {
+ s.push("(unknown user exception)");
+ break;
+ }
+
+ default:
+ {
+ Debug.assert(false);
+ break;
+ }
+ }
+
+ var unknown = stream.readString();
+ s.push("\nunknown = " + unknown);
+ break;
+ }
+
+ default:
+ {
+ s.push("(unknown)");
+ break;
+ }
+ }
+ }
+
+ function printRequestHeader(s, stream)
+ {
+ printIdentityFacetOperation(s, stream);
+
+ var mode = stream.readByte();
+ s.push("\nmode = " + mode + ' ');
+ switch(OperationMode.valueOf(mode))
+ {
+ case OperationMode.Normal:
+ {
+ s.push("(normal)");
+ break;
+ }
+
+ case OperationMode.Nonmutating:
+ {
+ s.push("(nonmutating)");
+ break;
+ }
+
+ case OperationMode.Idempotent:
+ {
+ s.push("(idempotent)");
+ break;
+ }
+
+ default:
+ {
+ s.push("(unknown)");
+ break;
+ }
+ }
+
+ var sz = stream.readSize();
+ s.push("\ncontext = ");
+ while(sz-- > 0)
+ {
+ var key = stream.readString();
+ var value = stream.readString();
+ s.push(key + '/'+ value);
+ if(sz > 0)
+ {
+ s.push(", ");
+ }
+ }
+
+ var ver = stream.skipEncaps();
+ if(!ver.equals(Protocol.Encoding_1_0))
+ {
+ s.push("\nencoding = ");
+ s.push(Ice.encodingVersionToString(ver));
+ }
+ }
+
+ function printHeader(s, stream)
+ {
+ stream.readByte(); // Don't bother printing the magic number
+ stream.readByte();
+ stream.readByte();
+ stream.readByte();
+
+ // var pMajor = stream.readByte();
+ // var pMinor = stream.readByte();
+ // s.push("\nprotocol version = " + pMajor + "." + pMinor);
+ stream.readByte(); // major
+ stream.readByte(); // minor
+
+ // var eMajor = stream.readByte();
+ // var eMinor = stream.readByte();
+ // s.push("\nencoding version = " + eMajor + "." + eMinor);
+ stream.readByte(); // major
+ stream.readByte(); // minor
+
+ var type = stream.readByte();
+
+ s.push("\nmessage type = " + type + " (" + getMessageTypeAsString(type) + ')');
+ var compress = stream.readByte();
+ s.push("\ncompression status = " + compress + ' ');
+ switch(compress)
+ {
+ case 0:
+ {
+ s.push("(not compressed; do not compress response, if any)");
+ break;
+ }
+
+ case 1:
+ {
+ s.push("(not compressed; compress response, if any)");
+ break;
+ }
+
+ case 2:
+ {
+ s.push("(compressed; compress response, if any)");
+ break;
+ }
+
+ default:
+ {
+ s.push("(unknown)");
+ break;
+ }
+ }
+
+ var size = stream.readInt();
+ s.push("\nmessage size = " + size);
+ return type;
+ }
+
+ function printMessage(s, stream)
+ {
+ var type = printHeader(s, stream);
+
+ switch(type)
+ {
+ case Protocol.closeConnectionMsg:
+ case Protocol.validateConnectionMsg:
+ {
+ // We're done.
+ break;
+ }
+
+ case Protocol.requestMsg:
+ {
+ printRequest(s, stream);
+ break;
+ }
+
+ case Protocol.requestBatchMsg:
+ {
+ printBatchRequest(s, stream);
+ break;
+ }
+
+ case Protocol.replyMsg:
+ {
+ printReply(s, stream);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ return type;
+ }
+
+ function getMessageTypeAsString(type)
+ {
+ switch(type)
+ {
+ case Protocol.requestMsg:
+ return "request";
+ case Protocol.requestBatchMsg:
+ return "batch request";
+ case Protocol.replyMsg:
+ return "reply";
+ case Protocol.closeConnectionMsg:
+ return "close connection";
+ case Protocol.validateConnectionMsg:
+ return "validate connection";
+ default:
+ return "unknown";
+ }
+ }
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/UUID.js b/js/src/Ice/UUID.js
new file mode 100644
index 00000000000..11928fcb1da
--- /dev/null
+++ b/js/src/Ice/UUID.js
@@ -0,0 +1,30 @@
+// **********************************************************************
+//
+// 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){
+ var Ice = global.Ice || {};
+
+ var UUID = {};
+
+ UUID.generateUUID = function()
+ {
+ var d = new Date().getTime();
+ var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = (d + Math.random() * 16) % 16 | 0;
+ d = Math.floor(d / 16);
+ return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
+ });
+ return uuid;
+ };
+
+ Ice.UUID = UUID;
+ Ice.generateUUID = UUID.generateUUID;
+
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/UnknownSlicedObject.js b/js/src/Ice/UnknownSlicedObject.js
new file mode 100644
index 00000000000..70ef7146f53
--- /dev/null
+++ b/js/src/Ice/UnknownSlicedObject.js
@@ -0,0 +1,80 @@
+// **********************************************************************
+//
+// 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/Object");
+ require("Ice/Class");
+
+ var Ice = global.Ice || {};
+
+ var SliceInfo = function()
+ {
+ /**
+ * The Slice type ID for this slice.
+ **/
+ this.typeId = "";
+
+ /**
+ * The Slice compact type ID for this slice.
+ **/
+ this.compactId = -1;
+
+ /**
+ * The encoded bytes for this slice, including the leading size integer.
+ **/
+ this.bytes = [];
+
+ /**
+ * The Ice objects referenced by this slice.
+ **/
+ this.objects = [];
+
+ /**
+ * Whether or not the slice contains optional members.
+ **/
+ this.hasOptionalMembers = false;
+
+ /**
+ * Whether or not this is the last slice.
+ **/
+ this.isLastSlice = false;
+ };
+
+ var SlicedData = function(slices)
+ {
+ this.slices = slices;
+ };
+
+ var UnknownSlicedObject = Ice.Class(Ice.Object,
+ {
+ __init__: function(unknownTypeId)
+ {
+ this._unknownTypeId = unknownTypeId;
+ },
+ getUnknownTypeId: function()
+ {
+ return this._unknownTypeId;
+ },
+ __write: function(os)
+ {
+ os.startWriteObject(this._slicedData);
+ os.endWriteObject();
+ },
+ __read: function(is)
+ {
+ is.startReadObject();
+ this._slicedData = is.endReadObject(true);
+ }
+ });
+
+ Ice.SliceInfo = SliceInfo;
+ Ice.SlicedData = SlicedData;
+ Ice.UnknownSlicedObject = UnknownSlicedObject;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/browser/.gitignore b/js/src/Ice/browser/.gitignore
new file mode 100644
index 00000000000..9c5c0a3f6d2
--- /dev/null
+++ b/js/src/Ice/browser/.gitignore
@@ -0,0 +1,2 @@
+ConnectionInfo.js
+EndpointInfo.js
diff --git a/js/src/Ice/browser/Buffer.js b/js/src/Ice/browser/Buffer.js
new file mode 100644
index 00000000000..5d6c33393fe
--- /dev/null
+++ b/js/src/Ice/browser/Buffer.js
@@ -0,0 +1,419 @@
+// **********************************************************************
+//
+// 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){
+ //
+ // IE 10 doesn't implement ArrayBuffer.slice
+ //
+
+ if(!ArrayBuffer.prototype.slice)
+ {
+ ArrayBuffer.prototype.slice = function (start, end)
+ {
+ var b = new Uint8Array(this);
+ end = end === undefined ? b.length : end;
+ var result = new Uint8Array(new ArrayBuffer(end - start));
+ for(var i = 0, length = result.length; i < length; i++)
+ {
+ result[i] = b[i + start];
+ }
+ return result.buffer;
+ };
+ }
+
+ var __BufferOverflowException__ = "BufferOverflowException";
+ var __BufferUnderflowException__ = "BufferUnderflowException";
+ var __IndexOutOfBoundsException__ = "IndexOutOfBoundsException";
+
+ //
+ // Buffer implementation to be used by web browsers, it uses ArrayBuffer as
+ // the store.
+ //
+
+ require("Ice/Class");
+ require("Ice/Long");
+
+ var Ice = global.Ice || Ice;
+ var Long = Ice.Long;
+
+ var Buffer = Ice.Class({
+ __init__: function(buffer)
+ {
+ if(buffer !== undefined)
+ {
+ this.b = buffer;
+ this.v = new DataView(this.b);
+ }
+ else
+ {
+ this.b = null; // ArrayBuffer
+ this.v = null; // DataView
+ }
+ this._position = 0;
+ this._limit = 0;
+ this._shrinkCounter = 0;
+ },
+ empty: function()
+ {
+ return this._limit === 0;
+ },
+ resize: function(n)
+ {
+ if(n === 0)
+ {
+ this.clear();
+ }
+ else if(n > this.capacity)
+ {
+ this.reserve(n);
+ }
+ this._limit = n;
+ },
+ clear: function()
+ {
+ this.b = null;
+ this.v = null;
+ this._position = 0;
+ this._limit = 0;
+ },
+ //
+ // Call expand(n) to add room for n additional bytes. Note that expand()
+ // examines the current position of the buffer first; we don't want to
+ // expand the buffer if the caller is writing to a location that is
+ // already in the buffer.
+ //
+ expand: function(n)
+ {
+ var sz = this.capacity === 0 ? n : this._position + n;
+ if(sz > this._limit)
+ {
+ this.resize(sz);
+ }
+ },
+ reset: function()
+ {
+ if(this._limit > 0 && this._limit * 2 < this.capacity)
+ {
+ //
+ // If the current buffer size is smaller than the
+ // buffer capacity, we shrink the buffer memory to the
+ // current size. This is to avoid holding on to too much
+ // memory if it's not needed anymore.
+ //
+ if(++this._shrinkCounter > 2)
+ {
+ this.reserve(this._limit);
+ this._shrinkCounter = 0;
+ }
+ }
+ else
+ {
+ this._shrinkCounter = 0;
+ }
+ this._limit = 0;
+ this._position = 0;
+ },
+ reserve: function(n)
+ {
+ if(n > this.capacity)
+ {
+ var capacity = Math.max(n, 2 * this.capacity);
+ capacity = Math.max(1024, capacity);
+ if(!this.b)
+ {
+ this.b = new ArrayBuffer(capacity);
+ }
+ else
+ {
+ var b = new Uint8Array(capacity);
+ b.set(new Uint8Array(this.b));
+ this.b = b.buffer;
+ }
+ this.v = new DataView(this.b);
+ }
+ else if(n < this.capacity)
+ {
+ this.b = this.b.slice(0, this.capacity);
+ this.v = new DataView(this.b);
+ }
+ else
+ {
+ return;
+ }
+ },
+ put: function(v)
+ {
+ if(this._position === this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.v.setUint8(this._position, v);
+ this._position++;
+ },
+ putAt: function(i, v)
+ {
+ if(i >= this._limit)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ this.v.setUint8(i, v);
+ },
+ putArray: function(v)
+ {
+ if(v.byteLength > 0)
+ {
+ //Expects an Uint8Array
+ if(this._position + v.length > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ new Uint8Array(this.b, 0, this.b.byteLength).set(v, this._position);
+ this._position += v.byteLength;
+ }
+ },
+ putShort: function(v)
+ {
+ if(this._position + 2 > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.v.setInt16(this._position, v, true);
+ this._position += 2;
+ },
+ putInt: function(v)
+ {
+ if(this._position + 4 > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.v.setInt32(this._position, v, true);
+ this._position += 4;
+ },
+ putIntAt: function(i, v)
+ {
+ if(i + 4 > this._limit || i < 0)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ this.v.setInt32(i, v, true);
+ },
+ putFloat: function(v)
+ {
+ if(this._position + 4 > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.v.setFloat32(this._position, v, true);
+ this._position += 4;
+ },
+ putDouble: function(v)
+ {
+ if(this._position + 8 > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.v.setFloat64(this._position, v, true);
+ this._position += 8;
+ },
+ putLong: function(v)
+ {
+ if(this._position + 8 > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ this.v.setInt32(this._position, v.low, true);
+ this._position += 4;
+ this.v.setInt32(this._position, v.high, true);
+ this._position += 4;
+ },
+ writeString: function(stream, v)
+ {
+ //
+ // Encode the string as utf8
+ //
+ var encoded = unescape(encodeURIComponent(v));
+
+ stream.writeSize(encoded.length);
+ stream.expand(encoded.length);
+ this.putString(encoded, encoded.length);
+ },
+ putString: function(v, sz)
+ {
+ if(this._position + sz > this._limit)
+ {
+ throw new Error(__BufferOverflowException__);
+ }
+ for(var i = 0; i < sz; ++i)
+ {
+ this.v.setUint8(this._position, v.charCodeAt(i));
+ this._position++;
+ }
+ },
+ get: function()
+ {
+ if(this._position >= this._limit)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var v = this.v.getUint8(this._position);
+ this._position++;
+ return v;
+ },
+ getAt: function(i)
+ {
+ if(i < 0 || i >= this._limit)
+ {
+ throw new Error(__IndexOutOfBoundsException__);
+ }
+ return this.v.getUint8(i);
+ },
+ getArray: function(length)
+ {
+ if(this._position + length > this._limit)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var buffer = this.b.slice(this._position, this._position + length);
+ this._position += length;
+ return new Uint8Array(buffer);
+ },
+ getArrayAt: function(position, length)
+ {
+ if(position + length > this._limit)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ length = length === undefined ? (this.b.byteLength - position) : length;
+ return new Uint8Array(this.b.slice(position, position + length));
+ },
+ getShort: function()
+ {
+ if(this._limit - this._position < 2)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var v = this.v.getInt16(this._position, true);
+ this._position += 2;
+ return v;
+ },
+ getInt: function()
+ {
+ if(this._limit - this._position < 4)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var v = this.v.getInt32(this._position, true);
+ this._position += 4;
+ return v;
+ },
+ getFloat: function()
+ {
+ if(this._limit - this._position < 4)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var v = this.v.getFloat32(this._position, true);
+ this._position += 4;
+ return v;
+ },
+ getDouble: function()
+ {
+ if(this._limit - this._position < 8)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var v = this.v.getFloat64(this._position, true);
+ this._position += 8;
+ return v;
+ },
+ getLong: function()
+ {
+ if(this._limit - this._position < 8)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+ var v = new Long();
+ v.low = this.v.getInt32(this._position, true);
+ this._position += 4;
+ v.high = this.v.getInt32(this._position, true);
+ this._position += 4;
+ return v;
+ },
+ getString: function(length)
+ {
+ if(this._position + length > this._limit)
+ {
+ throw new Error(__BufferUnderflowException__);
+ }
+
+ var data = new DataView(this.b, this._position, length);
+ var s = "";
+
+ for(var i = 0; i < length; ++i)
+ {
+ s += String.fromCharCode(data.getUint8(i));
+ }
+ this._position += length;
+ s = decodeURIComponent(escape(s));
+ return s;
+ }
+ });
+
+ var prototype = Buffer.prototype;
+
+ Object.defineProperty(prototype, "position", {
+ get: function() { return this._position; },
+ set: function(position){
+ if(position >= 0 && position <= this._limit)
+ {
+ this._position = position;
+ }
+ }
+ });
+
+ Object.defineProperty(prototype, "limit", {
+ get: function() { return this._limit; },
+ set: function(limit){
+ if(limit <= this.capacity)
+ {
+ this._limit = limit;
+ if(this._position > limit)
+ {
+ this._position = limit;
+ }
+ }
+ }
+ });
+
+ Object.defineProperty(prototype, "capacity", {
+ get: function() { return this.b === null ? 0 : this.b.byteLength; }
+ });
+
+ Object.defineProperty(prototype, "remaining", {
+ get: function() { return this._limit - this._position; }
+ });
+
+ //
+ // Create a native buffer from an array of bytes.
+ //
+ Buffer.createNative = function(data)
+ {
+ if(data === undefined)
+ {
+ return new Uint8Array(0);
+ }
+ else
+ {
+ return new Uint8Array(data);
+ }
+ };
+
+ Ice.Buffer = Buffer;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/browser/Debug.js b/js/src/Ice/browser/Debug.js
new file mode 100644
index 00000000000..c6739e40ebd
--- /dev/null
+++ b/js/src/Ice/browser/Debug.js
@@ -0,0 +1,41 @@
+// **********************************************************************
+//
+// 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/Exception");
+
+ var Ice = global.Ice || {};
+
+ var Exception = Ice.Exception;
+
+ var AssertionFailedException = Ice.Class(Error, {
+ __init__: function(message)
+ {
+ Error.call(this);
+ Exception.captureStackTrace(this);
+ this.message = message;
+ }
+ });
+ var Debug = {};
+
+ Debug.AssertionFailedException = AssertionFailedException;
+
+ Debug.assert = function(b, msg)
+ {
+ if(!b)
+ {
+ console.log(msg === undefined ? "assertion failed" : msg);
+ console.log(Error().stack);
+ throw new AssertionFailedException(msg === undefined ? "assertion failed" : msg);
+ }
+ };
+ Ice.Debug = Debug;
+ global.Ice = Ice;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/browser/EndpointFactory.js b/js/src/Ice/browser/EndpointFactory.js
new file mode 100644
index 00000000000..c8481c654b5
--- /dev/null
+++ b/js/src/Ice/browser/EndpointFactory.js
@@ -0,0 +1,51 @@
+// **********************************************************************
+//
+// 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/Endpoint");
+
+ require("Ice/browser/EndpointInfo");
+ require("Ice/browser/EndpointI");
+
+ var Ice = global.Ice || {};
+ var IceWS = global.IceWS || {};
+
+ var EndpointI = IceWS.EndpointI;
+
+ var EndpointFactory = Ice.Class({
+ __init__:function(instance, secure)
+ {
+ this._instance = instance;
+ this._secure = secure;
+ },
+ type: function()
+ {
+ return this._secure ? IceWS.WSSEndpointType : IceWS.WSEndpointType;
+ },
+ protocol: function()
+ {
+ return this._secure ? "wss" : "ws";
+ },
+ create: function(str, oaEndpoint)
+ {
+ return EndpointI.fromString(this._instance, this._secure, str, oaEndpoint);
+ },
+ read: function(s)
+ {
+ return EndpointI.fromStream(s, this._secure);
+ },
+ destroy: function()
+ {
+ this._instance = null;
+ }
+ });
+ IceWS.EndpointFactory = EndpointFactory;
+ global.IceWS = IceWS;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/browser/EndpointI.js b/js/src/Ice/browser/EndpointI.js
new file mode 100644
index 00000000000..f364a087922
--- /dev/null
+++ b/js/src/Ice/browser/EndpointI.js
@@ -0,0 +1,543 @@
+// **********************************************************************
+//
+// 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/Address");
+ require("Ice/HashUtil");
+ require("Ice/StringUtil");
+ require("Ice/Endpoint");
+ require("Ice/LocalException");
+
+ require("Ice/browser/Transceiver");
+ require("Ice/browser/EndpointInfo");
+
+ var Ice = global.Ice || {};
+ var IceWS = global.IceWS || {};
+
+ var Address = Ice.Address;
+ var HashUtil = Ice.HashUtil;
+ var StringUtil = Ice.StringUtil;
+ var Transceiver = IceWS.Transceiver;
+
+ var Class = Ice.Class;
+
+ var EndpointI = Class(Ice.Endpoint, {
+ __init__: function(instance, secure, ho, po, ti, conId, co, re)
+ {
+ this._instance = instance;
+ this._secure = secure;
+ this._host = ho;
+ this._port = po;
+ this._timeout = ti;
+ this._connectionId = conId;
+ this._compress = co;
+ this._resource = re;
+ this.calcHashValue();
+ },
+ //
+ // Convert the endpoint to its string form
+ //
+ toString: function()
+ {
+ //
+ // WARNING: Certain features, such as proxy validation in Glacier2,
+ // depend on the format of proxy strings. Changes to toString() and
+ // methods called to generate parts of the reference string could break
+ // these features. Please review for all features that depend on the
+ // format of proxyToString() before changing this and related code.
+ //
+ var s = (this._secure ? "wss" : "ws");
+
+ if(this._host !== null && this._host.length > 0)
+ {
+ s += " -h ";
+ s += (this._host.indexOf(':') !== -1) ? ("\"" + this._host + "\"") : this._host;
+ }
+
+ s += " -p " + this._port;
+
+ if(this._timeout != -1)
+ {
+ s += " -t " + this._timeout;
+ }
+ if(this._compress)
+ {
+ s += " -z";
+ }
+ if(this._resource !== null && this._resource.length > 0)
+ {
+ s += " -r ";
+ s += (this._resource.indexOf(':') !== -1) ? ("\"" + this._resource + "\"") : this._resource;
+ }
+ return s;
+ },
+ //
+ // Return the endpoint information.
+ //
+ getInfo: function()
+ {
+ return new EndpointInfoI(this._secure, this._timeout, this._compress, this._host, this._port, this._resource);
+ },
+ //
+ // Marshal the endpoint
+ //
+ streamWrite: function(s)
+ {
+ s.writeShort(this._secure ? IceWS.WSSEndpointType : IceWS.WSEndpointType);
+ s.startWriteEncaps();
+ s.writeString(this._host);
+ s.writeInt(this._port);
+ s.writeInt(this._timeout);
+ s.writeBool(this._compress);
+ s.writeString(this._resource);
+ s.endWriteEncaps();
+ },
+ //
+ // Return the endpoint type
+ //
+ type: function()
+ {
+ return this._secure ? IceWS.WSSEndpointType : IceWS.WSEndpointType;
+ },
+ //
+ // Return the timeout for the endpoint in milliseconds. 0 means
+ // non-blocking, -1 means no timeout.
+ //
+ timeout: function()
+ {
+ return this._timeout;
+ },
+ //
+ // Return a new endpoint with a different timeout value, provided
+ // that timeouts are supported by the endpoint. Otherwise the same
+ // endpoint is returned.
+ //
+ changeTimeout: function(timeout)
+ {
+ if(timeout === this._timeout)
+ {
+ return this;
+ }
+ else
+ {
+ return new EndpointI(this._instance, this._secure, this._host, this._port, timeout, this._connectionId, this._compress, this._resource);
+ }
+ },
+ //
+ // Return a new endpoint with a different connection id.
+ //
+ changeConnectionId: function(connectionId)
+ {
+ if(connectionId === this._connectionId)
+ {
+ return this;
+ }
+ else
+ {
+ return new EndpointI(this._instance, this._secure, this._host, this._port, this._timeout, connectionId, this._compress, this._resource);
+ }
+ },
+ //
+ // Return true if the endpoints support bzip2 compress, or false
+ // otherwise.
+ //
+ compress: function()
+ {
+ return this._compress;
+ },
+ //
+ // Return a new endpoint with a different compression value,
+ // provided that compression is supported by the
+ // endpoint. Otherwise the same endpoint is returned.
+ //
+ changeCompress: function(compress)
+ {
+ if(compress === this._compress)
+ {
+ return this;
+ }
+ else
+ {
+ return new EndpointI(this._instance, this._secure, this._host, this._port, this._timeout, this._connectionId, compress, this._resource);
+ }
+ },
+ //
+ // Return true if the endpoint is datagram-based.
+ //
+ datagram: function()
+ {
+ return false;
+ },
+ //
+ // Return true if the endpoint is secure.
+ //
+ secure: function()
+ {
+ return this._secure;
+ },
+ //
+ // Return a server side transceiver for this endpoint, or null if a
+ // transceiver can only be created by an acceptor. In case a
+ // transceiver is created, this operation also returns a new
+ // "effective" endpoint, which might differ from this endpoint,
+ // for example, if a dynamic port number is assigned.
+ //
+ transceiver: function(endpoint)
+ {
+ return null;
+ },
+ //
+ // Return an acceptor for this endpoint, or null if no acceptors
+ // is available. In case an acceptor is created, this operation
+ // also returns a new "effective" endpoint, which might differ
+ // from this endpoint, for example, if a dynamic port number is
+ // assigned.
+ //
+ acceptor: function(endpoint, adapterName)
+ {
+ return null;
+ },
+ connect: function()
+ {
+ if(this._instance.traceLevels().network >= 2)
+ {
+ this._instance.initializationData().logger.trace(this._instance.traceLevels().networkCat,
+ "trying to establish " + (this._secure ? "wss" : "ws") + " connection to " + this._host + ":" +
+ this._port);
+ }
+
+ return Transceiver.createOutgoing(this._instance, this._secure, new Address(this._host, this._port),
+ this._resource);
+ },
+ hashCode: function()
+ {
+ return this._hashCode;
+ },
+ //
+ // Compare endpoints for sorting purposes
+ //
+ equals: function(p)
+ {
+ if(!(p instanceof EndpointI))
+ {
+ return false;
+ }
+
+ if(this === p)
+ {
+ return true;
+ }
+
+ if(this._host !== p._host)
+ {
+ return false;
+ }
+
+ if(this._port !== p._port)
+ {
+ return false;
+ }
+
+ if(this._timeout !== p._timeout)
+ {
+ return false;
+ }
+
+ if(this._connectionId !== p._connectionId)
+ {
+ return false;
+ }
+
+ if(this._compress !== p._compress)
+ {
+ return false;
+ }
+
+ if(this._resource !== p._resource)
+ {
+ return false;
+ }
+
+ return true;
+ },
+ compareTo: function(p)
+ {
+ if(this === p)
+ {
+ return 0;
+ }
+
+ if(p === null)
+ {
+ return 1;
+ }
+
+ if(!(p instanceof EndpointI))
+ {
+ return this.type() < p.type() ? -1 : 1;
+ }
+
+ if(this._port < p._port)
+ {
+ return -1;
+ }
+ else if(p._port < this._port)
+ {
+ return 1;
+ }
+
+ if(this._timeout < p._timeout)
+ {
+ return -1;
+ }
+ else if(p._timeout < this._timeout)
+ {
+ return 1;
+ }
+
+ if(this._connectionId != p._connectionId)
+ {
+ return this._connectionId < p._connectionId ? -1 : 1;
+ }
+
+ if(!this._compress && p._compress)
+ {
+ return -1;
+ }
+ else if(!p._compress && this._compress)
+ {
+ return 1;
+ }
+
+ if(this._host < p._host)
+ {
+ return -1;
+ }
+ else if(p._host < this._host)
+ {
+ return 1;
+ }
+
+ if(this._resource == p._resource)
+ {
+ return 0;
+ }
+ else
+ {
+ return this._resource < p._resource ? -1 : 1;
+ }
+ },
+ calcHashValue: function()
+ {
+ var h = 5381;
+ h = HashUtil.addNumber(h, this._secure ? IceWS.WSSEndpointType : IceWS.WSEndpointType);
+ h = HashUtil.addString(h, this._host);
+ h = HashUtil.addNumber(h, this._port);
+ h = HashUtil.addNumber(h, this._timeout);
+ h = HashUtil.addString(h, this._connectionId);
+ h = HashUtil.addBoolean(h, this._compress);
+ h = HashUtil.addString(h, this._resource);
+ this._hashCode = h;
+ }
+ });
+
+ EndpointI.fromString = function(instance, secure, str, oaEndpoint)
+ {
+ var host = null;
+ var port = 0;
+ var timeout = -1;
+ var compress = false;
+ var resource = "";
+
+ var protocol = secure ? "wss" : "ws";
+
+ var arr = str.split(/[ \t\n\r]+/);
+
+ var i = 0;
+ while(i < arr.length)
+ {
+ if(arr[i].length === 0)
+ {
+ i++;
+ continue;
+ }
+
+ var option = arr[i++];
+ if(option.length != 2 && option.charAt(0) != '-')
+ {
+ throw new Ice.EndpointParseException("expected an endpoint option but found `" + option +
+ "' in endpoint `" + protocol + " " + str + "'");
+ }
+
+ var argument = null;
+ if(i < arr.length && arr[i].charAt(0) != '-')
+ {
+ argument = arr[i++];
+ if(argument.charAt(0) == '\"' && argument.charAt(argument.length - 1) == '\"')
+ {
+ argument = argument.substring(1, argument.length - 1);
+ }
+ }
+
+ switch(option.charAt(1))
+ {
+ case 'h':
+ {
+ if(argument === null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -h option in endpoint `" +
+ protocol + " " + str + "'");
+ }
+
+ host = argument;
+ break;
+ }
+
+ case 'p':
+ {
+ if(argument === null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -p option in endpoint `" +
+ protocol + " " + str + "'");
+ }
+
+ try
+ {
+ port = StringUtil.toInt(argument);
+ }
+ catch(ex)
+ {
+ throw new Ice.EndpointParseException("invalid port value `" + argument +
+ "' in endpoint `" + protocol + " " + str + "'");
+ }
+
+ if(port < 0 || port > 65535)
+ {
+ throw new Ice.EndpointParseException("port value `" + argument +
+ "' out of range in endpoint `" + protocol + " " + str +
+ "'");
+ }
+
+ break;
+ }
+
+ case 'r':
+ {
+ if(argument === null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -r option in endpoint `" +
+ protocol + " " + str + "'");
+ }
+
+ resource = argument;
+ break;
+ }
+
+ case 't':
+ {
+ if(argument === null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -t option in endpoint `" +
+ protocol + " " + str + "'");
+ }
+
+ try
+ {
+ timeout = StringUtil.toInt(argument);
+ }
+ catch(ex)
+ {
+ throw new Ice.EndpointParseException("invalid timeout value `" + argument +
+ "' in endpoint `" + protocol + " " + str + "'");
+ }
+
+ break;
+ }
+
+ case 'z':
+ {
+ if(argument !== null)
+ {
+ throw new Ice.EndpointParseException("unexpected argument `" + argument +
+ "' provided for -z option in `" + protocol + " " + str +
+ "'");
+ }
+
+ compress = true;
+ break;
+ }
+
+ default:
+ {
+ throw new Ice.EndpointParseException("unknown option `" + option + "' in `" + protocol + " " +
+ str + "'");
+ }
+ }
+ }
+
+ if(host === null)
+ {
+ host = instance.defaultsAndOverrides().defaultHost;
+ }
+ else if(host == "*")
+ {
+ if(oaEndpoint)
+ {
+ host = null;
+ }
+ else
+ {
+ throw new Ice.EndpointParseException("`-h *' not valid for proxy endpoint `" + protocol + " " + str +
+ "'");
+ }
+ }
+
+ if(host === null)
+ {
+ host = "";
+ }
+ return new EndpointI(instance, secure, host, port, timeout, "", compress, resource);
+ };
+
+ EndpointI.fromStream = function(s, secure)
+ {
+ s.startReadEncaps();
+ var host = s.readString();
+ var port = s.readInt();
+ var timeout = s.readInt();
+ var compress = s.readBool();
+ var resource = s.readString();
+ s.endReadEncaps();
+ return new EndpointI(s.instance, secure, host, port, timeout, "", compress, resource);
+ };
+
+ IceWS.EndpointI = EndpointI;
+ global.IceWS = IceWS;
+
+ var EndpointInfoI = Class(IceWS.EndpointInfo, {
+ __init__: function(secure, timeout, compress, host, port, resource)
+ {
+ IceWS.EndpointInfo.call(this, timeout, compress, host, port, resource);
+ this.secure = secure;
+ },
+ type: function()
+ {
+ return this._secure ? IceWS.WSSEndpointType : IceWS.WSEndpointType;
+ },
+ datagram: function()
+ {
+ return false;
+ },
+ secure: function()
+ {
+ return this._secure;
+ }
+ });
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/browser/Transceiver.js b/js/src/Ice/browser/Transceiver.js
new file mode 100644
index 00000000000..f700dfbfc55
--- /dev/null
+++ b/js/src/Ice/browser/Transceiver.js
@@ -0,0 +1,418 @@
+// **********************************************************************
+//
+// 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/Debug");
+ require("Ice/ExUtil");
+ require("Ice/Network");
+ require("Ice/SocketOperation");
+ require("Ice/Connection");
+ require("Ice/Exception");
+ require("Ice/LocalException");
+
+ require("Ice/browser/ConnectionInfo");
+
+ var Ice = global.Ice || {};
+ var IceWS = global.IceWS || {};
+
+ var Debug = Ice.Debug;
+ var ExUtil = Ice.ExUtil;
+ var Network = Ice.Network;
+ var SocketOperation = Ice.SocketOperation;
+ var Conn = Ice.Connection;
+ var LocalException = Ice.LocalException;
+ var SocketException = Ice.SocketException;
+
+ var StateNeedConnect = 0;
+ var StateConnectPending = 1;
+ var StateConnected = 2;
+ var StateClosePending = 3;
+ var StateClosed = 4;
+
+ var IsFirefox = navigator.userAgent.indexOf("Firefox") !== -1;
+
+ var Transceiver = Ice.Class({
+ __init__: function(instance)
+ {
+ this._traceLevels = instance.traceLevels();
+ this._logger = instance.initializationData().logger;
+ this._readBuffers = [];
+ this._readPosition = 0;
+ },
+ setCallbacks: function(connectedCallback, bytesAvailableCallback, bytesWrittenCallback)
+ {
+ this._connectedCallback = connectedCallback;
+ this._bytesAvailableCallback = bytesAvailableCallback;
+ this._bytesWrittenCallback = bytesWrittenCallback;
+ },
+ //
+ // Returns SocketOperation.None when initialization is complete.
+ //
+ initialize: function(readBuffer, writeBuffer)
+ {
+ try
+ {
+ if(this._exception)
+ {
+ throw this._exception;
+ }
+
+ if(this._state === StateNeedConnect)
+ {
+ this._state = StateConnectPending;
+ this._fd = new WebSocket(this._url, "ice.zeroc.com");
+ this._fd.binaryType = "arraybuffer";
+ var self = this;
+ this._fd.onopen = function(e) { self.socketConnected(e); };
+ this._fd.onmessage = function(e) { self.socketBytesAvailable(e.data); };
+ this._fd.onclose = function(e) { self.socketClosed(e); };
+ return SocketOperation.Connect; // Waiting for connect to complete.
+ }
+ else if(this._state === StateConnectPending)
+ {
+ //
+ // Socket is connected.
+ //
+ this._desc = fdToString(this._addr);
+ this._state = StateConnected;
+ }
+ }
+ catch(err)
+ {
+ if(!this._exception)
+ {
+ this._exception = translateError(this._state, err);
+ }
+
+ if(this._traceLevels.network >= 2)
+ {
+ var s = [];
+ s.push("failed to establish " + this.type() + " connection\n");
+ s.push(fdToString(this._addr));
+ this._logger.trace(this._traceLevels.networkCat, s.join(""));
+ }
+ throw this._exception;
+ }
+
+ Debug.assert(this._state === StateConnected);
+ if(this._traceLevels.network >= 1)
+ {
+ this._logger.trace(this._traceLevels.networkCat, this.type() +
+ " connection established\n" + this._desc);
+ }
+ return SocketOperation.None;
+ },
+ register: function()
+ {
+ //
+ // Register the socket data listener.
+ //
+ this._registered = true;
+ if(this._hasBytesAvailable || this._exception)
+ {
+ this._bytesAvailableCallback();
+ this._hasBytesAvailable = false;
+ }
+ },
+ unregister: function()
+ {
+ //
+ // Unregister the socket data listener.
+ //
+ this._registered = false;
+ },
+ close: function()
+ {
+ if(this._fd === null)
+ {
+ Debug.assert(this._exception); // Websocket creation failed.
+ return;
+ }
+
+ //
+ // WORKAROUND: With Firefox, calling close() if the websocket isn't connected
+ // yet doesn't close the connection. The server doesn't receive any close frame
+ // and the underlying socket isn't closed causing the server to hang on closing
+ // the connection until the browser exits.
+ //
+ // To workaround this problem, we always wait for the socket to be connected
+ // or closed before closing the socket.
+ //
+ if(this._fd.readyState === WebSocket.CONNECTING && IsFirefox)
+ {
+ this._state = StateClosePending;
+ return;
+ }
+
+ if(this._state == StateConnected && this._traceLevels.network >= 1)
+ {
+ this._logger.trace(this._traceLevels.networkCat, "closing " + this.type() + " connection\n" +
+ this._desc);
+ }
+
+ Debug.assert(this._fd !== null);
+ try
+ {
+ this._state = StateClosed;
+ this._fd.close();
+ }
+ catch(ex)
+ {
+ throw translateError(this._state, ex);
+ }
+ finally
+ {
+ this._fd = null;
+ }
+ },
+ //
+ // Returns true if all of the data was flushed to the kernel buffer.
+ //
+ write: function(byteBuffer)
+ {
+ if(this._exception)
+ {
+ throw this._exception;
+ }
+
+ var remaining = byteBuffer.remaining;
+ Debug.assert(remaining > 0);
+ Debug.assert(this._fd);
+
+ //
+ // Delay the send if more than 1KB is already queued for
+ // sending on the socket. If less, we consider that it's
+ // fine to push more data on the socket.
+ //
+ if(this._fd.bufferedAmount < 1024)
+ {
+ //
+ // Create a slice of the source buffer representing the remaining data to be written.
+ //
+ var slice = byteBuffer.b.slice(byteBuffer.position, byteBuffer.position + remaining);
+
+ //
+ // The socket will accept all of the data.
+ //
+ byteBuffer.position = byteBuffer.position + remaining;
+ this._fd.send(slice);
+ if(remaining > 0 && this._traceLevels.network >= 3)
+ {
+ var msg = "sent " + remaining + " of " + remaining + " bytes via " + this.type() + "\n" +this._desc;
+ this._logger.trace(this._traceLevels.networkCat, msg);
+ }
+ return true;
+ }
+ else
+ {
+ var transceiver = this;
+ var writtenCB = function()
+ {
+ if(transceiver._fd)
+ {
+ if(transceiver._fd.bufferedAmount === 0 || this._exception)
+ {
+ transceiver._bytesWrittenCallback();
+ }
+ else
+ {
+ setTimeout(writtenCB, 50);
+ }
+ }
+ };
+ setTimeout(writtenCB, 50);
+ return false;
+ }
+ },
+ read: function(byteBuffer, moreData)
+ {
+ if(this._exception)
+ {
+ throw this._exception;
+ }
+
+ moreData.value = false;
+
+ if(this._readBuffers.length === 0)
+ {
+ return false; // No data available.
+ }
+
+ var avail = this._readBuffers[0].byteLength - this._readPosition;
+ Debug.assert(avail > 0);
+ var remaining = byteBuffer.remaining;
+
+ while(byteBuffer.remaining > 0)
+ {
+ if(avail > byteBuffer.remaining)
+ {
+ avail = byteBuffer.remaining;
+ }
+
+ new Uint8Array(byteBuffer.b).set(new Uint8Array(this._readBuffers[0], this._readPosition, avail),
+ byteBuffer.position);
+
+ byteBuffer.position += avail;
+ this._readPosition += avail;
+ if(this._readPosition === this._readBuffers[0].byteLength)
+ {
+ //
+ // We've exhausted the current read buffer.
+ //
+ this._readPosition = 0;
+ this._readBuffers.shift();
+ if(this._readBuffers.length === 0)
+ {
+ break; // No more data - we're done.
+ }
+ else
+ {
+ avail = this._readBuffers[0].byteLength;
+ }
+ }
+ }
+
+ var n = remaining - byteBuffer.remaining;
+ if(n > 0 && this._traceLevels.network >= 3)
+ {
+ var msg = "received " + n + " of " + remaining + " bytes via " + this.type() + "\n" + this._desc;
+ this._logger.trace(this._traceLevels.networkCat, msg);
+ }
+
+ moreData.value = this._readBuffers.byteLength > 0;
+
+ return byteBuffer.remaining === 0;
+ },
+ type: function()
+ {
+ return this._secure ? "wss" : "ws";
+ },
+ getInfo: function()
+ {
+ Debug.assert(this._fd !== null);
+ var info = this.createInfo();
+
+ //
+ // The WebSocket API doens't provide this info
+ //
+ info.localAddress = "";
+ info.localPort = -1;
+ info.remoteAddress = this._addr.host;
+ info.remotePort = this._addr.port;
+ return info;
+ },
+ createInfo: function()
+ {
+ return new IceWS.ConnectionInfo();
+ },
+ checkSendSize: function(stream, messageSizeMax)
+ {
+ if(stream.size > messageSizeMax)
+ {
+ ExUtil.throwMemoryLimitException(stream.size, messageSizeMax);
+ }
+ },
+ toString: function()
+ {
+ return this._desc;
+ },
+ socketConnected: function(e)
+ {
+ if(this._state == StateClosePending)
+ {
+ this.close();
+ return;
+ }
+
+ Debug.assert(this._connectedCallback !== null);
+ this._connectedCallback();
+ },
+ socketBytesAvailable: function(buf)
+ {
+ Debug.assert(this._bytesAvailableCallback !== null);
+ if(buf.byteLength > 0)
+ {
+ this._readBuffers.push(buf);
+ if(this._registered)
+ {
+ this._bytesAvailableCallback();
+ }
+ else if(!this._hasBytesAvailable)
+ {
+ this._hasBytesAvailable = true;
+ }
+ }
+ },
+ socketClosed: function(err)
+ {
+ if(this._state == StateClosePending)
+ {
+ this.close();
+ return;
+ }
+
+ this._exception = translateError(this._state, err);
+ if(this._state < StateConnected)
+ {
+ this._connectedCallback();
+ }
+ else if(this._registered)
+ {
+ this._bytesAvailableCallback();
+ }
+ },
+ });
+
+ function fdToString(address)
+ {
+ return "local address = <not available>\nremote address = " + address.host + ":" + address.port;
+ }
+
+ function translateError(state, err)
+ {
+ if(state < StateConnected)
+ {
+ return new Ice.ConnectFailedException(err.code, err);
+ }
+ else
+ {
+ if(err === 1000) // CLOSE_NORMAL
+ {
+ throw new Ice.ConnectionLostException();
+ }
+ return new Ice.SocketException(err.code, err);
+ }
+ }
+
+ Transceiver.createOutgoing = function(instance, secure, addr, resource)
+ {
+ var transceiver = new Transceiver(instance);
+
+ var url = secure ? "wss" : "ws";
+ url += "://" + addr.host;
+ if(addr.port !== 80)
+ {
+ url += ":" + addr.port;
+ }
+ url += resource ? resource : "/";
+ transceiver._url = url;
+ transceiver._fd = null;
+ transceiver._addr = addr;
+ transceiver._desc = "remote address: " + addr.host + ":" + addr.port + " <not connected>";
+ transceiver._state = StateNeedConnect;
+ transceiver._secure = secure;
+ transceiver._exception = null;
+
+ return transceiver;
+ };
+
+ IceWS.Transceiver = Transceiver;
+ global.IceWS = IceWS;
+}(typeof (global) === "undefined" ? window : global));
diff --git a/js/src/Ice/package.json b/js/src/Ice/package.json
new file mode 100644
index 00000000000..c5e32a6ea18
--- /dev/null
+++ b/js/src/Ice/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "Ice",
+ "version": "0.1.0",
+ "main": "Ice.js"
+}
diff --git a/js/src/IceGrid/.gitignore b/js/src/IceGrid/.gitignore
new file mode 100644
index 00000000000..2cd3235f4ad
--- /dev/null
+++ b/js/src/IceGrid/.gitignore
@@ -0,0 +1,10 @@
+Admin.js
+Descriptor.js
+Exception.js
+FileParser.js
+Locator.js
+Observer.js
+Query.js
+Registry.js
+Session.js
+UserAccountMapper.js
diff --git a/js/src/IceGrid/IceGrid.js b/js/src/IceGrid/IceGrid.js
new file mode 100644
index 00000000000..413b0fd0aa9
--- /dev/null
+++ b/js/src/IceGrid/IceGrid.js
@@ -0,0 +1,21 @@
+// **********************************************************************
+//
+// 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(){
+ require("IceGrid/Admin");
+ require("IceGrid/Descriptor");
+ require("IceGrid/Exception");
+ require("IceGrid/FileParser");
+ require("IceGrid/Locator");
+ require("IceGrid/Observer");
+ require("IceGrid/Query");
+ require("IceGrid/Registry");
+ require("IceGrid/Session");
+ require("IceGrid/UserAccountMapper");
+}());
diff --git a/js/src/IceGrid/Makefile b/js/src/IceGrid/Makefile
new file mode 100644
index 00000000000..0d952c92ced
--- /dev/null
+++ b/js/src/IceGrid/Makefile
@@ -0,0 +1,43 @@
+# **********************************************************************
+#
+# 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.
+#
+# **********************************************************************
+
+top_srcdir = ../..
+
+LIBNAME = IceGrid
+
+TARGETS = $(call mklibtargets,$(LIBNAME))
+
+SLICES = $(SDIR)/Admin.ice \
+ $(SDIR)/Descriptor.ice \
+ $(SDIR)/Exception.ice \
+ $(SDIR)/FileParser.ice \
+ $(SDIR)/Locator.ice \
+ $(SDIR)/Observer.ice \
+ $(SDIR)/Query.ice \
+ $(SDIR)/Registry.ice \
+ $(SDIR)/Session.ice \
+ $(SDIR)/UserAccountMapper.ice
+
+SDIR = $(slicedir)/IceGrid
+
+GEN_SRCS = $(patsubst $(SDIR)/%.ice, %.js, $(SLICES))
+
+SRCS := $(GEN_SRCS)
+INSTALL_SRCS := IceGrid.js $(GEN_SRCS)
+
+include $(top_srcdir)/config/Make.rules.js
+
+SLICE2JSFLAGS := $(SLICE2JSFLAGS) --ice -I$(slicedir)
+
+lint:: $(INSTALL_SRCS)
+ jshint $(LINTFLAGS) $(INSTALL_SRCS)
+
+install:: all
+ $(call installlib,$(DESTDIR)$(install_libdir),$(libdir),$(LIBNAME))
+ $(call installmodule,$(DESTDIR)$(install_moduledir),$(INSTALL_SRCS),$(LIBNAME))
diff --git a/js/src/IceGrid/Makefile.mak b/js/src/IceGrid/Makefile.mak
new file mode 100644
index 00000000000..f64be2a73c6
--- /dev/null
+++ b/js/src/IceGrid/Makefile.mak
@@ -0,0 +1,42 @@
+# **********************************************************************
+#
+# 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.
+#
+# **********************************************************************
+
+top_srcdir = ..\..
+
+LIBNAME = IceGrid
+
+GEN_SRCS = Admin.js \
+ Descriptor.js \
+ Exception.js \
+ FileParser.js \
+ Locator.js \
+ Observer.js \
+ Query.js \
+ Registry.js \
+ Session.js \
+ UserAccountMapper.js
+
+SDIR = $(slicedir)\IceGrid
+
+SRCS = $(GEN_SRCS)
+INSTALL_SRCS = IceGrid.js $(GEN_SRCS)
+
+!include $(top_srcdir)\config\Make.rules.mak.js
+
+SLICE2JSFLAGS = $(SLICE2JSFLAGS) --ice -I"$(slicedir)"
+
+MODULEDIR = $(install_moduledir)\$(LIBNAME)
+
+install:: all
+ @if not exist $(MODULEDIR) \
+ @echo "Creating $(MODULEDIR)" && \
+ mkdir "$(MODULEDIR)"
+ @for %i in ( $(INSTALL_SRCS) ) do \
+ copy %i "$(MODULEDIR)"
+ copy package.json "$(MODULEDIR)"
diff --git a/js/src/IceGrid/package.json b/js/src/IceGrid/package.json
new file mode 100644
index 00000000000..d928926a5e1
--- /dev/null
+++ b/js/src/IceGrid/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "IceGrid",
+ "version": "0.1.0",
+ "main": "IceGrid.js"
+}
diff --git a/js/src/IceStorm/.gitignore b/js/src/IceStorm/.gitignore
new file mode 100644
index 00000000000..1e3e811ef95
--- /dev/null
+++ b/js/src/IceStorm/.gitignore
@@ -0,0 +1,2 @@
+IceStorm.js
+Metrics.js
diff --git a/js/src/IceStorm/Makefile b/js/src/IceStorm/Makefile
new file mode 100644
index 00000000000..876c8e05439
--- /dev/null
+++ b/js/src/IceStorm/Makefile
@@ -0,0 +1,35 @@
+# **********************************************************************
+#
+# 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.
+#
+# **********************************************************************
+
+top_srcdir = ../..
+
+LIBNAME = IceStorm
+
+TARGETS = $(call mklibtargets,$(LIBNAME))
+
+SLICES = $(SDIR)/IceStorm.ice \
+ $(SDIR)/Metrics.ice
+
+SDIR = $(slicedir)/IceStorm
+
+GEN_SRCS = $(patsubst $(SDIR)/%.ice, %.js, $(SLICES))
+
+SRCS := $(GEN_SRCS)
+INSTALL_SRCS := IceStorm.js $(GEN_SRCS)
+
+include $(top_srcdir)/config/Make.rules.js
+
+SLICE2JSFLAGS := $(SLICE2JSFLAGS) --ice -I$(slicedir)
+
+lint:: $(INSTALL_SRCS)
+ jshint $(LINTFLAGS) $(INSTALL_SRCS)
+
+install:: all
+ $(call installlib,$(DESTDIR)$(install_libdir),$(libdir),$(LIBNAME))
+ $(call installmodule,$(DESTDIR)$(install_moduledir),$(INSTALL_SRCS),$(LIBNAME))
diff --git a/js/src/IceStorm/Makefile.mak b/js/src/IceStorm/Makefile.mak
new file mode 100644
index 00000000000..073ab55fca9
--- /dev/null
+++ b/js/src/IceStorm/Makefile.mak
@@ -0,0 +1,34 @@
+# **********************************************************************
+#
+# 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.
+#
+# **********************************************************************
+
+top_srcdir = ..\..
+
+LIBNAME = IceStorm
+
+GEN_SRCS = IceStorm.js \
+ Metrics.js
+
+SDIR = $(slicedir)\IceStorm
+
+SRCS = $(GEN_SRCS)
+INSTALL_SRCS = IceStorm.js $(GEN_SRCS)
+
+!include $(top_srcdir)\config\Make.rules.mak.js
+
+SLICE2JSFLAGS = $(SLICE2JSFLAGS) --ice -I"$(slicedir)"
+
+MODULEDIR = $(install_moduledir)\$(LIBNAME)
+
+install:: all
+ @if not exist $(MODULEDIR) \
+ @echo "Creating $(MODULEDIR)" && \
+ mkdir "$(MODULEDIR)"
+ @for %i in ( $(INSTALL_SRCS) ) do \
+ copy %i "$(MODULEDIR)"
+ copy package.json "$(MODULEDIR)"
diff --git a/js/src/IceStorm/package.json b/js/src/IceStorm/package.json
new file mode 100644
index 00000000000..c41a8446174
--- /dev/null
+++ b/js/src/IceStorm/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "IceStorm",
+ "version": "0.1.0",
+ "main": "IceStorm.js"
+}
diff --git a/js/src/Makefile b/js/src/Makefile
new file mode 100644
index 00000000000..8144440381c
--- /dev/null
+++ b/js/src/Makefile
@@ -0,0 +1,33 @@
+# **********************************************************************
+#
+# 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.
+#
+# **********************************************************************
+
+top_srcdir = ..
+
+include $(top_srcdir)/config/Make.rules.js
+
+SUBDIRS = Ice Glacier2 IceStorm IceGrid
+
+.PHONY: $(EVERYTHING) $(SUBDIRS)
+
+
+all:: $(SUBDIRS)
+
+$(SUBDIRS):
+ @echo "making all in $@"
+ @$(MAKE) all --directory=$@
+
+$(EVERYTHING_EXCEPT_ALL)::
+ @for subdir in $(SUBDIRS); \
+ do \
+ if test -d $$subdir ; \
+ then \
+ echo "making $@ in $$subdir"; \
+ ( cd $$subdir && $(MAKE) $@ ) || exit 1; \
+ fi; \
+ done
diff --git a/js/src/Makefile.mak b/js/src/Makefile.mak
new file mode 100644
index 00000000000..d87264e34a1
--- /dev/null
+++ b/js/src/Makefile.mak
@@ -0,0 +1,19 @@
+# **********************************************************************
+#
+# 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.
+#
+# **********************************************************************
+
+top_srcdir = ..
+
+!include $(top_srcdir)\config\Make.rules.mak.js
+
+SUBDIRS = Ice Glacier2 IceStorm IceGrid
+
+$(EVERYTHING)::
+ @for %i in ( $(SUBDIRS) ) do \
+ @echo "making $@ in %i" && \
+ cmd /c "cd %i && $(MAKE) -nologo -f Makefile.mak $@" || exit 1