summaryrefslogtreecommitdiff
path: root/java-compat/src
diff options
context:
space:
mode:
Diffstat (limited to 'java-compat/src')
-rw-r--r--java-compat/src/Glacier2/build.gradle29
-rw-r--r--java-compat/src/Glacier2/src/main/java/Glacier2/Application.java515
-rw-r--r--java-compat/src/Glacier2/src/main/java/Glacier2/SessionCallback.java48
-rw-r--r--java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java398
-rw-r--r--java-compat/src/Glacier2/src/main/java/Glacier2/SessionHelper.java627
-rw-r--r--java-compat/src/Ice/build.gradle26
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/AMDCallback.java23
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/AMD_Object_ice_invoke.java40
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Application.java696
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/AsyncCallback.java22
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/AsyncResult.java105
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/BatchRequest.java33
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/BatchRequestInterceptor.java28
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Blobject.java53
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/BlobjectAsync.java50
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/BooleanHolder.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/BooleanOptional.java106
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ByteHolder.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ByteOptional.java106
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Callback.java57
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Callback_Communicator_flushBatchRequests.java55
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Callback_Connection_flushBatchRequests.java55
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_flushBatchRequests.java22
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_getConnection.java31
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_id.java31
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_ids.java31
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_invoke.java36
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_isA.java30
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_ping.java17
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ClassResolver.java29
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java389
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/CompactIdResolver.java29
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ConnectionI.java3030
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/DispatchInterceptor.java71
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/DispatchInterceptorAsyncCallback.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/DispatchStatus.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Dispatcher.java34
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/DoubleHolder.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/DoubleOptional.java106
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Exception.java91
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/FloatHolder.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/FloatOptional.java106
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/FormatType.java29
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Holder.java40
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ImplicitContextI.java318
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/InitializationData.java96
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/InputStream.java3422
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/IntHolder.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/IntOptional.java106
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/LocalException.java25
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/LocalObjectHolder.java33
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/LoggerI.java163
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/LoggerPlugin.java70
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/LongHolder.java33
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/LongOptional.java106
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/NativePropertiesAdmin.java16
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Object.java162
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java1559
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectHolder.java41
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectHolderBase.java38
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectImpl.java429
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectInputStream.java43
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectPrx.java1214
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectPrxHelper.java157
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectPrxHelperBase.java3000
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectPrxHolder.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectReader.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectWriter.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/OnewayCallback.java77
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Optional.java202
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/OptionalFormat.java70
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/OptionalObject.java70
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/OutputStream.java2426
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/PluginFactory.java27
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/PluginManagerI.java549
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/PropertiesAdminUpdateCallback.java15
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/PropertiesI.java764
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ProxyIdentityFacetKey.java97
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ProxyIdentityKey.java89
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ReadValueCallback.java27
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Request.java23
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ShortHolder.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ShortOptional.java106
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/SignalPolicy.java31
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/SliceInfo.java46
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/SlicedData.java26
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/StringHolder.java35
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/SysLoggerI.java244
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/SystemException.java25
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ThreadHookPlugin.java64
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ThreadNotification.java34
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TieBase.java30
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallback.java30
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackArg1.java20
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackArg1UE.java20
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackBool.java20
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackBoolUE.java15
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackByte.java20
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackByteUE.java15
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackDouble.java20
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackDoubleUE.java15
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackFloat.java20
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackFloatUE.java15
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackInt.java20
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackIntUE.java15
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackLong.java20
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackLongUE.java15
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackShort.java20
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackShortUE.java15
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackUE.java15
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/TwowayCallbackVoidUE.java25
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/UnknownSlicedValue.java54
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/UserException.java116
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/UserExceptionFactory.java26
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Util.java715
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ValueFactoryManagerI.java30
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/_AMD_Object_ice_invoke.java38
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/_Callback_Object_ice_invoke.java28
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ACMConfig.java82
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ACMMonitor.java20
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Acceptor.java23
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/AsyncResultI.java469
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/AsyncStatus.java17
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/BZip2.java281
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/BatchRequestQueue.java239
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/BufSizeWarnInfo.java25
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Buffer.java223
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/CallbackBase.java25
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/CancellationHandler.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/CollocatedObserverI.java34
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/CollocatedRequestHandler.java436
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/CommunicatorFlushBatch.java164
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java840
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ConnectRequestHandler.java385
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ConnectionACMMonitor.java126
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ConnectionFlushBatch.java102
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ConnectionObserverI.java62
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ConnectionRequestHandler.java82
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Connector.java25
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/DefaultsAndOverrides.java242
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/DictionaryPatcher.java41
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/DispatchObserverI.java55
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/DispatchWorkItem.java44
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/EndpointFactory.java21
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/EndpointFactoryManager.java183
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/EndpointHostResolver.java202
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/EndpointI.java197
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/EndpointIHolder.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/EndpointI_connectors.java16
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/EventHandler.java44
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/EventHandlerOpPair.java22
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Ex.java49
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/FactoryACMMonitor.java232
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/FixedReference.java319
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_BoolCallback.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_ByteCallback.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_CallbackBase.java50
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_DoubleCallback.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_FloatCallback.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_GenericCallback1.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_IntCallback.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_LongCallback.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_OnewayCallback.java44
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_ShortCallback.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallback.java44
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackArg1.java43
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackArg1UE.java35
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackBool.java42
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackBoolUE.java35
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackByte.java42
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackByteUE.java35
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackDouble.java42
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackDoubleUE.java35
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackFloat.java43
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackFloatUE.java34
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackInt.java43
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackIntUE.java35
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackLong.java43
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackLongUE.java35
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackShort.java43
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackShortUE.java35
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackUE.java34
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackVoidUE.java35
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Functional_VoidCallback.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/HTTPNetworkProxy.java135
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/HashUtil.java120
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/HttpParser.java732
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/IPEndpointI.java377
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Incoming.java415
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/IncomingAsync.java204
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java663
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/IncomingConnectionFactory.java658
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/InputStreamWrapper.java96
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Instance.java1863
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/InvocationObserverI.java249
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ListPatcher.java46
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java708
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/LocatorManager.java140
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/LocatorTable.java132
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminI.java465
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminLogger.java16
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminLoggerI.java254
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/MetricsAdminI.java400
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/MetricsMap.java517
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/MetricsViewI.java126
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Network.java1353
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/NetworkProxy.java60
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ObjectAdapterFactory.java268
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ObjectInputStream.java52
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ObserverHelper.java65
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/OpaqueEndpointI.java422
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/OutgoingAsync.java444
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/OutgoingAsyncBase.java107
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/OutgoingConnectionFactory.java1149
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/OutputStreamWrapper.java178
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ProcessI.java46
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/PropertiesAdminI.java214
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Property.java42
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java1254
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Protocol.java198
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ProtocolInstance.java142
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ProtocolPluginFacade.java34
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ProtocolPluginFacadeI.java59
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ProxyFactory.java302
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ProxyFlushBatch.java62
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ProxyGetConnection.java65
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ProxyOutgoingAsyncBase.java318
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/QueueExecutorService.java118
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/QueueRequestHandler.java96
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ReadyCallback.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Reference.java547
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ReferenceFactory.java916
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/RemoteObserverI.java34
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ReplyStatus.java22
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/RequestHandler.java22
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/RequestHandlerFactory.java96
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ResponseHandler.java18
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/RetryException.java27
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/RetryQueue.java84
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/RetryTask.java80
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java974
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/RouterInfo.java280
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/RouterManager.java76
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/SOCKSNetworkProxy.java128
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Selector.java408
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/SequencePatcher.java41
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ServantError.java28
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java322
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/SocketOperation.java20
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/StreamSocket.java329
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/TcpAcceptor.java150
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/TcpConnector.java101
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/TcpEndpointFactory.java58
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/TcpEndpointI.java317
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/TcpTransceiver.java126
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ThreadObserverI.java68
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ThreadPool.java823
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolCurrent.java51
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolWorkItem.java15
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolWorkQueue.java116
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Time.java19
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/TraceLevels.java45
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java514
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Transceiver.java32
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/TwowayCallback.java35
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/UdpConnector.java113
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/UdpEndpointFactory.java58
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/UdpEndpointI.java395
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java653
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Util.java301
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ValueFactoryManagerI.java33
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ValueWriter.java191
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/WSAcceptor.java82
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/WSConnector.java77
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/WSEndpoint.java324
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/WSEndpointFactory.java59
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/WSTransceiver.java1616
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/WebSocketException.java28
-rw-r--r--java-compat/src/Ice/src/main/java/IceMX/MetricsHelper.java188
-rw-r--r--java-compat/src/Ice/src/main/java/IceMX/Observer.java136
-rw-r--r--java-compat/src/Ice/src/main/java/IceMX/ObserverFactory.java142
-rw-r--r--java-compat/src/Ice/src/main/java/IceMX/ObserverFactoryWithDelegate.java48
-rw-r--r--java-compat/src/Ice/src/main/java/IceMX/ObserverWithDelegate.java74
-rw-r--r--java-compat/src/Ice/src/main/java/IceMX/ObserverWithDelegateI.java14
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/AcceptorI.java85
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/CertificateVerifier.java26
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/ConnectorI.java78
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/EndpointFactoryI.java60
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/EndpointI.java260
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/Instance.java62
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/NativeConnectionInfo.java28
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/PasswordCallback.java45
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/Plugin.java94
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/PluginFactory.java34
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/PluginI.java108
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/RFC2253.java434
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/SSLEngine.java1314
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/TransceiverI.java588
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/TrustManager.java362
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/Util.java72
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/X509KeyManagerI.java114
-rw-r--r--java-compat/src/Ice/src/main/java/IceSSL/X509TrustManagerI.java82
-rw-r--r--java-compat/src/Ice/src/main/java/IceUtilInternal/Assert.java45
-rw-r--r--java-compat/src/Ice/src/main/java/IceUtilInternal/Base64.java270
-rw-r--r--java-compat/src/Ice/src/main/java/IceUtilInternal/Options.java403
-rw-r--r--java-compat/src/Ice/src/main/java/IceUtilInternal/OutputBase.java188
-rw-r--r--java-compat/src/Ice/src/main/java/IceUtilInternal/StopWatch.java42
-rw-r--r--java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java540
-rw-r--r--java-compat/src/Ice/src/main/java/IceUtilInternal/XMLOutput.java275
-rw-r--r--java-compat/src/IceBT/build.gradle37
-rw-r--r--java-compat/src/IceBT/src/main/java/IceBT/AcceptorI.java224
-rw-r--r--java-compat/src/IceBT/src/main/java/IceBT/ConnectorI.java109
-rw-r--r--java-compat/src/IceBT/src/main/java/IceBT/EndpointFactoryI.java59
-rw-r--r--java-compat/src/IceBT/src/main/java/IceBT/EndpointI.java551
-rw-r--r--java-compat/src/IceBT/src/main/java/IceBT/Instance.java54
-rw-r--r--java-compat/src/IceBT/src/main/java/IceBT/PluginFactory.java34
-rw-r--r--java-compat/src/IceBT/src/main/java/IceBT/PluginI.java43
-rw-r--r--java-compat/src/IceBT/src/main/java/IceBT/TransceiverI.java693
-rw-r--r--java-compat/src/IceBT/src/main/java/IceBT/Util.java14
-rw-r--r--java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothAdapter.java55
-rw-r--r--java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothDevice.java25
-rw-r--r--java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothServerSocket.java19
-rw-r--r--java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothSocket.java40
-rw-r--r--java-compat/src/IceBox/build.gradle29
-rw-r--r--java-compat/src/IceBox/src/main/java/IceBox/Admin.java184
-rw-r--r--java-compat/src/IceBox/src/main/java/IceBox/Server.java79
-rw-r--r--java-compat/src/IceBox/src/main/java/IceBox/ServiceManagerI.java1178
-rw-r--r--java-compat/src/IceDiscovery/build.gradle27
-rw-r--r--java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LocatorI.java43
-rw-r--r--java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LocatorRegistryI.java179
-rw-r--r--java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupI.java399
-rw-r--r--java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupReplyI.java35
-rw-r--r--java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginFactory.java20
-rw-r--r--java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginI.java138
-rw-r--r--java-compat/src/IceGrid/build.gradle30
-rw-r--r--java-compat/src/IceLocatorDiscovery/build.gradle27
-rw-r--r--java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginFactory.java20
-rw-r--r--java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginI.java456
-rw-r--r--java-compat/src/IcePatch2/build.gradle29
-rw-r--r--java-compat/src/IceStorm/build.gradle29
340 files changed, 68699 insertions, 0 deletions
diff --git a/java-compat/src/Glacier2/build.gradle b/java-compat/src/Glacier2/build.gradle
new file mode 100644
index 00000000000..d087e401336
--- /dev/null
+++ b/java-compat/src/Glacier2/build.gradle
@@ -0,0 +1,29 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+sourceCompatibility = iceSourceCompatibility
+targetCompatibility = iceTargetCompatibility
+
+project.ext.displayName = "Glacier2 Compat"
+project.ext.description = "Firewall traversal for Ice"
+
+slice {
+ java {
+ set1 {
+ args = "--ice --tie --checksum Glacier2.SliceChecksums"
+ files = fileTree(dir: "${sliceDir}/Glacier2", includes:['*.ice'], excludes:["*F.ice"])
+ }
+ }
+}
+
+dependencies {
+ compile project(':ice-compat')
+}
+
+apply from: "$rootProject.projectDir/../java/gradle/library.gradle"
diff --git a/java-compat/src/Glacier2/src/main/java/Glacier2/Application.java b/java-compat/src/Glacier2/src/main/java/Glacier2/Application.java
new file mode 100644
index 00000000000..2d5768fdf1c
--- /dev/null
+++ b/java-compat/src/Glacier2/src/main/java/Glacier2/Application.java
@@ -0,0 +1,515 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Glacier2;
+
+/**
+ * An extension of Ice.Application that makes it easy to write
+ * Glacier2 applications.
+ *
+ * <p> Applications must create a derived class that implements the
+ * {@link #createSession} and {@link #runWithSession} methods.<p>
+ *
+ * The base class invokes {@link #createSession} to create a new
+ * Glacier2 session and then invokes {@link #runWithSession} in
+ * which the subclass performs its application logic. The base class
+ * automatically destroys the session when {@link #runWithSession}
+ * returns.
+ *
+ * If {@link #runWithSession} calls {@link #restart} or raises any of
+ * the exceptions Ice.ConnectionRefusedException,
+ * Ice.ConnectionLostException, Ice.UnknownLocalException,
+ * Ice.RequestFailedException, or Ice.TimeoutException, the base
+ * class destroys the current session and restarts the application
+ * with another call to {@link #createSession} followed by
+ * {@link #runWithSession}.
+ *
+ * The application can optionally override the {@link #sessionDestroyed}
+ * callback method if it needs to take action when connectivity with
+ * the Glacier2 router is lost.
+ *
+ * A program can contain only one instance of this class.
+ *
+ * @see Ice.Application
+ * @see Glacier2.Router
+ * @see Glacier2.Session
+ * @see Ice.Communicator
+ * @see Ice.Logger
+ * @see #runWithSession
+ **/
+public abstract class Application extends Ice.Application
+{
+ /**
+ * This exception is raised if the session should be restarted.
+ */
+ public class RestartSessionException extends Exception
+ {
+ }
+
+ /**
+ * Initializes an instance that calls {@link Communicator#shutdown} if
+ * a signal is received.
+ **/
+ public
+ Application()
+ {
+ }
+
+ /**
+ * Initializes an instance that handles signals according to the signal
+ * policy.
+ *
+ * @param signalPolicy Determines how to respond to signals.
+ *
+ * @see SignalPolicy
+ **/
+ public
+ Application(Ice.SignalPolicy signalPolicy)
+ {
+ super(signalPolicy);
+ }
+
+ /**
+ * Called once the communicator has been initialized and the Glacier2 session
+ * has been established. A derived class must implement <code>runWithSession</code>,
+ * which is the application's starting method.
+ *
+ * @param args The argument vector for the application. <code>Application</code>
+ * scans the argument vector passed to <code>main</code> for options that are
+ * specific to the Ice run time and removes them; therefore, the vector passed
+ * to <code>run</code> is free from Ice-related options and contains only options
+ * and arguments that are application-specific.
+ *
+ * @return The <code>runWithSession</code> method should return zero for successful
+ * termination, and non-zero otherwise. <code>Application.main</code> returns the
+ * value returned by <code>runWithSession</code>.
+ **/
+ public abstract int
+ runWithSession(String[] args)
+ throws RestartSessionException;
+
+ /**
+ * Run should not be overridden for Glacier2.Application. Instead
+ * <code>runWithSession</code> should be used.
+ */
+ @Override
+ final public int
+ run(String[] args)
+ {
+ // This shouldn't be called.
+ assert false;
+ return 0;
+ }
+
+ /**
+ * Called to restart the application's Glacier2 session. This
+ * method never returns. The exception produce an application restart
+ * when called from the Application main thread.
+ *
+ * @throws RestartSessionException This exception is always thrown.
+ **/
+ public void
+ restart()
+ throws RestartSessionException
+ {
+ throw new RestartSessionException();
+ }
+
+ /**
+ * Creates a new Glacier2 session. A call to
+ * <code>createSession</code> always precedes a call to
+ * <code>runWithSession</code>. If <code>Ice.LocalException</code>
+ * is thrown from this method, the application is terminated.
+ *
+ * @return The Glacier2 session.
+ **/
+ abstract public Glacier2.SessionPrx
+ createSession();
+
+ /**
+ * Called when the session refresh thread detects that the session has been
+ * destroyed. A subclass can override this method to take action after the
+ * loss of connectivity with the Glacier2 router. This method is called
+ * according to the Ice invocation dipsatch rules (in other words, it
+ * uses the same rules as an servant upcall or AMI callback).
+ **/
+ public void
+ sessionDestroyed()
+ {
+ }
+
+ /**
+ * Returns the Glacier2 router proxy
+ * @return The router proxy.
+ **/
+ public static Glacier2.RouterPrx
+ router()
+ {
+ return _router;
+ }
+
+ /**
+ * Returns the Glacier2 session proxy
+ * @return The session proxy.
+ **/
+ public static Glacier2.SessionPrx
+ session()
+ {
+ return _session;
+ }
+
+ /**
+ * Returns the category to be used in the identities of all of the client's
+ * callback objects. Clients must use this category for the router to
+ * forward callback requests to the intended client.
+ * @return The category.
+ * @throws SessionNotExistException No session exists.
+ **/
+ public String
+ categoryForClient()
+ throws SessionNotExistException
+ {
+ if(_router == null)
+ {
+ throw new SessionNotExistException();
+ }
+ return _category;
+ }
+
+ /**
+ * Create a new Ice identity for callback objects with the given
+ * identity name field.
+ * @return The identity.
+ * @throws SessionNotExistException No session exists.
+ **/
+ public Ice.Identity
+ createCallbackIdentity(String name)
+ throws SessionNotExistException
+ {
+ return new Ice.Identity(name, categoryForClient());
+ }
+
+ /**
+ * Adds a servant to the callback object adapter's Active Servant Map with a UUID.
+ * @param servant The servant to add.
+ * @return The proxy for the servant.
+ * @throws SessionNotExistException No session exists.
+ **/
+ public Ice.ObjectPrx
+ addWithUUID(Ice.Object servant)
+ throws SessionNotExistException
+ {
+ return objectAdapter().add(servant, createCallbackIdentity(java.util.UUID.randomUUID().toString()));
+ }
+
+ /**
+ * Creates an object adapter for callback objects.
+ * @return The object adapter.
+ * @throws SessionNotExistException No session exists.
+ */
+ public Ice.ObjectAdapter
+ objectAdapter()
+ throws SessionNotExistException
+ {
+ if(_router == null)
+ {
+ throw new SessionNotExistException();
+ }
+
+ synchronized(this)
+ {
+ if(_adapter == null)
+ {
+ _adapter = communicator().createObjectAdapterWithRouter("", _router);
+ _adapter.activate();
+ }
+ }
+ return _adapter;
+ }
+
+ private class CloseCallbackI implements Ice.CloseCallback
+ {
+ @Override
+ public void closed(Ice.Connection con)
+ {
+ sessionDestroyed();
+ }
+ }
+
+ @Override
+ protected int
+ doMain(Ice.StringSeqHolder argHolder, Ice.InitializationData initData)
+ {
+ //
+ // Set the default properties for all Glacier2 applications.
+ //
+ initData.properties.setProperty("Ice.RetryIntervals", "-1");
+
+ boolean restart;
+ Ice.Holder<Integer> ret = new Ice.Holder<Integer>();
+ do
+ {
+ //
+ // A copy of the initialization data and the string array
+ // needs to be passed to doMainInternal, as these can be
+ // changed by the application.
+ //
+ Ice.InitializationData id = initData.clone();
+ id.properties = id.properties._clone();
+ Ice.StringSeqHolder h = new Ice.StringSeqHolder();
+ h.value = argHolder.value.clone();
+
+ restart = doMain(h, id, ret);
+ }
+ while(restart);
+ return ret.value;
+ }
+
+ private boolean
+ doMain(Ice.StringSeqHolder argHolder, Ice.InitializationData initData, Ice.Holder<Integer> status)
+ {
+ //
+ // Reset internal state variables from Ice.Application. The
+ // remainder are reset at the end of this method.
+ //
+ _callbackInProgress = false;
+ _destroyed = false;
+ _interrupted = false;
+
+ boolean restart = false;
+ status.value = 0;
+
+ try
+ {
+ _communicator = Ice.Util.initialize(argHolder, initData);
+
+ _router = Glacier2.RouterPrxHelper.uncheckedCast(communicator().getDefaultRouter());
+ if(_router == null)
+ {
+ Ice.Util.getProcessLogger().error("no glacier2 router configured");
+ status.value = 1;
+ }
+ else
+ {
+ //
+ // The default is to destroy when a signal is received.
+ //
+ if(_signalPolicy == Ice.SignalPolicy.HandleSignals)
+ {
+ destroyOnInterrupt();
+ }
+
+ //
+ // If createSession throws, we're done.
+ //
+ try
+ {
+ _session = createSession();
+ _createdSession = true;
+ }
+ catch(Ice.LocalException ex)
+ {
+ Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ status.value = 1;
+ }
+
+ if(_createdSession)
+ {
+ int acmTimeout = 0;
+ try
+ {
+ acmTimeout = _router.getACMTimeout();
+ }
+ catch(Ice.OperationNotExistException ex)
+ {
+ }
+ if(acmTimeout <= 0)
+ {
+ acmTimeout = (int)_router.getSessionTimeout();
+ }
+ if(acmTimeout > 0)
+ {
+ Ice.Connection connection = _router.ice_getCachedConnection();
+ assert(connection != null);
+ connection.setACM(new Ice.IntOptional(acmTimeout),
+ null,
+ new Ice.Optional<Ice.ACMHeartbeat>(Ice.ACMHeartbeat.HeartbeatAlways));
+ connection.setCloseCallback(new CloseCallbackI());
+ }
+ _category = _router.getCategoryForClient();
+ status.value = runWithSession(argHolder.value);
+ }
+ }
+ }
+ //
+ // We want to restart on those exceptions that indicate a
+ // break down in communications, but not those exceptions that
+ // indicate a programming logic error (i.e., marshal, protocol
+ // failure, etc).
+ //
+ catch(RestartSessionException ex)
+ {
+ restart = true;
+ }
+ catch(Ice.ConnectionRefusedException ex)
+ {
+ Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ restart = true;
+ }
+ catch(Ice.ConnectionLostException ex)
+ {
+ Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ restart = true;
+ }
+ catch(Ice.UnknownLocalException ex)
+ {
+ Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ restart = true;
+ }
+ catch(Ice.RequestFailedException ex)
+ {
+ Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ restart = true;
+ }
+ catch(Ice.TimeoutException ex)
+ {
+ Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ restart = true;
+ }
+ catch(Ice.LocalException ex)
+ {
+ Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ status.value = 1;
+ }
+ catch(java.lang.Exception ex)
+ {
+ Ice.Util.getProcessLogger().error("unknown exception:\n" + IceInternal.Ex.toString(ex));
+ status.value = 1;
+ }
+ catch(java.lang.Error err)
+ {
+ //
+ // We catch Error to avoid hangs in some non-fatal situations
+ //
+ Ice.Util.getProcessLogger().error("Java error:\n" + IceInternal.Ex.toString(err));
+ status.value = 1;
+ }
+
+ //
+ // This clears any set interrupt.
+ //
+ if(_signalPolicy == Ice.SignalPolicy.HandleSignals)
+ {
+ defaultInterrupt();
+ }
+
+ synchronized(_mutex)
+ {
+ while(_callbackInProgress)
+ {
+ try
+ {
+ _mutex.wait();
+ }
+ catch(java.lang.InterruptedException ex)
+ {
+ }
+ }
+
+ if(_destroyed)
+ {
+ _communicator = null;
+ }
+ else
+ {
+ _destroyed = true;
+ //
+ // And _communicator != null, meaning will be
+ // destroyed next, _destroyed = true also ensures that
+ // any remaining callback won't do anything.
+ //
+ }
+ }
+
+ if(_createdSession && _router != null)
+ {
+ try
+ {
+ _router.destroySession();
+ }
+ catch(Ice.ConnectionLostException ex)
+ {
+ //
+ // Expected if another thread invoked on an object from the session concurrently.
+ //
+ }
+ catch(Glacier2.SessionNotExistException ex)
+ {
+ //
+ // This can also occur.
+ //
+ }
+ catch(Throwable ex)
+ {
+ //
+ // Not expected.
+ //
+ Ice.Util.getProcessLogger().error("unexpected exception when destroying the session:\n" +
+ IceInternal.Ex.toString(ex));
+ }
+ _router = null;
+ }
+
+ if(_communicator != null)
+ {
+ try
+ {
+ _communicator.destroy();
+ }
+ catch(Ice.LocalException ex)
+ {
+ Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ status.value = 1;
+ }
+ catch(java.lang.Exception ex)
+ {
+ Ice.Util.getProcessLogger().error("unknown exception:\n" + IceInternal.Ex.toString(ex));
+ status.value = 1;
+ }
+ _communicator = null;
+ }
+
+ synchronized(_mutex)
+ {
+ if(_appHook != null)
+ {
+ _appHook.done();
+ }
+ }
+
+ //
+ // Reset internal state. We cannot reset the Application state
+ // here, since _destroyed must remain true until we re-run
+ // this method.
+ //
+ _adapter = null;
+ _router = null;
+ _session = null;
+ _createdSession = false;
+ _category = null;
+
+ return restart;
+ }
+
+ private static Ice.ObjectAdapter _adapter;
+ private static Glacier2.RouterPrx _router;
+ private static Glacier2.SessionPrx _session;
+ private static boolean _createdSession = false;
+ private static String _category;
+}
diff --git a/java-compat/src/Glacier2/src/main/java/Glacier2/SessionCallback.java b/java-compat/src/Glacier2/src/main/java/Glacier2/SessionCallback.java
new file mode 100644
index 00000000000..b1532e1fbd0
--- /dev/null
+++ b/java-compat/src/Glacier2/src/main/java/Glacier2/SessionCallback.java
@@ -0,0 +1,48 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Glacier2;
+
+/**
+ * A callback class to get notifications of status changes in the Glacier2 session.
+ * All callbacks on the <code>Callback</code> interface occur in the main swing thread.
+ */
+public interface SessionCallback
+{
+ /**
+ * Notifies the application that the communicator was created.
+ *
+ * @param session The Glacier2 session.
+ */
+ void createdCommunicator(SessionHelper session);
+
+ /**
+ * Notifies the application that the Glacier2 session has been established.
+ *
+ * @param session The established session.
+ */
+ void connected(SessionHelper session)
+ throws SessionNotExistException;
+
+ /**
+ * Notifies the application that the Glacier2 session has been disconnected.
+ *
+ * @param session The disconnected session.
+ */
+ void disconnected(SessionHelper session);
+
+ /**
+ * Notifies the application that the Glacier2 session establishment failed.
+ *
+ * @param session The session reporting the connection
+ * failure.
+ * @param ex The exception.
+ */
+ void connectFailed(SessionHelper session, Throwable ex);
+}
diff --git a/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java b/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java
new file mode 100644
index 00000000000..b7b086a8798
--- /dev/null
+++ b/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java
@@ -0,0 +1,398 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Glacier2;
+
+/**
+ * A helper class for using Glacier2 with GUI applications.
+ *
+ * Applications should create a session factory for each Glacier2 router to which the application will
+ * connect. To connect with the Glacier2 router, call {@link SessionFactory#connect}. The callback object is
+ * notified of the various life cycle events. Once the session is torn down for whatever reason, the application
+ * can use the session factory to create another connection.
+ */
+public class SessionFactoryHelper
+{
+ /**
+ * Creates a SessionFactory object.
+ *
+ * @param callback The callback object for notifications.
+ * @throws {@link Ice.InitializationException}
+ */
+ public
+ SessionFactoryHelper(SessionCallback callback)
+ throws Ice.InitializationException
+ {
+ initialize(callback, new Ice.InitializationData(), Ice.Util.createProperties());
+ }
+
+ /**
+ * Creates a SessionFactory object.
+ *
+ * @param initData The initialization data to use when creating the communicator.
+ * @param callback The callback object for notifications.
+ * @throws {@link Ice.InitializationException}
+ */
+ public
+ SessionFactoryHelper(Ice.InitializationData initData, SessionCallback callback)
+ throws Ice.InitializationException
+ {
+ initialize(callback, initData, initData.properties);
+ }
+
+ /**
+ * Creates a SessionFactory object.
+ *
+ * @param properties The properties to use when creating the communicator.
+ * @param callback The callback object for notifications.
+ * @throws {@link Ice.InitializationException}
+ */
+ public
+ SessionFactoryHelper(Ice.Properties properties, SessionCallback callback)
+ throws Ice.InitializationException
+ {
+ initialize(callback, new Ice.InitializationData(), properties);
+ }
+
+ private void
+ initialize(SessionCallback callback, Ice.InitializationData initData, Ice.Properties properties)
+ throws Ice.InitializationException
+ {
+ if(callback == null)
+ {
+ throw new Ice.InitializationException("Attempt to create a SessionFactoryHelper with a null " +
+ "SessionCallback argument");
+ }
+
+ if(initData == null)
+ {
+ throw new Ice.InitializationException("Attempt to create a SessionFactoryHelper with a null " +
+ "InitializationData argument");
+ }
+
+ if(properties == null)
+ {
+ throw new Ice.InitializationException("Attempt to create a SessionFactoryHelper with a null Properties " +
+ "argument");
+ }
+
+ _callback = callback;
+ _initData = initData;
+ _initData.properties = properties;
+
+ //
+ // Set default properties;
+ //
+ _initData.properties.setProperty("Ice.RetryIntervals", "-1");
+ }
+
+ /**
+ * Set the router object identity.
+ *
+ * @param identity The Glacier2 router's identity.
+ */
+ synchronized public void
+ setRouterIdentity(Ice.Identity identity)
+ {
+ _identity = identity;
+ }
+
+ /**
+ * Returns the object identity of the Glacier2 router.
+ *
+ * @return The Glacier2 router's identity.
+ */
+ synchronized public Ice.Identity
+ getRouterIdentity()
+ {
+ return _identity;
+ }
+
+ /**
+ * Sets the host on which the Glacier2 router runs.
+ *
+ * @param hostname The host name (or IP address) of the router host.
+ */
+ synchronized public void
+ setRouterHost(String hostname)
+ {
+ _routerHost = hostname;
+ }
+
+ /**
+ * Returns the host on which the Glacier2 router runs.
+ *
+ * @return The Glacier2 router host.
+ */
+ synchronized public String
+ getRouterHost()
+ {
+ return _routerHost;
+ }
+
+ /**
+ * Sets whether to connect with the Glacier2 router securely.
+ *
+ * @param secure If <code>true</code>, the client connects to the router
+ * via SSL; otherwise, the client connects via TCP.
+ * @deprecated deprecated, use SessionFactoryHelper.setProtocol instead
+ */
+ @Deprecated
+ public void
+ setSecure(boolean secure)
+ {
+ setProtocol(secure ? "ssl" : "tcp");
+ }
+
+ /**
+ * Returns whether the session factory will establish a secure connection to the Glacier2 router.
+ *
+ * @return The secure flag.
+ * @deprecated deprecated, use SessionFactoryHelper.getProtocol instead
+ */
+ @Deprecated
+ public boolean
+ getSecure()
+ {
+ return getProtocol().equals("ssl");
+ }
+
+ /**
+ *
+ * Sets the protocol that will be used by the session factory to establish the connection.
+ *
+ * @param protocol.
+ */
+ synchronized public void setProtocol(String protocol)
+ {
+ if(protocol == null)
+ {
+ throw new IllegalArgumentException("You must use a valid protocol");
+ }
+
+ if(!protocol.equals("tcp") &&
+ !protocol.equals("ssl") &&
+ !protocol.equals("wss") &&
+ !protocol.equals("ws"))
+ {
+ throw new IllegalArgumentException("Unknow protocol `" + protocol + "'");
+ }
+
+ _protocol = protocol;
+ }
+
+ /**
+ *
+ * Returns the protocol that will be used by the session factory to establish the connection.
+ *
+ * @return The protocol.
+ */
+ synchronized public String getProtocol()
+ {
+ return _protocol;
+ }
+
+ /**
+ * Sets the connect and connection timeout for the Glacier2 router.
+ *
+ * @param timeoutMillisecs The timeout in milliseconds. A zero
+ * or negative timeout value indicates that the router proxy has no associated timeout.
+ */
+ synchronized public void
+ setTimeout(int timeoutMillisecs)
+ {
+ _timeout = timeoutMillisecs;
+ }
+
+ /**
+ * Returns the connect and connection timeout associated with the Glacier2 router.
+ *
+ * @return The timeout.
+ */
+ synchronized public int
+ getTimeout()
+ {
+ return _timeout;
+ }
+
+ /**
+ * Sets the Glacier2 router port to connect to.
+ *
+ * @param port The port. If 0, then the default port (4063 for TCP or 4064 for SSL) is used.
+ */
+ synchronized public void
+ setPort(int port)
+ {
+ _port = port;
+ }
+
+ /**
+ * Returns the Glacier2 router port to connect to.
+ *
+ * @return The port.
+ */
+ synchronized public int
+ getPort()
+ {
+ return getPortInternal();
+ }
+
+ private int getPortInternal()
+ {
+ return _port == 0 ? ((_protocol.equals("ssl") ||
+ _protocol.equals("wss"))? GLACIER2_SSL_PORT : GLACIER2_TCP_PORT) : _port;
+ }
+
+ /**
+ * Returns the initialization data used to initialize the communicator.
+ *
+ * @return The initialization data.
+ */
+ synchronized public Ice.InitializationData
+ getInitializationData()
+ {
+ return _initData;
+ }
+
+ /**
+ * Sets the request context to use while establishing a connection to the Glacier2 router.
+ *
+ * @param context The request context.
+ */
+ synchronized public void
+ setConnectContext(final java.util.Map<String, String> context)
+ {
+ _context = context;
+ }
+
+ /**
+ * Determines whether the session should create an object adapter that the client
+ * can use for receiving callbacks.
+ *
+ * @param useCallbacks True if the session should create an object adapter.
+ */
+ synchronized public void
+ setUseCallbacks(boolean useCallbacks)
+ {
+ _useCallbacks = useCallbacks;
+ }
+
+ /**
+ * Indicates whether a newly-created session will also create an object adapter that
+ * the client can use for receiving callbacks.
+ *
+ * @return True if the session will create an object adapter.
+ */
+ synchronized public boolean
+ getUseCallbacks()
+ {
+ return _useCallbacks;
+ }
+
+ /**
+ * Connects to the Glacier2 router using the associated SSL credentials.
+ *
+ * Once the connection is established, {@link SessionCallback#connected} is called on the callback object;
+ * upon failure, {@link SessionCallback#connectFailed} is called with the exception.
+ *
+ * @return The connected session.
+ */
+ synchronized public SessionHelper
+ connect()
+ {
+ SessionHelper session = new SessionHelper(_callback, createInitData(), getRouterFinderStr(), _useCallbacks);
+ session.connect(_context);
+ return session;
+ }
+
+ /**
+ * Connect the Glacier2 session using user name and password credentials.
+ *
+ * Once the connection is established, {@link SessionCallback#connected} is called on the callback object;
+ * upon failure, {@link SessionCallback#connectFailed) is called with the exception.
+ *
+ * @param username The user name.
+ * @param password The password.
+ * @return The connected session.
+ */
+ synchronized public SessionHelper
+ connect(final String username, final String password)
+ {
+ SessionHelper session = new SessionHelper(_callback, createInitData(), getRouterFinderStr(), _useCallbacks);
+ session.connect(username, password, _context);
+ return session;
+ }
+
+ private Ice.InitializationData
+ createInitData()
+ {
+ //
+ // Clone the initialization data and properties.
+ //
+ Ice.InitializationData initData = _initData.clone();
+ initData.properties = initData.properties._clone();
+
+ if(initData.properties.getProperty("Ice.Default.Router").length() == 0 && _identity != null)
+ {
+ initData.properties.setProperty("Ice.Default.Router", getProxyStr(_identity));
+ }
+
+ //
+ // If using a secure connection setup the IceSSL plug-in, if IceSSL
+ // plug-in has already been setup we don't want to override the
+ // configuration so it can be loaded from a custom location.
+ //
+ if((_protocol.equals("ssl") || _protocol.equals("wss")) &&
+ initData.properties.getProperty("Ice.Plugin.IceSSL").length() == 0)
+ {
+ initData.properties.setProperty("Ice.Plugin.IceSSL", "IceSSL.PluginFactory");
+ }
+
+ return initData;
+ }
+
+ private String
+ getRouterFinderStr()
+ {
+ Ice.Identity ident = new Ice.Identity("RouterFinder", "Ice");
+ return getProxyStr(ident);
+ }
+
+ private String
+ getProxyStr(Ice.Identity ident)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("\"");
+ sb.append(Ice.Util.identityToString(ident));
+ sb.append("\":");
+ sb.append(_protocol + " -p ");
+ sb.append(getPortInternal());
+ sb.append(" -h \"");
+ sb.append(_routerHost);
+ sb.append("\"");
+ if(_timeout > 0)
+ {
+ sb.append(" -t ");
+ sb.append(_timeout);
+ }
+ return sb.toString();
+ }
+
+ private SessionCallback _callback;
+ private String _routerHost = "localhost";
+ private Ice.InitializationData _initData;
+ private Ice.Identity _identity = null;
+ private String _protocol = "ssl";
+ private int _port = 0;
+ private int _timeout = 10000;
+ private java.util.Map<String, String> _context;
+ private boolean _useCallbacks = true;
+ private static final int GLACIER2_SSL_PORT = 4064;
+ private static final int GLACIER2_TCP_PORT = 4063;
+}
diff --git a/java-compat/src/Glacier2/src/main/java/Glacier2/SessionHelper.java b/java-compat/src/Glacier2/src/main/java/Glacier2/SessionHelper.java
new file mode 100644
index 00000000000..70257c9f66d
--- /dev/null
+++ b/java-compat/src/Glacier2/src/main/java/Glacier2/SessionHelper.java
@@ -0,0 +1,627 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Glacier2;
+
+/**
+ * A helper class for using Glacier2 with GUI applications.
+ */
+public class SessionHelper
+{
+ /**
+ * Creates a Glacier2 session.
+ *
+ * @param callback The callback for notifications about session establishment.
+ * @param initData The {@link Ice.InitializationData} for initializing the communicator.
+ * @param finderStr The stringified Ice.RouterFinder proxy.
+ * @param useCallbacks True if the session should create an object adapter for receiving callbacks.
+ */
+ public SessionHelper(SessionCallback callback, Ice.InitializationData initData, String finderStr,
+ boolean useCallbacks)
+ {
+ _callback = callback;
+ _initData = initData;
+ _finderStr = finderStr;
+ _useCallbacks = useCallbacks;
+ }
+
+ /**
+ * Destroys the Glacier2 session.
+ *
+ * Once the session has been destroyed, {@link SessionCallback.disconnected} is called on
+ * the associated callback object.
+ */
+ public void
+ destroy()
+ {
+ synchronized(this)
+ {
+ if(_destroy)
+ {
+ return;
+ }
+ _destroy = true;
+ if(!_connected)
+ {
+ //
+ // In this case a connecting session is being destroyed.
+ // We destroy the communicator to trigger the immediate
+ // failure of the connection establishment.
+ //
+ new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ destroyCommunicator();
+ }
+ }).start();
+ return;
+ }
+ _session = null;
+ _connected = false;
+
+ try
+ {
+ Runtime.getRuntime().removeShutdownHook(_shutdownHook);
+ }
+ catch(IllegalStateException ex)
+ {
+ // Ignore
+ }
+ catch(SecurityException ex)
+ {
+ // Ignore
+ }
+ }
+
+ //
+ // Run destroyInternal in a thread because it makes remote invocations.
+ //
+ new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ destroyInternal();
+ }
+ }).start();
+ }
+
+ /**
+ * Returns the session's communicator object.
+ * @return The communicator.
+ */
+ synchronized public Ice.Communicator
+ communicator()
+ {
+ return _communicator;
+ }
+
+ /**
+ * Returns the category to be used in the identities of all of the client's
+ * callback objects. Clients must use this category for the router to
+ * forward callback requests to the intended client.
+ * @return The category.
+ * @throws SessionNotExistException No session exists.
+ **/
+ synchronized public String
+ categoryForClient()
+ throws SessionNotExistException
+ {
+ if(_router == null)
+ {
+ throw new SessionNotExistException();
+ }
+
+ return _category;
+ }
+
+ /**
+ * Adds a servant to the callback object adapter's Active Servant Map with a UUID.
+ * @param servant The servant to add.
+ * @return The proxy for the servant.
+ * @throws SessionNotExistException No session exists.
+ **/
+ synchronized public Ice.ObjectPrx
+ addWithUUID(Ice.Object servant)
+ throws SessionNotExistException
+ {
+ if(_router == null)
+ {
+ throw new SessionNotExistException();
+ }
+ return internalObjectAdapter().add(servant, new Ice.Identity(java.util.UUID.randomUUID().toString(),
+ _category));
+ }
+
+ /**
+ * Returns the Glacier2 session proxy. If the session hasn't been established yet,
+ * or the session has already been destroyed, throws SessionNotExistException.
+ * @return The session proxy, or throws SessionNotExistException if no session exists.
+ * @throws SessionNotExistException No session exists.
+ */
+ synchronized public Glacier2.SessionPrx
+ session()
+ throws SessionNotExistException
+ {
+ if(_session == null)
+ {
+ throw new SessionNotExistException();
+ }
+
+ return _session;
+ }
+
+ /**
+ * Returns true if there is an active session, otherwise returns false.
+ * @return <code>true</code>if session exists or false if no session exists.
+ */
+ synchronized public boolean
+ isConnected()
+ {
+ return _connected;
+ }
+
+ /**
+ * Creates an object adapter for callback objects.
+ * @return The object adapter.
+ * @throws SessionNotExistException No session exists.
+ */
+ synchronized public Ice.ObjectAdapter
+ objectAdapter()
+ throws SessionNotExistException
+ {
+ return internalObjectAdapter();
+ }
+
+ //
+ // Only call this method when the calling thread owns the lock
+ //
+ private Ice.ObjectAdapter
+ internalObjectAdapter()
+ throws SessionNotExistException
+ {
+ if(_router == null)
+ {
+ throw new SessionNotExistException();
+ }
+ if(!_useCallbacks)
+ {
+ throw new Ice.InitializationException(
+ "Object adapter not available, call SessionFactoryHelper.setUseCallbacks(true)");
+ }
+ return _adapter;
+ }
+
+ private interface ConnectStrategy
+ {
+ Glacier2.SessionPrx
+ connect(Glacier2.RouterPrx router)
+ throws CannotCreateSessionException, PermissionDeniedException;
+ }
+
+ /**
+ * Connects to the Glacier2 router using the associated SSL credentials.
+ *
+ * Once the connection is established, {@link SessionCallback#connected} is called on the callback object;
+ * upon failure, {@link SessionCallback#exception} is called with the exception.
+ *
+ * @param context The request context to use when creating the session.
+ */
+ synchronized protected void
+ connect(final java.util.Map<String, String> context)
+ {
+ connectImpl(new ConnectStrategy()
+ {
+ @Override
+ public SessionPrx connect(RouterPrx router)
+ throws CannotCreateSessionException, PermissionDeniedException
+ {
+ return router.createSessionFromSecureConnection(context);
+ }
+ });
+ }
+
+ /**
+ * Connects a Glacier2 session using user name and password credentials.
+ *
+ * Once the connection is established, {@link SessionCallback#connected} is called on the callback object;
+ * upon failure {@link SessionCallback.exception} is called with the exception.
+ *
+ * @param username The user name.
+ * @param password The password.
+ * @param context The request context to use when creating the session.
+ */
+ synchronized protected void
+ connect(final String username, final String password, final java.util.Map<String, String> context)
+ {
+ connectImpl(new ConnectStrategy()
+ {
+ @Override
+ public SessionPrx connect(RouterPrx router)
+ throws CannotCreateSessionException, PermissionDeniedException
+ {
+ return router.createSession(username, password, context);
+ }
+ });
+ }
+
+ private void
+ connected(RouterPrx router, SessionPrx session)
+ {
+ //
+ // Remote invocation should be done without acquiring a mutex lock.
+ //
+ assert(router != null);
+ Ice.Connection conn = router.ice_getCachedConnection();
+ String category = router.getCategoryForClient();
+ int acmTimeout = 0;
+ try
+ {
+ acmTimeout = router.getACMTimeout();
+ }
+ catch(Ice.OperationNotExistException ex)
+ {
+ }
+
+ if(acmTimeout <= 0)
+ {
+ acmTimeout = (int)router.getSessionTimeout();
+ }
+
+ //
+ // We create the callback object adapter here because createObjectAdapter internally
+ // makes synchronous RPCs to the router. We can't create the OA on-demand when the
+ // client calls objectAdapter() or addWithUUID() because they can be called from the
+ // GUI thread.
+ //
+ if(_useCallbacks)
+ {
+ assert(_adapter == null);
+ _adapter = _communicator.createObjectAdapterWithRouter("", router);
+ _adapter.activate();
+ }
+
+ synchronized(this)
+ {
+ _router = router;
+
+ if(_destroy)
+ {
+ //
+ // Run destroyInternal in a thread because it makes remote invocations.
+ //
+ new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ destroyInternal();
+ }
+ }).start();
+ return;
+ }
+
+ //
+ // Cache the category.
+ //
+ _category = category;
+
+ //
+ // Assign the session after _destroy is checked.
+ //
+ _session = session;
+ _connected = true;
+
+ if(acmTimeout > 0)
+ {
+ Ice.Connection connection = _router.ice_getCachedConnection();
+ assert(connection != null);
+ connection.setACM(new Ice.IntOptional(acmTimeout),
+ null,
+ new Ice.Optional<Ice.ACMHeartbeat>(Ice.ACMHeartbeat.HeartbeatAlways));
+ connection.setCloseCallback(new Ice.CloseCallback()
+ {
+ @Override
+ public void closed(Ice.Connection con)
+ {
+ destroy();
+ }
+ });
+ }
+
+ _shutdownHook = new Thread("Shutdown hook")
+ {
+ @Override
+ public void run()
+ {
+ SessionHelper.this.destroy();
+ }
+ };
+
+ try
+ {
+ Runtime.getRuntime().addShutdownHook(_shutdownHook);
+ }
+ catch(IllegalStateException e)
+ {
+ //
+ // Shutdown in progress, ignored
+ //
+ }
+ catch(SecurityException ex)
+ {
+ //
+ // Ignore. Unsigned applets cannot registered shutdown hooks.
+ //
+ }
+ }
+
+ dispatchCallback(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ _callback.connected(SessionHelper.this);
+ }
+ catch(SessionNotExistException ex)
+ {
+ SessionHelper.this.destroy();
+ }
+ }
+ }, conn);
+ }
+
+ private void
+ destroyInternal()
+ {
+ assert _destroy;
+ Glacier2.RouterPrx router = null;
+ Ice.Communicator communicator = null;
+ synchronized(this)
+ {
+ if(_router == null)
+ {
+ return;
+ }
+
+ router = _router;
+ _router = null;
+
+ communicator = _communicator;
+ }
+
+ assert communicator != null;
+
+ try
+ {
+ router.destroySession();
+ }
+ catch(Ice.ConnectionLostException e)
+ {
+ //
+ // Expected if another thread invoked on an object from the session concurrently.
+ //
+ }
+ catch(SessionNotExistException e)
+ {
+ //
+ // This can also occur.
+ //
+ }
+ catch(Throwable e)
+ {
+ //
+ // Not expected.
+ //
+ communicator.getLogger().warning("SessionHelper: unexpected exception when destroying the session:\n" + e);
+ }
+
+ try
+ {
+ communicator.destroy();
+ }
+ catch(Throwable ex)
+ {
+ }
+
+ //
+ // Notify the callback that the session is gone.
+ //
+ dispatchCallback(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ _callback.disconnected(SessionHelper.this);
+ }
+ }, null);
+ }
+
+ private void
+ destroyCommunicator()
+ {
+ Ice.Communicator communicator = null;
+ synchronized(this)
+ {
+ communicator = _communicator;
+ }
+
+ if(communicator != null)
+ {
+ try
+ {
+ _communicator.destroy();
+ }
+ catch(Throwable ex)
+ {
+ }
+ }
+ }
+
+ private void
+ connectImpl(final ConnectStrategy factory)
+ {
+ assert !_destroy;
+
+ try
+ {
+ _communicator = Ice.Util.initialize(_initData);
+ }
+ catch(final Ice.LocalException ex)
+ {
+ _destroy = true;
+ new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ dispatchCallback(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ _callback.connectFailed(SessionHelper.this, ex);
+ }
+ }, null);
+ }
+ }).start();
+ return;
+ }
+
+ final Ice.RouterFinderPrx finder =
+ Ice.RouterFinderPrxHelper.uncheckedCast(_communicator.stringToProxy(_finderStr));
+ new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ if(_communicator.getDefaultRouter() == null)
+ {
+ try
+ {
+ _communicator.setDefaultRouter(finder.getRouter());
+ }
+ catch(final Ice.CommunicatorDestroyedException ex)
+ {
+ dispatchCallback(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ _callback.connectFailed(SessionHelper.this, ex);
+ }
+ }, null);
+ return;
+ }
+ catch(Exception ex)
+ {
+ //
+ // In case of error getting router identity from RouterFinder use
+ // default identity.
+ //
+ Ice.Identity ident = new Ice.Identity("router", "Glacier2");
+ _communicator.setDefaultRouter(Ice.RouterPrxHelper.uncheckedCast(finder.ice_identity(ident)));
+ }
+ }
+
+ try
+ {
+ dispatchCallbackAndWait(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ _callback.createdCommunicator(SessionHelper.this);
+ }
+ });
+
+ Glacier2.RouterPrx routerPrx = Glacier2.RouterPrxHelper.uncheckedCast(
+ _communicator.getDefaultRouter());
+ Glacier2.SessionPrx session = factory.connect(routerPrx);
+ connected(routerPrx, session);
+ }
+ catch(final Exception ex)
+ {
+ try
+ {
+ _communicator.destroy();
+ }
+ catch(Throwable ex1)
+ {
+ }
+
+ dispatchCallback(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ _callback.connectFailed(SessionHelper.this, ex);
+ }
+ }, null);
+ }
+ }
+ }).start();
+ }
+
+ private void
+ dispatchCallback(Runnable runnable, Ice.Connection conn)
+ {
+ if(_initData.dispatcher != null)
+ {
+ _initData.dispatcher.dispatch(runnable, conn);
+ }
+ else
+ {
+ runnable.run();
+ }
+ }
+
+ private void
+ dispatchCallbackAndWait(final Runnable runnable)
+ {
+ if(_initData.dispatcher != null)
+ {
+ final java.util.concurrent.Semaphore sem = new java.util.concurrent.Semaphore(0);
+ _initData.dispatcher.dispatch(
+ new Runnable()
+ {
+ @Override
+ public void
+ run()
+ {
+ runnable.run();
+ sem.release();
+ }
+ }, null);
+ sem.acquireUninterruptibly();
+ }
+ else
+ {
+ runnable.run();
+ }
+ }
+
+ private final Ice.InitializationData _initData;
+ private Ice.Communicator _communicator;
+ private Ice.ObjectAdapter _adapter;
+ private Glacier2.RouterPrx _router;
+ private Glacier2.SessionPrx _session;
+ private String _category;
+ private String _finderStr;
+ private boolean _useCallbacks;
+
+ private final SessionCallback _callback;
+ private boolean _destroy = false;
+ private boolean _connected = false;
+ private Thread _shutdownHook;
+}
diff --git a/java-compat/src/Ice/build.gradle b/java-compat/src/Ice/build.gradle
new file mode 100644
index 00000000000..3edcb8df149
--- /dev/null
+++ b/java-compat/src/Ice/build.gradle
@@ -0,0 +1,26 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+sourceCompatibility = iceSourceCompatibility
+targetCompatibility = iceTargetCompatibility
+
+project.ext.displayName = "Ice Compat"
+project.ext.description = "Ice is a comprehensive RPC framework that helps you build distributed applications" +
+ " with minimal effort using familiar object-oriented idioms"
+
+slice {
+ java {
+ set1 {
+ args = "--ice"
+ files = fileTree(dir: "$sliceDir", includes:['Ice/*.ice', 'IceSSL/*.ice'], excludes:['Ice/*F.ice'])
+ }
+ }
+}
+
+apply from: "$rootProject.projectDir/../java/gradle/library.gradle"
diff --git a/java-compat/src/Ice/src/main/java/Ice/AMDCallback.java b/java-compat/src/Ice/src/main/java/Ice/AMDCallback.java
new file mode 100644
index 00000000000..9ece32a5899
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/AMDCallback.java
@@ -0,0 +1,23 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * AMDCallback is the interface from which all AMD callbacks are derived.
+ **/
+public interface AMDCallback
+{
+ /**
+ * ice_exception indicates to the Ice run time that
+ * the operation completed with an exception.
+ * @param ex The exception to be raised.
+ **/
+ public void ice_exception(java.lang.Exception ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/AMD_Object_ice_invoke.java b/java-compat/src/Ice/src/main/java/Ice/AMD_Object_ice_invoke.java
new file mode 100644
index 00000000000..5fbeb9649c6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/AMD_Object_ice_invoke.java
@@ -0,0 +1,40 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Callback interface for <Blobject> AMD servants.
+ *
+ @see BlobjectAsync
+ **/
+public interface AMD_Object_ice_invoke
+{
+ /**
+ * Indicates to the Ice run time that an operation
+ * completed.
+ *
+ * @param ok <code>true</code> indicates that the operation
+ * completed successfully; <code>false</code> indicates that the
+ * operation raised a user exception.
+ * @param outEncaps The encoded out-parameters for the operation or,
+ * if <code>ok</code> is <code>false</code>, the encoded user exception.
+ **/
+ void ice_response(boolean ok, byte[] outEncaps);
+
+ /**
+ * Indicates to the Ice run time that an operation completed
+ * with a run-time exception.
+ *
+ * @param ex The encoded Ice run-time exception. Note that, if <code>ex</code>
+ * is a user exception, the caller receives {@link UnknownUserException}.
+ * Use {@link #ice_response} to raise user exceptions.
+ **/
+ void ice_exception(java.lang.Exception ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Application.java b/java-compat/src/Ice/src/main/java/Ice/Application.java
new file mode 100644
index 00000000000..3562445becb
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Application.java
@@ -0,0 +1,696 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Utility base class that makes it easy to correctly initialize and finalize
+ * the Ice run time, as well as handle signals. Unless the application specifies
+ * a logger, <Application> installs a per-process logger that logs to the standard
+ * error output.
+ * <p>
+ * Applications must create a derived class that implements the {@link #run} method.
+ * <p>
+ * A program can contain only one instance of this class.
+ *
+ * @see #run
+ * @see Communicator
+ * @see Logger
+ **/
+public abstract class Application
+{
+ /**
+ * Initializes an instance that calls {@link Communicator#shutdown} if
+ * a signal is received.
+ **/
+ public
+ Application()
+ {
+ }
+
+ /**
+ * Initializes an instance that handles signals according to the signal
+ * policy.
+ *
+ * @param signalPolicy Determines how to respond to signals.
+ *
+ * @see SignalPolicy
+ **/
+ public
+ Application(SignalPolicy signalPolicy)
+ {
+ _signalPolicy = signalPolicy;
+ }
+
+ /**
+ * The application must call <code>main</code> after it has
+ * instantiated the derived class. <code>main</code> creates
+ * a communicator, establishes the specified signal policy, and,
+ * once <code>run</code> returns, destroys the communicator.
+ * <p>
+ * The method prints an error message for any exception that propagates
+ * out of <code>run</code> and ensures that the communicator is
+ * destroyed correctly even if <code>run</code> completes abnormally.
+ *
+ * @param appName The name of the application. This parameter is used to initialize
+ * the value of the <code>Ice.ProgramName</code> property.
+ * @param args The arguments for the application (as passed to <code>Main(String[])</code>
+ * by the operating system.
+ * @return The value returned by <code>run</code>. If <code>run</code> terminates with an exception,
+ * the return value is non-zero.
+ **/
+ public final int
+ main(String appName, String[] args)
+ {
+ return main(appName, args, new InitializationData());
+ }
+
+ /**
+ * The application must call <code>main</code> after it has
+ * instantiated the derived class. <code>main</code> creates
+ * a communicator, establishes the specified signal policy, and,
+ * once <code>run</code> returns, destroys the communicator.
+ * <p>
+ * The method prints an error message for any exception that propagates
+ * out of <code>run</code> and ensures that the communicator is
+ * destroyed correctly even if <code>run</code> completes abnormally.
+ *
+ * @param appName The name of the application. This parameter is used to initialize
+ * the value of the <code>Ice.ProgramName</code> property.
+ * @param configFile The configuration file with which to initialize
+ * Ice properties.
+ * @return The value returned by <code>run</code>. If <code>run</code> terminates with an exception,
+ * the return value is non-zero.
+ **/
+ public final int
+ main(String appName, String[] args, String configFile)
+ {
+ if(Util.getProcessLogger() instanceof LoggerI)
+ {
+ Util.setProcessLogger(new LoggerI(appName, ""));
+ }
+
+ InitializationData initData = new InitializationData();
+ if(configFile != null)
+ {
+ try
+ {
+ initData.properties = Util.createProperties();
+ initData.properties.load(configFile);
+ }
+ catch(LocalException ex)
+ {
+ Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ return 1;
+ }
+ catch(java.lang.Exception ex)
+ {
+ Util.getProcessLogger().error("unknown exception: " + IceInternal.Ex.toString(ex));
+ return 1;
+ }
+ }
+ return main(appName, args, initData);
+ }
+
+ /**
+ * The application must call <code>main</code> after it has
+ * instantiated the derived class. <code>main</code> creates
+ * a communicator, establishes the specified signal policy, and,
+ * once <code>run</code> returns, destroys the communicator.
+ * <p>
+ * The method prints an error message for any exception that propagates
+ * out of <code>run</code> and ensures that the communicator is
+ * destroyed correctly even if <code>run</code> completes abnormally.
+ *
+ * @param appName The name of the application. This parameter is used to initialize
+ * the value of the <code>Ice.ProgramName</code> property.
+ * @param args The arguments for the application (as passed to <code>Main(String[])</code>.
+ * @param initializationData Additional data used to initialize the communicator.
+ * @return The value returned by <code>run</code>. If <code>run</code> terminates with an exception,
+ * the return value is non-zero.
+ *
+ * @see InitializationData
+ **/
+ public final int
+ main(String appName, String[] args, InitializationData initializationData)
+ {
+ if(Util.getProcessLogger() instanceof LoggerI)
+ {
+ Util.setProcessLogger(new LoggerI(appName, ""));
+ }
+
+ if(_communicator != null)
+ {
+ Util.getProcessLogger().error("only one instance of the Application class can be used");
+ return 1;
+ }
+
+ _appName = appName;
+
+ //
+ // We parse the properties here to extract Ice.ProgramName.
+ //
+ InitializationData initData;
+ if(initializationData != null)
+ {
+ initData = initializationData.clone();
+ }
+ else
+ {
+ initData = new InitializationData();
+ }
+ StringSeqHolder argHolder = new StringSeqHolder(args);
+ try
+ {
+ initData.properties = Util.createProperties(argHolder, initData.properties);
+ }
+ catch(LocalException ex)
+ {
+ Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ return 1;
+ }
+ catch(java.lang.Exception ex)
+ {
+ Util.getProcessLogger().error("unknown exception: " + IceInternal.Ex.toString(ex));
+ return 1;
+ }
+ _appName = initData.properties.getPropertyWithDefault("Ice.ProgramName", _appName);
+
+ //
+ // If the process logger is the default logger, we replace it with a
+ // a logger which is using the program name for the prefix.
+ //
+ if(!initData.properties.getProperty("Ice.ProgramName").equals("") && Util.getProcessLogger() instanceof LoggerI)
+ {
+ Util.setProcessLogger(new LoggerI(initData.properties.getProperty("Ice.ProgramName"), ""));
+ }
+
+ return doMain(argHolder, initData);
+ }
+
+ protected int
+ doMain(StringSeqHolder argHolder, Ice.InitializationData initData)
+ {
+ int status = 0;
+
+ try
+ {
+ _communicator = Util.initialize(argHolder, initData);
+
+ //
+ // The default is to destroy when a signal is received.
+ //
+ if(_signalPolicy == SignalPolicy.HandleSignals)
+ {
+ destroyOnInterrupt();
+ }
+
+ status = run(argHolder.value);
+ }
+ catch(LocalException ex)
+ {
+ Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ status = 1;
+ }
+ catch(java.lang.Exception ex)
+ {
+ Util.getProcessLogger().error("unknown exception: " + IceInternal.Ex.toString(ex));
+ status = 1;
+ }
+ catch(java.lang.Error err)
+ {
+ //
+ // We catch Error to avoid hangs in some non-fatal situations
+ //
+ Util.getProcessLogger().error("Java error: " + IceInternal.Ex.toString(err));
+ status = 1;
+ }
+
+ // This clears any set interrupt.
+ if(_signalPolicy == SignalPolicy.HandleSignals)
+ {
+ defaultInterrupt();
+ }
+
+ synchronized(_mutex)
+ {
+ boolean interrupted = false;
+ while(_callbackInProgress)
+ {
+ try
+ {
+ _mutex.wait();
+ }
+ catch(InterruptedException ex)
+ {
+ interrupted = true;
+ }
+ }
+ if(interrupted)
+ {
+ Thread.currentThread().interrupt();
+ }
+
+ if(_destroyed)
+ {
+ _communicator = null;
+ }
+ else
+ {
+ _destroyed = true;
+ //
+ // And _communicator != null, meaning will be
+ // destroyed next, _destroyed = true also ensures that
+ // any remaining callback won't do anything
+ //
+ }
+ }
+
+ if(_communicator != null)
+ {
+ try
+ {
+ try
+ {
+ _communicator.destroy();
+ }
+ catch(Ice.OperationInterruptedException ex)
+ {
+ Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ // Retry communicator destroy in case of an operation
+ // interrupt exception, but don't do so in a loop
+ // otherwise it could go on forever.
+ _communicator.destroy();
+ }
+ }
+ catch(LocalException ex)
+ {
+ Util.getProcessLogger().error(IceInternal.Ex.toString(ex));
+ status = 1;
+ }
+ catch(java.lang.Exception ex)
+ {
+ Util.getProcessLogger().error("unknown exception: " + IceInternal.Ex.toString(ex));
+ status = 1;
+ }
+ _communicator = null;
+ }
+
+ synchronized(_mutex)
+ {
+ if(_appHook != null)
+ {
+ _appHook.done();
+ }
+ }
+
+ return status;
+ }
+
+ /**
+ * Called once the communicator has been initialized. The derived class must
+ * implement <code>run</code>, which is the application's starting method.
+ *
+ * @param args The argument vector for the application. <code>Application</code>
+ * scans the argument vector passed to <code>main</code> for options that are
+ * specific to the Ice run time and removes them; therefore, the vector passed
+ * to <code>run</code> is free from Ice-related options and contains only options
+ * and arguments that are application-specific.
+ *
+ * @return The <code>run</code> method should return zero for successful termination, and
+ * non-zero otherwise. <code>Application.main</code> returns the value returned by <code>run</code>.
+ **/
+ public abstract int
+ run(String[] args);
+
+ /**
+ * Returns the value of <code>appName</code> that is passed to <code>main</code> (which is also the
+ * the value of <code>Ice.ProgramName</code>). This method is useful mainly for error messages that
+ * include the application name. Because <appName> is a static method, it is available from anywhere
+ * in the program.
+ *
+ * @return The name of the application.
+ **/
+ public static String
+ appName()
+ {
+ return _appName;
+ }
+
+ /**
+ * Returns the communicator for the application. Because <communicator> is a static method,
+ * it permits access to the communicator from anywhere in the program. Note that, as a consequence,
+ * you cannot have more than one instance of <code>Application</code> in a program.
+ *
+ * @return The communicator for the application.
+ **/
+ public static Communicator
+ communicator()
+ {
+ return _communicator;
+ }
+
+ /**
+ * Instructs <code>Application</code> to call {@link Communicator#destroy} on receipt of a signal.
+ * This is default signal handling policy established by the default constructor.
+ *
+ * @see Communicator#destroy
+ **/
+ public static void
+ destroyOnInterrupt()
+ {
+ if(_signalPolicy == SignalPolicy.HandleSignals)
+ {
+ synchronized(_mutex)
+ {
+ //
+ // As soon as the destroy hook ends all the threads are
+ // terminated. So the destroy hook will join the current
+ // thread before to end.
+ //
+ try
+ {
+ changeHook(new DestroyHook());
+ }
+ catch(java.lang.IllegalStateException ex)
+ {
+ if(_communicator != null)
+ {
+ _communicator.destroy();
+ }
+ }
+ }
+ }
+ else
+ {
+ Util.getProcessLogger().warning(
+ "interrupt method called on Application configured to not handle interrupts.");
+ }
+ }
+
+ /**
+ * Instructs <code>Application</code> to call {@link Communicator#shutdown} on receipt of a signal.
+ *
+ * @see Communicator#shutdown
+ **/
+ public static void
+ shutdownOnInterrupt()
+ {
+ if(_signalPolicy == SignalPolicy.HandleSignals)
+ {
+ synchronized(_mutex)
+ {
+ //
+ // As soon as the shutdown hook ends all the threads are
+ // terminated. So the shutdown hook will join the current
+ // thread before to end.
+ //
+ try
+ {
+ changeHook(new ShutdownHook());
+ }
+ catch(java.lang.IllegalStateException ex)
+ {
+ if(_communicator != null)
+ {
+ _communicator.shutdown();
+ }
+ }
+ }
+ }
+ else
+ {
+ Util.getProcessLogger().warning(
+ "interrupt method called on Application configured to not handle interrupts.");
+ }
+ }
+
+ /**
+ * Installs a custom shutdown hook. The implementation of the shutdown
+ * hook can do whatever cleanup is necessary to shut down the application.
+ * The hook is unregistered once <code>run</code> returns.
+ * Note that the hook must obey the rules for shutdown hooks; specifically,
+ * it must not call <code>exit</code>.
+ *
+ * @param newHook The thread to run on shutdown.
+ *
+ * @see java.lang.Runtime#addShutdownHook
+ **/
+ public static void
+ setInterruptHook(java.lang.Thread newHook) // Pun intended.
+ {
+ if(_signalPolicy == SignalPolicy.HandleSignals)
+ {
+ try
+ {
+ changeHook(new CustomHook(newHook));
+ }
+ catch(java.lang.IllegalStateException ex)
+ {
+ // Ignore.
+ }
+ }
+ else
+ {
+ Util.getProcessLogger().warning(
+ "interrupt method called on Application configured to not handle interrupts.");
+ }
+ }
+
+ /**
+ * Clears any shutdown hooks, including any hook established with {@link #destroyOnInterrupt} or
+ * {@link #shutdownOnInterrupt}.
+ **/
+ public static void
+ defaultInterrupt()
+ {
+ if(_signalPolicy == SignalPolicy.HandleSignals)
+ {
+ changeHook(null);
+ }
+ else
+ {
+ Util.getProcessLogger().warning(
+ "interrupt method called on Application configured to not handle interrupts.");
+ }
+ }
+
+ /**
+ * Determines whether the application shut down intentionally or was forced to shut down by the JVM. This
+ * is useful for logging purposes.
+ *
+ * @return <code>true</code> if a shutdown hook caused the communicator to shut down; false otherwise.
+ **/
+ public static boolean
+ interrupted()
+ {
+ synchronized(_mutex)
+ {
+ return _interrupted;
+ }
+ }
+
+ private static void
+ changeHook(AppHook newHook)
+ {
+ synchronized(_mutex)
+ {
+ //
+ // Remove any existing shutdown hooks.
+ //
+ try
+ {
+ if(_appHook != null)
+ {
+ Runtime.getRuntime().removeShutdownHook(_appHook);
+ _appHook.done();
+ _appHook = null;
+ }
+ }
+ catch(java.lang.IllegalStateException ex)
+ {
+ //
+ // Expected if we are in the process of shutting down.
+ //
+ }
+
+ //
+ // Note that we let the IllegalStateException propagate
+ // out if necessary.
+ //
+ if(newHook != null)
+ {
+ Runtime.getRuntime().addShutdownHook(newHook);
+ _appHook = newHook;
+ }
+ }
+ }
+
+ private static boolean
+ setCallbackInProgress(boolean destroy)
+ {
+ synchronized(_mutex)
+ {
+ if(_destroyed)
+ {
+ //
+ // Being destroyed by main thread
+ //
+ return false;
+ }
+ _callbackInProgress = true;
+ _destroyed = destroy;
+ _interrupted = true;
+ return true;
+ }
+ }
+
+ private static void
+ clearCallbackInProgress()
+ {
+ synchronized(_mutex)
+ {
+ _callbackInProgress = false;
+ _mutex.notify();
+ }
+ }
+
+ // For use by Glacier2.Application
+ static public class AppHook extends Thread
+ {
+ public void
+ done()
+ {
+ synchronized(_doneMutex)
+ {
+ _done = true;
+ _doneMutex.notify();
+ }
+ }
+
+ protected boolean _done = false;
+ protected final java.lang.Object _doneMutex = new java.lang.Object();
+ }
+
+ static class DestroyHook extends AppHook
+ {
+ @Override
+ public void
+ run()
+ {
+ synchronized(_doneMutex)
+ {
+ if(!setCallbackInProgress(true))
+ {
+ return;
+ }
+
+ Communicator communicator = communicator();
+ if(communicator != null)
+ {
+ communicator.destroy();
+ }
+
+ clearCallbackInProgress();
+
+ while(!_done)
+ {
+ try
+ {
+ _doneMutex.wait();
+ }
+ catch(InterruptedException ex)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ static class ShutdownHook extends AppHook
+ {
+ @Override
+ public void
+ run()
+ {
+ synchronized(_doneMutex)
+ {
+ if(!setCallbackInProgress(false))
+ {
+ return;
+ }
+
+ Communicator communicator = communicator();
+ if(communicator != null)
+ {
+ communicator.shutdown();
+ }
+
+ clearCallbackInProgress();
+
+ while(!_done)
+ {
+ try
+ {
+ _doneMutex.wait();
+ }
+ catch(InterruptedException ex)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Although this class doesn't actually use any of the AppHook
+ // done stuff, its more trouble than its worth to add all of the
+ // code necessary to support another hook member variable and
+ // support code.
+ static class CustomHook extends AppHook
+ {
+ CustomHook(Thread hook)
+ {
+ _hook = hook;
+ }
+
+ @Override
+ public void
+ run()
+ {
+ synchronized(_doneMutex)
+ {
+ if(!setCallbackInProgress(false))
+ {
+ return;
+ }
+
+ _hook.run();
+
+ clearCallbackInProgress();
+
+ //
+ // Don't bother to join with main, we're done.
+ //
+ }
+ }
+
+ private Thread _hook;
+ }
+
+ protected static String _appName;
+ protected static Communicator _communicator;
+ protected static AppHook _appHook;
+ protected final static java.lang.Object _mutex = new java.lang.Object();
+ protected static boolean _callbackInProgress = false;
+ protected static boolean _destroyed = false;
+ protected static boolean _interrupted = false;
+ protected static SignalPolicy _signalPolicy = SignalPolicy.HandleSignals;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/AsyncCallback.java b/java-compat/src/Ice/src/main/java/Ice/AsyncCallback.java
new file mode 100644
index 00000000000..7ec2a2837ac
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/AsyncCallback.java
@@ -0,0 +1,22 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * An application can optionally supply an instance of this class in an
+ * asynchronous invocation. The application must create a subclass and
+ * implement the completed method.
+ *
+ * @deprecated This class is deprecated, use Ice.Callback instead.
+ **/
+@Deprecated
+public abstract class AsyncCallback extends Callback
+{
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/AsyncResult.java b/java-compat/src/Ice/src/main/java/Ice/AsyncResult.java
new file mode 100644
index 00000000000..f62006ecc43
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/AsyncResult.java
@@ -0,0 +1,105 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * An AsyncResult object is the return value of an asynchronous invocation.
+ * With this object, an application can obtain several attributes of the
+ * invocation and discover its outcome.
+ **/
+public interface AsyncResult
+{
+ /**
+ * If not completed, cancels the request. This is a local
+ * operation, it won't cancel the request on the server side.
+ * Calling <code>cancel</code> prevents a queued request from
+ * being sent or ignores a reply if the request has already
+ * been sent.
+ **/
+ public void cancel();
+
+ /**
+ * Returns the communicator that sent the invocation.
+ *
+ * @return The communicator.
+ **/
+ public Communicator getCommunicator();
+
+ /**
+ * Returns the connection that was used to call the <code>begin_</code> method, or nil
+ * if this AsyncResult object was not obtained via an asynchronous connection invocation
+ * (such as <code>begin_flushBatchRequests</code>).
+ *
+ * @return The connection.
+ **/
+ public Connection getConnection();
+
+ /**
+ * Returns the proxy that was used to call the <code>begin_</code> method, or nil
+ * if this AsyncResult object was not obtained via an asynchronous proxy invocation.
+ *
+ * @return The proxy.
+ **/
+ public ObjectPrx getProxy();
+
+ /**
+ * Indicates whether the result of an invocation is available.
+ *
+ * @return True if the result is available, which means a call to the <code>end_</code>
+ * method will not block. The method returns false if the result is not yet available.
+ **/
+ public boolean isCompleted();
+
+ /**
+ * Blocks the caller until the result of the invocation is available.
+ **/
+ public void waitForCompleted();
+
+ /**
+ * When you call the <code>begin_</code> method, the Ice run time attempts to
+ * write the corresponding request to the client-side transport. If the
+ * transport cannot accept the request, the Ice run time queues the request
+ * for later transmission. This method returns true if, at the time it is called,
+ * the request has been written to the local transport (whether it was initially
+ * queued or not). Otherwise, if the request is still queued, this method returns
+ * false.
+ *
+ * @return True if the request has been sent, or false if the request is queued.
+ **/
+ public boolean isSent();
+
+ /**
+ * Blocks the caller until the request has been written to the client-side transport.
+ **/
+ public void waitForSent();
+
+ /**
+ * If the invocation failed with a local exception, throws the local exception.
+ **/
+ public void throwLocalException();
+
+ /**
+ * This method returns true if a request was written to the client-side
+ * transport without first being queued. If the request was initially
+ * queued, this method returns false (independent of whether the request
+ * is still in the queue or has since been written to the client-side transport).
+ *
+ * @return True if the request was sent without being queued, or false
+ * otherwise.
+ **/
+ public boolean sentSynchronously();
+
+ /**
+ * Returns the name of the operation.
+ *
+ * @return The operation name.
+ **/
+ public String getOperation();
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/BatchRequest.java b/java-compat/src/Ice/src/main/java/Ice/BatchRequest.java
new file mode 100644
index 00000000000..c18b6da917a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/BatchRequest.java
@@ -0,0 +1,33 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface BatchRequest
+{
+ /**
+ * Confirms the queuing of the batch request.
+ **/
+ void enqueue();
+
+ /**
+ * The marshalled size of the request.
+ **/
+ int getSize();
+
+ /**
+ * The name of the operation
+ **/
+ String getOperation();
+
+ /**
+ * The proxy used to invoke the batch request.
+ **/
+ Ice.ObjectPrx getProxy();
+};
diff --git a/java-compat/src/Ice/src/main/java/Ice/BatchRequestInterceptor.java b/java-compat/src/Ice/src/main/java/Ice/BatchRequestInterceptor.java
new file mode 100644
index 00000000000..148225cbd21
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/BatchRequestInterceptor.java
@@ -0,0 +1,28 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base interface for listening to batch request queues.
+ **/
+public interface BatchRequestInterceptor
+{
+ /**
+ * Called by the Ice runtime when a batch request is about to be
+ * added to the batch request queue of a proxy or connection.
+ *
+ * The implementation of this method must call enqueue() on the
+ * request to confirm its addition to the queue, if not called
+ * the request isn't added to the queue. The implementation can
+ * raise an Ice local exception to notify the caller of a failure.
+ *
+ **/
+ void enqueue(Ice.BatchRequest request, int queueBatchRequestCount, int queueBatchRequestSize);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Blobject.java b/java-compat/src/Ice/src/main/java/Ice/Blobject.java
new file mode 100644
index 00000000000..0a3fda4b795
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Blobject.java
@@ -0,0 +1,53 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class for dynamic dispatch servants. A server application
+ * derives a concrete servant class from <code>Blobject</code> that
+ * implements the {@link Blobject#ice_invoke} method.
+ **/
+public abstract class Blobject extends Ice.ObjectImpl
+{
+ /**
+ * Dispatch an incoming request.
+ *
+ * @param inEncaps The encoded in-parameters for the operation.
+ * @param outEncaps The encoded out-paramaters and return value
+ * for the operation. The return value follows any out-parameters.
+ * @param current The Current object to pass to the operation.
+ * @return If the operation completed successfully, the return value
+ * is <code>true</code>. If the operation raises a user exception,
+ * the return value is <code>false</code>; in this case, <code>outEncaps</code>
+ * must contain the encoded user exception. If the operation raises an
+ * Ice run-time exception, it must throw it directly.
+ **/
+ public abstract boolean
+ ice_invoke(byte[] inEncaps, ByteSeqHolder outEncaps, Current current);
+
+ @Override
+ public DispatchStatus
+ __dispatch(IceInternal.Incoming in, Current current)
+ {
+ byte[] inEncaps;
+ ByteSeqHolder outEncaps = new ByteSeqHolder();
+ inEncaps = in.readParamEncaps();
+ boolean ok = ice_invoke(inEncaps, outEncaps, current);
+ in.__writeParamEncaps(outEncaps.value, ok);
+ if(ok)
+ {
+ return DispatchStatus.DispatchOK;
+ }
+ else
+ {
+ return DispatchStatus.DispatchUserException;
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/BlobjectAsync.java b/java-compat/src/Ice/src/main/java/Ice/BlobjectAsync.java
new file mode 100644
index 00000000000..4521de71e11
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/BlobjectAsync.java
@@ -0,0 +1,50 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * <code>BlobjectAsync</code> is the base class for asynchronous dynamic
+ * dispatch servants. A server application derives a concrete servant
+ * class that implements the {@link BlobjectAsync#ice_invoke_async} method,
+ * which is called by the Ice run time to deliver every request on this
+ * object.
+ **/
+public abstract class BlobjectAsync extends Ice.ObjectImpl
+{
+ /**
+ * Dispatch an incoming request.
+ *
+ * @param cb The callback object through which the invocation's results
+ * must be delivered.
+ * @param inEncaps The encoded input parameters.
+ * @param current The Current object, which provides important information
+ * about the request, such as the identity of the target object and the
+ * name of the operation.
+ **/
+ public abstract void
+ ice_invoke_async(AMD_Object_ice_invoke cb, byte[] inEncaps, Current current);
+
+ @Override
+ public DispatchStatus
+ __dispatch(IceInternal.Incoming in, Current current)
+ {
+ byte[] inEncaps = in.readParamEncaps();
+ AMD_Object_ice_invoke cb = new _AMD_Object_ice_invoke(in);
+ try
+ {
+ ice_invoke_async(cb, inEncaps, current);
+ }
+ catch(java.lang.Exception ex)
+ {
+ cb.ice_exception(ex);
+ }
+ return DispatchStatus.DispatchAsync;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/BooleanHolder.java b/java-compat/src/Ice/src/main/java/Ice/BooleanHolder.java
new file mode 100644
index 00000000000..7233a0d27fc
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/BooleanHolder.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for booleans that are out- or inout-parameters.
+ **/
+public final class BooleanHolder extends Holder<Boolean>
+{
+ /**
+ * Instantiates the class with the value <code>false</code>.
+ **/
+ public
+ BooleanHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed value.
+ *
+ * @param value The <code>boolean</code> value stored by this holder.
+ **/
+ public
+ BooleanHolder(boolean value)
+ {
+ super(value);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/BooleanOptional.java b/java-compat/src/Ice/src/main/java/Ice/BooleanOptional.java
new file mode 100644
index 00000000000..e6275db43ae
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/BooleanOptional.java
@@ -0,0 +1,106 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Manages an optional boolean parameter.
+ **/
+public class BooleanOptional
+{
+ /**
+ * The value defaults to unset.
+ **/
+ public BooleanOptional()
+ {
+ _isSet = false;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The initial value.
+ **/
+ public BooleanOptional(boolean v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * Sets the value to a shallow copy of the given optional.
+ *
+ * @param opt The source value.
+ **/
+ public BooleanOptional(BooleanOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Obtains the current value.
+ *
+ * @return The current value.
+ * @throws IllegalStateException If the value is not set.
+ **/
+ public boolean get()
+ {
+ if(!_isSet)
+ {
+ throw new IllegalStateException("no value is set");
+ }
+ return _value;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The new value.
+ **/
+ public void set(boolean v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * If the given argument is set, this optional is set to a shallow copy of the argument,
+ * otherwise this optional is unset.
+ *
+ * @param opt The source value.
+ **/
+ public void set(BooleanOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Determines whether the value is set.
+ *
+ * @return True if the value is set, false otherwise.
+ **/
+ public boolean isSet()
+ {
+ return _isSet;
+ }
+
+ /**
+ * Unsets this value.
+ **/
+ public void clear()
+ {
+ _isSet = false;
+ _value = false;
+ }
+
+ private boolean _value;
+ private boolean _isSet;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ByteHolder.java b/java-compat/src/Ice/src/main/java/Ice/ByteHolder.java
new file mode 100644
index 00000000000..ac54599f84d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ByteHolder.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for bytes that are out- or inout-parameters.
+ **/
+public final class ByteHolder extends Holder<Byte>
+{
+ /**
+ * Instantiates the class with the value zero.
+ **/
+ public
+ ByteHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed value.
+ *
+ * @param value The <code>byte</code> value stored by this holder.
+ **/
+ public
+ ByteHolder(byte value)
+ {
+ super(value);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ByteOptional.java b/java-compat/src/Ice/src/main/java/Ice/ByteOptional.java
new file mode 100644
index 00000000000..493bfaf34a4
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ByteOptional.java
@@ -0,0 +1,106 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Manages an optional byte parameter.
+ **/
+public class ByteOptional
+{
+ /**
+ * The value defaults to unset.
+ **/
+ public ByteOptional()
+ {
+ _isSet = false;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The initial value.
+ **/
+ public ByteOptional(byte v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * Sets the value to a shallow copy of the given optional.
+ *
+ * @param opt The source value.
+ **/
+ public ByteOptional(ByteOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Obtains the current value.
+ *
+ * @return The current value.
+ * @throws IllegalStateException If the value is not set.
+ **/
+ public byte get()
+ {
+ if(!_isSet)
+ {
+ throw new IllegalStateException("no value is set");
+ }
+ return _value;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The new value.
+ **/
+ public void set(byte v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * If the given argument is set, this optional is set to a shallow copy of the argument,
+ * otherwise this optional is unset.
+ *
+ * @param opt The source value.
+ **/
+ public void set(ByteOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Determines whether the value is set.
+ *
+ * @return True if the value is set, false otherwise.
+ **/
+ public boolean isSet()
+ {
+ return _isSet;
+ }
+
+ /**
+ * Unsets this value.
+ **/
+ public void clear()
+ {
+ _isSet = false;
+ _value = 0;
+ }
+
+ private byte _value;
+ private boolean _isSet;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Callback.java b/java-compat/src/Ice/src/main/java/Ice/Callback.java
new file mode 100644
index 00000000000..0d852d6d4c6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Callback.java
@@ -0,0 +1,57 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * An application can optionally supply an instance of this class in an
+ * asynchronous invocation. The application must create a subclass and
+ * implement the completed method.
+ **/
+public abstract class Callback extends IceInternal.CallbackBase
+{
+ /**
+ * Invoked when the invocation completes. The subclass should
+ * call the matching <code>end_OP</code> method on the proxy and
+ * must be prepared to handle exceptions.
+ *
+ * @param r The asynchronous result object returned by the <code>begin_OP</code> method.
+ **/
+ public abstract void completed(AsyncResult r);
+
+ /**
+ * Invoked when the Ice run time has passed the outgoing message
+ * buffer to the transport. The default implementation does nothing,
+ * a subclass can override it if it needs to take action when the
+ * message is successfully sent.
+ *
+ * @param r The asynchronous result object returned by the <code>begin_OP</code> method.
+ **/
+ public void sent(AsyncResult r)
+ {
+ }
+
+ @Override
+ public final void __completed(AsyncResult r)
+ {
+ completed(r);
+ }
+
+ @Override
+ public final void __sent(AsyncResult r)
+ {
+ sent(r);
+ }
+
+ @Override
+ public final boolean __hasSentCallback()
+ {
+ return true;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Callback_Communicator_flushBatchRequests.java b/java-compat/src/Ice/src/main/java/Ice/Callback_Communicator_flushBatchRequests.java
new file mode 100644
index 00000000000..ef8fabded16
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Callback_Communicator_flushBatchRequests.java
@@ -0,0 +1,55 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Asynchronous callback base class for Communicator.begin_flushBatchRequests.
+ **/
+public abstract class Callback_Communicator_flushBatchRequests extends IceInternal.CallbackBase
+{
+ /**
+ * Called when the invocation raises an Ice run-time exception.
+ *
+ * @param ex The Ice run-time exception raised by the operation.
+ **/
+ public abstract void exception(LocalException ex);
+
+ /**
+ * Called when a queued invocation is sent successfully.
+ **/
+ public void sent(boolean sentSynchronously)
+ {
+ }
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ try
+ {
+ __result.getCommunicator().end_flushBatchRequests(__result);
+ }
+ catch(LocalException __ex)
+ {
+ exception(__ex);
+ }
+ }
+
+ @Override
+ public final void __sent(AsyncResult __result)
+ {
+ sent(__result.sentSynchronously());
+ }
+
+ @Override
+ public final boolean __hasSentCallback()
+ {
+ return true;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Callback_Connection_flushBatchRequests.java b/java-compat/src/Ice/src/main/java/Ice/Callback_Connection_flushBatchRequests.java
new file mode 100644
index 00000000000..0386c6c8abf
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Callback_Connection_flushBatchRequests.java
@@ -0,0 +1,55 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Asynchronous callback base class for Connection.begin_flushBatchRequests.
+ **/
+public abstract class Callback_Connection_flushBatchRequests extends IceInternal.CallbackBase
+{
+ /**
+ * Called when the invocation raises an Ice run-time exception.
+ *
+ * @param ex The Ice run-time exception raised by the operation.
+ **/
+ public abstract void exception(LocalException ex);
+
+ /**
+ * Called when a queued invocation is sent successfully.
+ **/
+ public void sent(boolean sentSynchronously)
+ {
+ }
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ try
+ {
+ __result.getConnection().end_flushBatchRequests(__result);
+ }
+ catch(LocalException __ex)
+ {
+ exception(__ex);
+ }
+ }
+
+ @Override
+ public final void __sent(AsyncResult __result)
+ {
+ sent(__result.sentSynchronously());
+ }
+
+ @Override
+ public final boolean __hasSentCallback()
+ {
+ return true;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_flushBatchRequests.java b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_flushBatchRequests.java
new file mode 100644
index 00000000000..2154e37cfa4
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_flushBatchRequests.java
@@ -0,0 +1,22 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Callback object for {@link ObjectPrx#begin_ice_flushBatchRequests}.
+ **/
+public abstract class Callback_Object_ice_flushBatchRequests extends OnewayCallback
+{
+ @Override
+ public final void response()
+ {
+ // Not used.
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_getConnection.java b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_getConnection.java
new file mode 100644
index 00000000000..f65533fdaf1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_getConnection.java
@@ -0,0 +1,31 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Callback object for {@link ObjectPrx#begin_ice_getConnection}.
+ **/
+public abstract class Callback_Object_ice_getConnection extends IceInternal.TwowayCallback
+ implements Ice.TwowayCallbackArg1<Ice.Connection>
+{
+ /**
+ * Called when the invocation completes successfully.
+ *
+ * @param __ret The connection being used by the proxy.
+ **/
+ @Override
+ public abstract void response(Ice.Connection __ret);
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ ObjectPrxHelperBase.__ice_getConnection_completed(this, __result);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_id.java b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_id.java
new file mode 100644
index 00000000000..541989f45da
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_id.java
@@ -0,0 +1,31 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Callback object for {@link ObjectPrx#begin_ice_id}.
+ **/
+public abstract class Callback_Object_ice_id extends IceInternal.TwowayCallback
+ implements Ice.TwowayCallbackArg1<String>
+{
+ /**
+ * Called when the invocation completes successfully.
+ *
+ * @param __ret The Slice type id of the most-derived interface supported by the target object.
+ **/
+ @Override
+ public abstract void response(String __ret);
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ ObjectPrxHelperBase.__ice_id_completed(this, __result);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_ids.java b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_ids.java
new file mode 100644
index 00000000000..ab2ecbd5a95
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_ids.java
@@ -0,0 +1,31 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Callback object for {@link ObjectPrx#begin_ice_ids}.
+ **/
+public abstract class Callback_Object_ice_ids extends IceInternal.TwowayCallback
+ implements Ice.TwowayCallbackArg1<String[]>
+{
+ /**
+ * Called when the invocation completes successfully.
+ *
+ * @param __ret The Slice type ids of the interfaces supported by the target object.
+ **/
+ @Override
+ public abstract void response(String[] __ret);
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ ObjectPrxHelperBase.__ice_ids_completed(this, __result);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_invoke.java b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_invoke.java
new file mode 100644
index 00000000000..a60a22ce7ff
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_invoke.java
@@ -0,0 +1,36 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Callback object for {@link ObjectPrx#begin_ice_invoke}.
+ **/
+public abstract class Callback_Object_ice_invoke
+ extends IceInternal.TwowayCallback implements _Callback_Object_ice_invoke
+{
+ /**
+ * The Ice run time calls <code>response</code> when an asynchronous operation invocation
+ * completes successfully or raises a user exception.
+ *
+ * @param ret Indicates the result of the invocation. If <code>true</code>, the operation
+ * completed succesfully; if <code>false</code>, the operation raised a user exception.
+ * @param outParams Contains the encoded out-parameters of the operation (if any) if <code>ok</code>
+ * is <code>true</code>; otherwise, if <code>ok</code> is <code>false</code>, contains the
+ * encoded user exception raised by the operation.
+ **/
+ @Override
+ public abstract void response(boolean ret, byte[] outParams);
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ ObjectPrxHelperBase.__ice_invoke_completed(this, __result);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_isA.java b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_isA.java
new file mode 100644
index 00000000000..8ccba433133
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_isA.java
@@ -0,0 +1,30 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Callback object for {@link ObjectPrx#begin_ice_isA}.
+ **/
+public abstract class Callback_Object_ice_isA extends IceInternal.TwowayCallback implements Ice.TwowayCallbackBool
+{
+ /**
+ * Called when the invocation completes successfully.
+ *
+ * @param __ret True if the target object supports the given interface, false otherwise.
+ **/
+ @Override
+ public abstract void response(boolean __ret);
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ ObjectPrxHelperBase.__ice_isA_completed(this, __result);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_ping.java b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_ping.java
new file mode 100644
index 00000000000..61be444f1bc
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Callback_Object_ice_ping.java
@@ -0,0 +1,17 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Callback object for {@link ObjectPrx#begin_ice_ping}.
+ **/
+public abstract class Callback_Object_ice_ping extends OnewayCallback
+{
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ClassResolver.java b/java-compat/src/Ice/src/main/java/Ice/ClassResolver.java
new file mode 100644
index 00000000000..87be1d49ce3
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ClassResolver.java
@@ -0,0 +1,29 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ *
+ * A ClassResolver translates a Slice type Id into a Java class using
+ * an implementation-defined algorithm.
+ *
+ **/
+public interface ClassResolver
+{
+ /**
+ * Resolve a Slice type Id into a Java class. The type Id corresponds to a
+ * Slice value or user exception.
+ *
+ * @param typeId A string type ID (such as <code>"::Module::Class"</code>).
+ * @return The Java class object corresponding to the Slice type ID, or null
+ * if no class could be found.
+ **/
+ Class<?> resolveClass(String typeId);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java b/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java
new file mode 100644
index 00000000000..5523f7663b4
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java
@@ -0,0 +1,389 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public final class CommunicatorI implements Communicator
+{
+ @Override
+ public void
+ destroy()
+ {
+ _instance.destroy();
+ }
+
+ @Override
+ public void
+ shutdown()
+ {
+ _instance.objectAdapterFactory().shutdown();
+ }
+
+ @Override
+ public void
+ waitForShutdown()
+ {
+ _instance.objectAdapterFactory().waitForShutdown();
+ }
+
+ @Override
+ public boolean
+ isShutdown()
+ {
+ return _instance.objectAdapterFactory().isShutdown();
+ }
+
+ @Override
+ public Ice.ObjectPrx
+ stringToProxy(String s)
+ {
+ return _instance.proxyFactory().stringToProxy(s);
+ }
+
+ @Override
+ public String
+ proxyToString(Ice.ObjectPrx proxy)
+ {
+ return _instance.proxyFactory().proxyToString(proxy);
+ }
+
+ @Override
+ public Ice.ObjectPrx
+ propertyToProxy(String s)
+ {
+ return _instance.proxyFactory().propertyToProxy(s);
+ }
+
+ @Override
+ public java.util.Map<String, String>
+ proxyToProperty(Ice.ObjectPrx proxy, String prefix)
+ {
+ return _instance.proxyFactory().proxyToProperty(proxy, prefix);
+ }
+
+ @Override @SuppressWarnings("deprecation")
+ public Ice.Identity
+ stringToIdentity(String s)
+ {
+ return Ice.Util.stringToIdentity(s);
+ }
+
+ @Override @SuppressWarnings("deprecation")
+ public String
+ identityToString(Ice.Identity ident)
+ {
+ return Ice.Util.identityToString(ident);
+ }
+
+ @Override
+ public ObjectAdapter
+ createObjectAdapter(String name)
+ {
+ return _instance.objectAdapterFactory().createObjectAdapter(name, null);
+ }
+
+ @Override
+ public ObjectAdapter
+ createObjectAdapterWithEndpoints(String name, String endpoints)
+ {
+ if(name.length() == 0)
+ {
+ name = java.util.UUID.randomUUID().toString();
+ }
+
+ getProperties().setProperty(name + ".Endpoints", endpoints);
+ return _instance.objectAdapterFactory().createObjectAdapter(name, null);
+ }
+
+ @Override
+ public ObjectAdapter
+ createObjectAdapterWithRouter(String name, RouterPrx router)
+ {
+ if(name.length() == 0)
+ {
+ name = java.util.UUID.randomUUID().toString();
+ }
+
+ //
+ // We set the proxy properties here, although we still use the proxy supplied.
+ //
+ java.util.Map<String, String> properties = proxyToProperty(router, name + ".Router");
+ for(java.util.Map.Entry<String, String> p : properties.entrySet())
+ {
+ getProperties().setProperty(p.getKey(), p.getValue());
+ }
+
+ return _instance.objectAdapterFactory().createObjectAdapter(name, router);
+ }
+
+ @Override @SuppressWarnings("deprecation")
+ public void addObjectFactory(ObjectFactory factory, String id)
+ {
+ _instance.addObjectFactory(factory, id);
+ }
+
+ @Override @SuppressWarnings("deprecation")
+ public ObjectFactory findObjectFactory(String id)
+ {
+ return _instance.findObjectFactory(id);
+ }
+
+ @Override
+ public ValueFactoryManager getValueFactoryManager()
+ {
+ return _instance.initializationData().valueFactoryManager;
+ }
+
+ @Override
+ public Properties
+ getProperties()
+ {
+ return _instance.initializationData().properties;
+ }
+
+ @Override
+ public Logger
+ getLogger()
+ {
+ return _instance.initializationData().logger;
+ }
+
+ @Override
+ public Ice.Instrumentation.CommunicatorObserver
+ getObserver()
+ {
+ return _instance.initializationData().observer;
+ }
+
+ @Override
+ public RouterPrx
+ getDefaultRouter()
+ {
+ return _instance.referenceFactory().getDefaultRouter();
+ }
+
+ @Override
+ public void
+ setDefaultRouter(RouterPrx router)
+ {
+ _instance.setDefaultRouter(router);
+ }
+
+ @Override
+ public LocatorPrx
+ getDefaultLocator()
+ {
+ return _instance.referenceFactory().getDefaultLocator();
+ }
+
+ @Override
+ public void
+ setDefaultLocator(LocatorPrx locator)
+ {
+ _instance.setDefaultLocator(locator);
+ }
+
+ @Override
+ public ImplicitContext
+ getImplicitContext()
+ {
+ return _instance.getImplicitContext();
+ }
+
+ @Override
+ public PluginManager
+ getPluginManager()
+ {
+ return _instance.pluginManager();
+ }
+
+ @Override
+ public void
+ flushBatchRequests()
+ {
+ end_flushBatchRequests(begin_flushBatchRequests());
+ }
+
+ @Override
+ public AsyncResult
+ begin_flushBatchRequests()
+ {
+ return begin_flushBatchRequestsInternal(null);
+ }
+
+ @Override
+ public AsyncResult
+ begin_flushBatchRequests(Callback cb)
+ {
+ return begin_flushBatchRequestsInternal(cb);
+ }
+
+ @Override
+ public AsyncResult
+ begin_flushBatchRequests(Callback_Communicator_flushBatchRequests cb)
+ {
+ return begin_flushBatchRequestsInternal(cb);
+ }
+
+ @Override
+ public AsyncResult
+ begin_flushBatchRequests(IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_flushBatchRequestsInternal(
+ new IceInternal.Functional_CallbackBase(false, __exceptionCb, __sentCb)
+ {
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ try
+ {
+ __result.getCommunicator().end_flushBatchRequests(__result);
+ }
+ catch(Exception __ex)
+ {
+ __exceptionCb.apply(__ex);
+ }
+ }
+ });
+ }
+
+ private static final String __flushBatchRequests_name = "flushBatchRequests";
+
+ private Ice.AsyncResult
+ begin_flushBatchRequestsInternal(IceInternal.CallbackBase cb)
+ {
+ IceInternal.OutgoingConnectionFactory connectionFactory = _instance.outgoingConnectionFactory();
+ IceInternal.ObjectAdapterFactory adapterFactory = _instance.objectAdapterFactory();
+
+ //
+ // This callback object receives the results of all invocations
+ // of Connection.begin_flushBatchRequests.
+ //
+ IceInternal.CommunicatorFlushBatch result = new IceInternal.CommunicatorFlushBatch(this,
+ _instance,
+ __flushBatchRequests_name,
+ cb);
+
+ connectionFactory.flushAsyncBatchRequests(result);
+ adapterFactory.flushAsyncBatchRequests(result);
+
+ //
+ // Inform the callback that we have finished initiating all of the
+ // flush requests.
+ //
+ result.ready();
+
+ return result;
+ }
+
+ @Override
+ public void
+ end_flushBatchRequests(AsyncResult r)
+ {
+ IceInternal.CommunicatorFlushBatch ri =
+ IceInternal.CommunicatorFlushBatch.check(r, this, __flushBatchRequests_name);
+ ri.__wait();
+ }
+
+
+ @Override
+ public ObjectPrx
+ createAdmin(ObjectAdapter adminAdapter, Identity adminId)
+ {
+ return _instance.createAdmin(adminAdapter, adminId);
+ }
+
+ @Override
+ public ObjectPrx
+ getAdmin()
+ {
+ return _instance.getAdmin();
+ }
+
+ @Override
+ public void
+ addAdminFacet(Object servant, String facet)
+ {
+ _instance.addAdminFacet(servant, facet);
+ }
+
+ @Override
+ public Object
+ removeAdminFacet(String facet)
+ {
+ return _instance.removeAdminFacet(facet);
+ }
+
+ @Override
+ public Object
+ findAdminFacet(String facet)
+ {
+ return _instance.findAdminFacet(facet);
+ }
+
+ @Override
+ public java.util.Map<String, Ice.Object>
+ findAllAdminFacets()
+ {
+ return _instance.findAllAdminFacets();
+ }
+
+ CommunicatorI(InitializationData initData)
+ {
+ _instance = new IceInternal.Instance(this, initData);
+ }
+
+ /**
+ * For compatibility with C#, we do not invoke methods on other objects
+ * from within a finalizer.
+ *
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ if(!_instance.destroyed())
+ {
+ _instance.logger().warning("Ice::Communicator::destroy() has not been called");
+ }
+
+ super.finalize();
+ }
+ */
+
+ //
+ // Certain initialization tasks need to be completed after the
+ // constructor.
+ //
+ void
+ finishSetup(StringSeqHolder args)
+ {
+ try
+ {
+ _instance.finishSetup(args, this);
+ }
+ catch(RuntimeException ex)
+ {
+ _instance.destroy();
+ throw ex;
+ }
+ }
+
+ //
+ // For use by IceInternal.Util.getInstance()
+ //
+ public IceInternal.Instance
+ getInstance()
+ {
+ return _instance;
+ }
+
+ private IceInternal.Instance _instance;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/CompactIdResolver.java b/java-compat/src/Ice/src/main/java/Ice/CompactIdResolver.java
new file mode 100644
index 00000000000..d959ab38904
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/CompactIdResolver.java
@@ -0,0 +1,29 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Applications that make use of compact type IDs to conserve space
+ * when marshaling class instances, and also use the streaming API to
+ * extract such classes, can intercept the translation between compact
+ * type IDs and their corresponding string type IDs by installing an
+ * instance of <code>CompactIdResolver</code> in <code>InitializationData</code>.
+ **/
+public interface CompactIdResolver
+{
+ /**
+ * Translates a compact (integer) ID into its string equivalent.
+ *
+ * @param id The compact ID.
+ * @return A string type ID (such as <code>"::Module::Class"</code>),
+ * or an empty string if the compact ID is unknown.
+ **/
+ String resolve(int id);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ConnectionI.java b/java-compat/src/Ice/src/main/java/Ice/ConnectionI.java
new file mode 100644
index 00000000000..cac2a6fb3d2
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ConnectionI.java
@@ -0,0 +1,3030 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+import java.util.concurrent.Callable;
+
+public final class ConnectionI extends IceInternal.EventHandler
+ implements Connection, IceInternal.ResponseHandler, IceInternal.CancellationHandler
+{
+ public interface StartCallback
+ {
+ void connectionStartCompleted(ConnectionI connection);
+
+ void connectionStartFailed(ConnectionI connection, Ice.LocalException ex);
+ }
+
+ private class TimeoutCallback implements Runnable
+ {
+ @Override
+ public void run()
+ {
+ timedOut();
+ }
+ }
+
+ public void start(StartCallback callback)
+ {
+ try
+ {
+ synchronized(this)
+ {
+ // The connection might already be closed if the communicator
+ // was destroyed.
+ if(_state >= StateClosed)
+ {
+ assert (_exception != null);
+ throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+
+ if(!initialize(IceInternal.SocketOperation.None) || !validate(IceInternal.SocketOperation.None))
+ {
+ _startCallback = callback;
+ return;
+ }
+
+ //
+ // We start out in holding state.
+ //
+ setState(StateHolding);
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ exception(ex);
+ callback.connectionStartFailed(this, _exception);
+ return;
+ }
+
+ callback.connectionStartCompleted(this);
+ }
+
+ public void startAndWait() throws InterruptedException
+ {
+ try
+ {
+ synchronized(this)
+ {
+ // The connection might already be closed if the communicator
+ // was destroyed.
+ if(_state >= StateClosed)
+ {
+ assert (_exception != null);
+ throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+
+ if(!initialize(IceInternal.SocketOperation.None) || !validate(IceInternal.SocketOperation.None))
+ {
+ while(_state <= StateNotValidated)
+ {
+ wait();
+ }
+
+ if(_state >= StateClosing)
+ {
+ assert (_exception != null);
+ throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+ }
+
+ //
+ // We start out in holding state.
+ //
+ setState(StateHolding);
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ exception(ex);
+ waitUntilFinished();
+ }
+ }
+
+ public synchronized void activate()
+ {
+ if(_state <= StateNotValidated)
+ {
+ return;
+ }
+
+ if(_acmLastActivity > 0)
+ {
+ _acmLastActivity = IceInternal.Time.currentMonotonicTimeMillis();
+ }
+
+ setState(StateActive);
+ }
+
+ public synchronized void hold()
+ {
+ if(_state <= StateNotValidated)
+ {
+ return;
+ }
+
+ setState(StateHolding);
+ }
+
+ // DestructionReason.
+ public final static int ObjectAdapterDeactivated = 0;
+ public final static int CommunicatorDestroyed = 1;
+
+ synchronized public void destroy(int reason)
+ {
+ switch(reason)
+ {
+ case ObjectAdapterDeactivated:
+ {
+ setState(StateClosing, new ObjectAdapterDeactivatedException());
+ break;
+ }
+
+ case CommunicatorDestroyed:
+ {
+ setState(StateClosing, new CommunicatorDestroyedException());
+ break;
+ }
+ }
+ }
+
+ @Override
+ synchronized public void close(boolean force)
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+
+ if(force)
+ {
+ setState(StateClosed, new ForcedCloseConnectionException());
+ }
+ 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.
+ //
+ while(!_asyncRequests.isEmpty())
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+
+ setState(StateClosing, new CloseConnectionException());
+ }
+ }
+
+ public synchronized boolean isActiveOrHolding()
+ {
+ return _state > StateNotValidated && _state < StateClosing;
+ }
+
+ public synchronized boolean isFinished()
+ {
+ if(_state != StateFinished || _dispatchCount != 0)
+ {
+ return false;
+ }
+
+ assert (_state == StateFinished);
+ return true;
+ }
+
+ public synchronized void throwException()
+ {
+ if(_exception != null)
+ {
+ assert (_state >= StateClosing);
+ throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+ }
+
+ public synchronized void waitUntilHolding() throws InterruptedException
+ {
+ while(_state < StateHolding || _dispatchCount > 0)
+ {
+ wait();
+ }
+ }
+
+ public synchronized void waitUntilFinished() throws InterruptedException
+ {
+ //
+ // We wait indefinitely until the connection 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.
+ //
+ while(_state < StateFinished || _dispatchCount > 0)
+ {
+ wait();
+ }
+
+ assert (_state == StateFinished);
+
+ //
+ // Clear the OA. See bug 1673 for the details of why this is necessary.
+ //
+ _adapter = null;
+ }
+
+ synchronized public void updateObserver()
+ {
+ if(_state < StateNotValidated || _state > StateClosed)
+ {
+ return;
+ }
+
+ assert (_instance.initializationData().observer != null);
+ _observer = _instance.initializationData().observer.getConnectionObserver(initConnectionInfo(),
+ _endpoint,
+ toConnectionState(_state),
+ _observer);
+ if(_observer != null)
+ {
+ _observer.attach();
+ }
+ else
+ {
+ _writeStreamPos = -1;
+ _readStreamPos = -1;
+ }
+ }
+
+ synchronized public void monitor(long now, IceInternal.ACMConfig acm)
+ {
+ if(_state != StateActive)
+ {
+ return;
+ }
+
+ //
+ // We send a heartbeat if there was no activity in the last
+ // (timeout / 4) period. Sending a heartbeat sooner than
+ // really needed is safer to ensure that the receiver will
+ // receive in time the heartbeat. Sending the heartbeat if
+ // there was no activity in the last (timeout / 2) period
+ // isn't enough since monitor() is called only every (timeout
+ // / 2) period.
+ //
+ // Note that this doesn't imply that we are sending 4
+ // heartbeats per timeout period because the monitor() method
+ // is sill only called every (timeout / 2) period.
+ //
+ if(acm.heartbeat == ACMHeartbeat.HeartbeatAlways ||
+ (acm.heartbeat != ACMHeartbeat.HeartbeatOff && _writeStream.isEmpty() &&
+ now >= (_acmLastActivity + acm.timeout / 4)))
+ {
+ if(acm.heartbeat != ACMHeartbeat.HeartbeatOnInvocation || _dispatchCount > 0)
+ {
+ heartbeat();
+ }
+ }
+
+ if(_readStream.size() > IceInternal.Protocol.headerSize || !_writeStream.isEmpty())
+ {
+ //
+ // If writing or reading, nothing to do, the connection
+ // timeout will kick-in if writes or reads don't progress.
+ // This check is necessary because the activity timer is
+ // only set when a message is fully read/written.
+ //
+ return;
+ }
+
+ if(acm.close != ACMClose.CloseOff && now >= (_acmLastActivity + acm.timeout))
+ {
+ if(acm.close == ACMClose.CloseOnIdleForceful ||
+ (acm.close != ACMClose.CloseOnIdle && (!_asyncRequests.isEmpty())))
+ {
+ //
+ // Close the connection if we didn't receive a heartbeat in
+ // the last period.
+ //
+ setState(StateClosed, new ConnectionTimeoutException());
+ }
+ else if(acm.close != ACMClose.CloseOnInvocation && _dispatchCount == 0 && _batchRequestQueue.isEmpty() &&
+ _asyncRequests.isEmpty())
+ {
+ //
+ // The connection is idle, close it.
+ //
+ setState(StateClosing, new ConnectionTimeoutException());
+ }
+ }
+ }
+
+ synchronized public int
+ sendAsyncRequest(IceInternal.OutgoingAsyncBase out, boolean compress, boolean response, int batchRequestNum)
+ throws IceInternal.RetryException
+ {
+ final OutputStream os = out.getOs();
+
+ if(_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 IceInternal.RetryException((Ice.LocalException) _exception.fillInStackTrace());
+ }
+
+ assert (_state > StateNotValidated);
+ assert (_state < StateClosing);
+
+ //
+ // Ensure the message isn't bigger than what we can send with the
+ // transport.
+ //
+ _transceiver.checkSendSize(os.getBuffer());
+
+ //
+ // Notify the request that it's cancelable with this connection.
+ // This will throw if the request is canceled.
+ //
+ out.cancelable(this);
+
+ int requestId = 0;
+ if(response)
+ {
+ //
+ // Create a new unique request ID.
+ //
+ requestId = _nextRequestId++;
+ if(requestId <= 0)
+ {
+ _nextRequestId = 1;
+ requestId = _nextRequestId++;
+ }
+
+ //
+ // Fill in the request ID.
+ //
+ os.pos(IceInternal.Protocol.headerSize);
+ os.writeInt(requestId);
+ }
+ else if(batchRequestNum > 0)
+ {
+ os.pos(IceInternal.Protocol.headerSize);
+ os.writeInt(batchRequestNum);
+ }
+
+ out.attachRemoteObserver(initConnectionInfo(), _endpoint, requestId);
+
+ int status;
+ try
+ {
+ status = sendMessage(new OutgoingMessage(out, os, compress, requestId));
+ }
+ catch(Ice.LocalException ex)
+ {
+ setState(StateClosed, ex);
+ assert (_exception != null);
+ throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+
+ if(response)
+ {
+ //
+ // Add to the async requests map.
+ //
+ _asyncRequests.put(requestId, out);
+ }
+ return status;
+ }
+
+ public IceInternal.BatchRequestQueue
+ getBatchRequestQueue()
+ {
+ return _batchRequestQueue;
+ }
+
+ @Override
+ public void flushBatchRequests()
+ {
+ end_flushBatchRequests(begin_flushBatchRequests());
+ }
+
+ private static final String __flushBatchRequests_name = "flushBatchRequests";
+
+ @Override
+ public Ice.AsyncResult begin_flushBatchRequests()
+ {
+ return begin_flushBatchRequestsInternal(null);
+ }
+
+ @Override
+ public Ice.AsyncResult begin_flushBatchRequests(Callback cb)
+ {
+ return begin_flushBatchRequestsInternal(cb);
+ }
+
+ @Override
+ public Ice.AsyncResult begin_flushBatchRequests(Callback_Connection_flushBatchRequests cb)
+ {
+ return begin_flushBatchRequestsInternal(cb);
+ }
+
+ @Override
+ public AsyncResult begin_flushBatchRequests(IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_flushBatchRequestsInternal(new IceInternal.Functional_CallbackBase(false, __exceptionCb, __sentCb)
+ {
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ try
+ {
+ __result.getConnection().end_flushBatchRequests(__result);
+ }
+ catch(Exception __ex)
+ {
+ __exceptionCb.apply(__ex);
+ }
+ }
+ });
+ }
+
+ private Ice.AsyncResult begin_flushBatchRequestsInternal(IceInternal.CallbackBase cb)
+ {
+ IceInternal.ConnectionFlushBatch result =
+ new IceInternal.ConnectionFlushBatch(this, _communicator, _instance, __flushBatchRequests_name, cb);
+ result.invoke();
+ return result;
+ }
+
+ @Override
+ public void end_flushBatchRequests(AsyncResult ir)
+ {
+ IceInternal.ConnectionFlushBatch r =
+ IceInternal.ConnectionFlushBatch.check(ir, this, __flushBatchRequests_name);
+ r.__wait();
+ }
+
+ @Override
+ synchronized public void setCloseCallback(final CloseCallback callback)
+ {
+ if(_state >= StateClosed)
+ {
+ if(callback != null)
+ {
+ _threadPool.dispatch(new IceInternal.DispatchWorkItem(this)
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ callback.closed(ConnectionI.this);
+ }
+ catch(Exception ex)
+ {
+ _logger.error("connection callback exception:\n" + ex + '\n' + _desc);
+ }
+ }
+ });
+ }
+ }
+ else
+ {
+ _closeCallback = callback;
+ }
+ }
+
+ @Override
+ synchronized public void setHeartbeatCallback(final HeartbeatCallback callback)
+ {
+ _heartbeatCallback = callback;
+ }
+
+ @Override
+ synchronized public void setACM(Ice.IntOptional timeout, Ice.Optional<ACMClose> close,
+ Ice.Optional<ACMHeartbeat> heartbeat)
+ {
+ if(_monitor == null || _state >= StateClosed)
+ {
+ return;
+ }
+
+ if(_state == StateActive)
+ {
+ _monitor.remove(this);
+ }
+ _monitor = _monitor.acm(timeout, close, heartbeat);
+
+ if(_monitor.getACM().timeout <= 0)
+ {
+ _acmLastActivity = -1; // Disable the recording of last activity.
+ }
+ else if(_state == StateActive && _acmLastActivity == -1)
+ {
+ _acmLastActivity = IceInternal.Time.currentMonotonicTimeMillis();
+ }
+
+ if(_state == StateActive)
+ {
+ _monitor.add(this);
+ }
+ }
+
+ @Override
+ synchronized public Ice.ACM getACM()
+ {
+ return _monitor != null ? _monitor.getACM() : new ACM(0, ACMClose.CloseOff, ACMHeartbeat.HeartbeatOff);
+ }
+
+ @Override
+ synchronized public void asyncRequestCanceled(IceInternal.OutgoingAsyncBase outAsync, Ice.LocalException ex)
+ {
+ if(_state >= StateClosed)
+ {
+ return; // The request has already been or will be shortly notified of the failure.
+ }
+
+ java.util.Iterator<OutgoingMessage> it = _sendStreams.iterator();
+ while(it.hasNext())
+ {
+ OutgoingMessage o = it.next();
+ if(o.outAsync == outAsync)
+ {
+ if(o.requestId > 0)
+ {
+ _asyncRequests.remove(o.requestId);
+ }
+
+ if(ex instanceof ConnectionTimeoutException)
+ {
+ setState(StateClosed, ex);
+ }
+ else
+ {
+ //
+ // If the request is being sent, don't remove it from the send
+ // streams, it will be removed once the sending is finished.
+ //
+ // Note that since we swapped the message stream to _writeStream
+ // it's fine if the OutgoingAsync output stream is released (and
+ // as long as canceled requests cannot be retried).
+ //
+ o.canceled();
+ if(o != _sendStreams.getFirst())
+ {
+ it.remove();
+ }
+ if(outAsync.completed(ex))
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ }
+ return;
+ }
+ }
+
+ if(outAsync instanceof IceInternal.OutgoingAsync)
+ {
+ IceInternal.OutgoingAsync o = (IceInternal.OutgoingAsync) outAsync;
+ java.util.Iterator<IceInternal.OutgoingAsyncBase> it2 = _asyncRequests.values().iterator();
+ while(it2.hasNext())
+ {
+ if(it2.next() == o)
+ {
+ if(ex instanceof ConnectionTimeoutException)
+ {
+ setState(StateClosed, ex);
+ }
+ else
+ {
+ it2.remove();
+ if(outAsync.completed(ex))
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ }
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ synchronized public void sendResponse(int requestId, OutputStream os, byte compressFlag, boolean amd)
+ {
+ assert (_state > StateNotValidated);
+
+ try
+ {
+ if(--_dispatchCount == 0)
+ {
+ if(_state == StateFinished)
+ {
+ reap();
+ }
+ notifyAll();
+ }
+
+ if(_state >= StateClosed)
+ {
+ assert (_exception != null);
+ throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+
+ sendMessage(new OutgoingMessage(os, compressFlag != 0, true));
+
+ if(_state == StateClosing && _dispatchCount == 0)
+ {
+ initiateShutdown();
+ }
+ }
+ catch(LocalException ex)
+ {
+ setState(StateClosed, ex);
+ }
+ }
+
+ @Override
+ synchronized public void sendNoResponse()
+ {
+ assert (_state > StateNotValidated);
+ try
+ {
+ if(--_dispatchCount == 0)
+ {
+ if(_state == StateFinished)
+ {
+ reap();
+ }
+ notifyAll();
+ }
+
+ if(_state >= StateClosed)
+ {
+ assert (_exception != null);
+ throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+
+ if(_state == StateClosing && _dispatchCount == 0)
+ {
+ initiateShutdown();
+ }
+ }
+ catch(LocalException ex)
+ {
+ setState(StateClosed, ex);
+ }
+ }
+
+ @Override
+ public boolean systemException(int requestId, Ice.SystemException ex, boolean amd)
+ {
+ return false; // System exceptions aren't marshalled.
+ }
+
+ @Override
+ public synchronized void invokeException(int requestId, LocalException ex, int invokeNum, boolean amd)
+ {
+ //
+ // Fatal exception while invoking a request. Since
+ // sendResponse/sendNoResponse isn't
+ // called in case of a fatal exception we decrement _dispatchCount here.
+ //
+
+ setState(StateClosed, ex);
+
+ if(invokeNum > 0)
+ {
+ assert (_dispatchCount > 0);
+ _dispatchCount -= invokeNum;
+ assert (_dispatchCount >= 0);
+ if(_dispatchCount == 0)
+ {
+ if(_state == StateFinished)
+ {
+ reap();
+ }
+ notifyAll();
+ }
+ }
+ }
+
+ public IceInternal.EndpointI endpoint()
+ {
+ return _endpoint; // No mutex protection necessary, _endpoint is
+ // immutable.
+ }
+
+ public IceInternal.Connector connector()
+ {
+ return _connector; // No mutex protection necessary, _connector is
+ // immutable.
+ }
+
+ @Override
+ public synchronized void setAdapter(ObjectAdapter adapter)
+ {
+ if(_state <= StateNotValidated || _state >= StateClosing)
+ {
+ return;
+ }
+
+ _adapter = adapter;
+
+ if(_adapter != null)
+ {
+ _servantManager = ((ObjectAdapterI) _adapter).getServantManager();
+ if(_servantManager == null)
+ {
+ _adapter = null;
+ }
+ }
+ else
+ {
+ _servantManager = null;
+ }
+
+ //
+ // We never change the thread pool with which we were
+ // initially registered, even if we add or remove an object
+ // adapter.
+ //
+ }
+
+ @Override
+ public synchronized ObjectAdapter getAdapter()
+ {
+ return _adapter;
+ }
+
+ @Override
+ public Endpoint getEndpoint()
+ {
+ return _endpoint; // No mutex protection necessary, _endpoint is
+ // immutable.
+ }
+
+ @Override
+ public ObjectPrx createProxy(Identity ident)
+ {
+ //
+ // Create a reference and return a reverse proxy for this
+ // reference.
+ //
+ return _instance.proxyFactory().referenceToProxy(_instance.referenceFactory().create(ident, this));
+ }
+
+ //
+ // Operations from EventHandler
+ //
+ @Override
+ public void message(IceInternal.ThreadPoolCurrent current)
+ {
+ StartCallback startCB = null;
+ java.util.List<OutgoingMessage> sentCBs = null;
+ MessageInfo info = null;
+ int dispatchCount = 0;
+
+ synchronized(this)
+ {
+ if(_state >= StateClosed)
+ {
+ return;
+ }
+
+ if(!current.ioReady())
+ {
+ return;
+ }
+
+ int readyOp = current.operation;
+ try
+ {
+ unscheduleTimeout(current.operation);
+
+ int writeOp = IceInternal.SocketOperation.None;
+ int readOp = IceInternal.SocketOperation.None;
+
+ if((readyOp & IceInternal.SocketOperation.Write) != 0)
+ {
+ final IceInternal.Buffer buf = _writeStream.getBuffer();
+ if(_observer != null)
+ {
+ observerStartWrite(buf);
+ }
+ writeOp = write(buf);
+ if(_observer != null && (writeOp & IceInternal.SocketOperation.Write) == 0)
+ {
+ observerFinishWrite(buf);
+ }
+ }
+
+ while((readyOp & IceInternal.SocketOperation.Read) != 0)
+ {
+ final IceInternal.Buffer buf = _readStream.getBuffer();
+ if(_observer != null && !_readHeader)
+ {
+ observerStartRead(buf);
+ }
+
+ readOp = read(buf);
+ if((readOp & IceInternal.SocketOperation.Read) != 0)
+ {
+ break;
+ }
+ if(_observer != null && !_readHeader)
+ {
+ assert (!buf.b.hasRemaining());
+ observerFinishRead(buf);
+ }
+
+ if(_readHeader) // Read header if necessary.
+ {
+ _readHeader = false;
+
+ if(_observer != null)
+ {
+ _observer.receivedBytes(IceInternal.Protocol.headerSize);
+ }
+
+ int pos = _readStream.pos();
+ if(pos < IceInternal.Protocol.headerSize)
+ {
+ //
+ // This situation is possible for small UDP packets.
+ //
+ throw new Ice.IllegalMessageSizeException();
+ }
+
+ _readStream.pos(0);
+ byte[] m = new byte[4];
+ m[0] = _readStream.readByte();
+ m[1] = _readStream.readByte();
+ m[2] = _readStream.readByte();
+ m[3] = _readStream.readByte();
+ if(m[0] != IceInternal.Protocol.magic[0] || m[1] != IceInternal.Protocol.magic[1] ||
+ m[2] != IceInternal.Protocol.magic[2] || m[3] != IceInternal.Protocol.magic[3])
+ {
+ Ice.BadMagicException ex = new Ice.BadMagicException();
+ ex.badMagic = m;
+ throw ex;
+ }
+
+ _readProtocol.__read(_readStream);
+ IceInternal.Protocol.checkSupportedProtocol(_readProtocol);
+
+ _readProtocolEncoding.__read(_readStream);
+ IceInternal.Protocol.checkSupportedProtocolEncoding(_readProtocolEncoding);
+
+ _readStream.readByte(); // messageType
+ _readStream.readByte(); // compress
+ int size = _readStream.readInt();
+ if(size < IceInternal.Protocol.headerSize)
+ {
+ throw new Ice.IllegalMessageSizeException();
+ }
+ if(size > _messageSizeMax)
+ {
+ IceInternal.Ex.throwMemoryLimitException(size, _messageSizeMax);
+ }
+ if(size > _readStream.size())
+ {
+ _readStream.resize(size);
+ }
+ _readStream.pos(pos);
+ }
+
+ if(_readStream.pos() != _readStream.size())
+ {
+ if(_endpoint.datagram())
+ {
+ // The message was truncated.
+ throw new Ice.DatagramLimitException();
+ }
+ continue;
+ }
+ break;
+ }
+
+ int newOp = readOp | writeOp;
+ readyOp = readyOp & ~newOp;
+ assert (readyOp != 0 || newOp != 0);
+
+ if(_state <= StateNotValidated)
+ {
+ if(newOp != 0)
+ {
+ //
+ // Wait for all the transceiver conditions to be
+ // satisfied before continuing.
+ //
+ scheduleTimeout(newOp);
+ _threadPool.update(this, current.operation, newOp);
+ return;
+ }
+
+ if(_state == StateNotInitialized && !initialize(current.operation))
+ {
+ return;
+ }
+
+ if(_state <= StateNotValidated && !validate(current.operation))
+ {
+ return;
+ }
+
+ _threadPool.unregister(this, current.operation);
+
+ //
+ // We start out in holding state.
+ //
+ setState(StateHolding);
+ if(_startCallback != null)
+ {
+ startCB = _startCallback;
+ _startCallback = null;
+ if(startCB != null)
+ {
+ ++dispatchCount;
+ }
+ }
+ }
+ else
+ {
+ assert (_state <= StateClosingPending);
+
+ //
+ // We parse messages first, if we receive a close
+ // connection message we won't send more messages.
+ //
+ if((readyOp & IceInternal.SocketOperation.Read) != 0)
+ {
+ // Optimization: use the thread's stream.
+ info = new MessageInfo(current.stream);
+ newOp |= parseMessage(info);
+ dispatchCount += info.messageDispatchCount;
+ }
+
+ if((readyOp & IceInternal.SocketOperation.Write) != 0)
+ {
+ sentCBs = new java.util.LinkedList<OutgoingMessage>();
+ newOp |= sendNextMessage(sentCBs);
+ if(!sentCBs.isEmpty())
+ {
+ ++dispatchCount;
+ }
+ else
+ {
+ sentCBs = null;
+ }
+ }
+
+ if(_state < StateClosed)
+ {
+ scheduleTimeout(newOp);
+ _threadPool.update(this, current.operation, newOp);
+ }
+ }
+
+ if(_acmLastActivity > 0)
+ {
+ _acmLastActivity = IceInternal.Time.currentMonotonicTimeMillis();
+ }
+
+ if(dispatchCount == 0)
+ {
+ return; // Nothing to dispatch we're done!
+ }
+
+ _dispatchCount += dispatchCount;
+ current.ioCompleted();
+ }
+ catch(DatagramLimitException ex) // Expected.
+ {
+ if(_warnUdp)
+ {
+ _logger.warning("maximum datagram size of " + _readStream.pos() + " exceeded");
+ }
+ _readStream.resize(IceInternal.Protocol.headerSize);
+ _readStream.pos(0);
+ _readHeader = true;
+ return;
+ }
+ catch(SocketException ex)
+ {
+ setState(StateClosed, ex);
+ return;
+ }
+ catch(LocalException ex)
+ {
+ if(_endpoint.datagram())
+ {
+ if(_warn)
+ {
+ String s = "datagram connection exception:\n" + ex + '\n' + _desc;
+ _logger.warning(s);
+ }
+ _readStream.resize(IceInternal.Protocol.headerSize);
+ _readStream.pos(0);
+ _readHeader = true;
+ }
+ else
+ {
+ setState(StateClosed, ex);
+ }
+ return;
+ }
+ }
+
+ if(!_dispatcher) // Optimization, call dispatch() directly if there's no dispatcher.
+ {
+ dispatch(startCB, sentCBs, info);
+ }
+ else
+ {
+ // No need for the stream if heartbeat callback
+ if(info != null && info.heartbeatCallback == null)
+ {
+ //
+ // Create a new stream for the dispatch instead of using the
+ // thread pool's thread stream.
+ //
+ assert (info.stream == current.stream);
+ InputStream stream = info.stream;
+ info.stream = new InputStream(_instance, IceInternal.Protocol.currentProtocolEncoding);
+ info.stream.swap(stream);
+ }
+
+ final StartCallback finalStartCB = startCB;
+ final java.util.List<OutgoingMessage> finalSentCBs = sentCBs;
+ final MessageInfo finalInfo = info;
+ _threadPool.dispatchFromThisThread(new IceInternal.DispatchWorkItem(this)
+ {
+ @Override
+ public void run()
+ {
+ dispatch(finalStartCB, finalSentCBs, finalInfo);
+ }
+ });
+ }
+ }
+
+ protected void dispatch(StartCallback startCB, java.util.List<OutgoingMessage> sentCBs, MessageInfo info)
+ {
+ int dispatchedCount = 0;
+
+ //
+ // Notify the factory that the connection establishment and
+ // validation has completed.
+ //
+ if(startCB != null)
+ {
+ startCB.connectionStartCompleted(this);
+ ++dispatchedCount;
+ }
+
+ //
+ // Notify AMI calls that the message was sent.
+ //
+ if(sentCBs != null)
+ {
+ for(OutgoingMessage msg : sentCBs)
+ {
+ msg.outAsync.invokeSent();
+ }
+ ++dispatchedCount;
+ }
+
+ if(info != null)
+ {
+ //
+ // Asynchronous replies must be handled outside the thread
+ // synchronization, so that nested calls are possible.
+ //
+ if(info.outAsync != null)
+ {
+ info.outAsync.invokeCompleted();
+ ++dispatchedCount;
+ }
+
+ if(info.heartbeatCallback != null)
+ {
+ try
+ {
+ info.heartbeatCallback.heartbeat(this);
+ }
+ catch(Exception ex)
+ {
+ _logger.error("connection callback exception:\n" + ex + '\n' + _desc);
+ }
+ ++dispatchedCount;
+ }
+
+ //
+ // Method invocation (or multiple invocations for batch messages)
+ // must be done outside the thread synchronization, so that nested
+ // calls are possible.
+ //
+ if(info.invokeNum > 0)
+ {
+ invokeAll(info.stream, info.invokeNum, info.requestId, info.compress, info.servantManager, info.adapter);
+
+ //
+ // Don't increase dispatchedCount, the dispatch count is
+ // decreased when the incoming reply is sent.
+ //
+ }
+ }
+
+ //
+ // Decrease dispatch count.
+ //
+ if(dispatchedCount > 0)
+ {
+ boolean queueShutdown = false;
+
+ synchronized(this)
+ {
+ _dispatchCount -= dispatchedCount;
+ if(_dispatchCount == 0)
+ {
+ //
+ // Only initiate shutdown if not already done. It might
+ // have already been done if the sent callback or AMI
+ // callback was dispatched when the connection was already
+ // in the closing state.
+ //
+ if(_state == StateClosing)
+ {
+ if(_instance.queueRequests())
+ {
+ //
+ // We can't call initiateShutdown() from this thread in certain
+ // situations (such as in Android).
+ //
+ queueShutdown = true;
+ }
+ else
+ {
+ try
+ {
+ initiateShutdown();
+ }
+ catch(Ice.LocalException ex)
+ {
+ setState(StateClosed, ex);
+ }
+ }
+ }
+ else if(_state == StateFinished)
+ {
+ reap();
+ }
+ if(!queueShutdown)
+ {
+ notifyAll();
+ }
+ }
+ }
+
+ if(queueShutdown)
+ {
+ _instance.getQueueExecutor().executeNoThrow(new Callable<Void>()
+ {
+ @Override
+ public Void call() throws Exception
+ {
+ synchronized(ConnectionI.this)
+ {
+ try
+ {
+ initiateShutdown();
+ }
+ catch(Ice.LocalException ex)
+ {
+ setState(StateClosed, ex);
+ }
+ ConnectionI.this.notifyAll();
+ }
+ return null;
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ public void finished(IceInternal.ThreadPoolCurrent current, final boolean close)
+ {
+ synchronized(this)
+ {
+ assert (_state == StateClosed);
+ unscheduleTimeout(IceInternal.SocketOperation.Read | IceInternal.SocketOperation.Write);
+ }
+
+ //
+ // If there are no callbacks to call, we don't call ioCompleted() since
+ // we're not going to call code that will potentially block (this avoids
+ // promoting a new leader and unecessary thread creation, especially if
+ // this is called on shutdown).
+ //
+ if(_startCallback == null && _sendStreams.isEmpty() && _asyncRequests.isEmpty() &&
+ _closeCallback == null && _heartbeatCallback == null)
+ {
+ finish(close);
+ return;
+ }
+
+ current.ioCompleted();
+ if(!_dispatcher) // Optimization, call finish() directly if there's no
+ // dispatcher.
+ {
+ finish(close);
+ }
+ else
+ {
+ _threadPool.dispatchFromThisThread(new IceInternal.DispatchWorkItem(this)
+ {
+ @Override
+ public void run()
+ {
+ finish(close);
+ }
+ });
+ }
+ }
+
+ public void finish(boolean close)
+ {
+ if(!_initialized)
+ {
+ if(_instance.traceLevels().network >= 2)
+ {
+ StringBuffer s = new StringBuffer("failed to ");
+ s.append(_connector != null ? "establish" : "accept");
+ s.append(" ");
+ s.append(_endpoint.protocol());
+ s.append(" connection\n");
+ s.append(toString());
+ s.append("\n");
+ s.append(_exception);
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+ }
+ else
+ {
+ if(_instance.traceLevels().network >= 1)
+ {
+ StringBuffer s = new StringBuffer("closed ");
+ s.append(_endpoint.protocol());
+ s.append(" connection\n");
+ s.append(toString());
+
+ //
+ // Trace the cause of unexpected connection closures
+ //
+ if(!(_exception instanceof CloseConnectionException ||
+ _exception instanceof ForcedCloseConnectionException ||
+ _exception instanceof ConnectionTimeoutException ||
+ _exception instanceof CommunicatorDestroyedException ||
+ _exception instanceof ObjectAdapterDeactivatedException))
+ {
+ s.append("\n");
+ s.append(_exception);
+ }
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+ }
+
+ if(close)
+ {
+ try
+ {
+ _transceiver.close();
+ }
+ catch(Ice.LocalException ex)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ String s = "unexpected connection exception:\n " + _desc + "\n" + sw.toString();
+ _instance.initializationData().logger.error(s);
+ }
+ }
+
+ if(_startCallback != null)
+ {
+ if(_instance.queueRequests())
+ {
+ // The connectStartFailed method might try to connect with another
+ // connector.
+ _instance.getQueueExecutor().executeNoThrow(new Callable<Void>()
+ {
+ @Override
+ public Void call() throws Exception
+ {
+ _startCallback.connectionStartFailed(ConnectionI.this, _exception);
+ return null;
+ }
+ });
+ }
+ else
+ {
+ _startCallback.connectionStartFailed(this, _exception);
+ }
+ _startCallback = null;
+ }
+
+ if(!_sendStreams.isEmpty())
+ {
+ if(!_writeStream.isEmpty())
+ {
+ //
+ // Return the stream to the outgoing call. This is important for
+ // retriable AMI calls which are not marshalled again.
+ //
+ OutgoingMessage message = _sendStreams.getFirst();
+ _writeStream.swap(message.stream);
+ }
+
+ for(OutgoingMessage p : _sendStreams)
+ {
+ p.completed(_exception);
+ if(p.requestId > 0) // Make sure finished isn't called twice.
+ {
+ _asyncRequests.remove(p.requestId);
+ }
+ }
+ _sendStreams.clear();
+ }
+
+ for(IceInternal.OutgoingAsyncBase p : _asyncRequests.values())
+ {
+ if(p.completed(_exception))
+ {
+ p.invokeCompleted();
+ }
+ }
+ _asyncRequests.clear();
+
+ //
+ // Don't wait to be reaped to reclaim memory allocated by read/write streams.
+ //
+ _writeStream.clear();
+ _writeStream.getBuffer().clear();
+ _readStream.clear();
+ _readStream.getBuffer().clear();
+
+ if(_closeCallback != null)
+ {
+ try
+ {
+ _closeCallback.closed(this);
+ }
+ catch(Exception ex)
+ {
+ _logger.error("connection callback exception:\n" + ex + '\n' + _desc);
+ }
+ _closeCallback = null;
+ }
+
+ _heartbeatCallback = null;
+
+ //
+ // This must be done last as this will cause waitUntilFinished() to
+ // return (and communicator objects such as the timer might be destroyed
+ // too).
+ //
+ synchronized(this)
+ {
+ setState(StateFinished);
+
+ if(_dispatchCount == 0)
+ {
+ reap();
+ }
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return _toString();
+ }
+
+ @Override
+ public java.nio.channels.SelectableChannel fd()
+ {
+ return _transceiver.fd();
+ }
+
+ @Override
+ public void setReadyCallback(IceInternal.ReadyCallback callback)
+ {
+ _transceiver.setReadyCallback(callback);
+ }
+
+ public synchronized void timedOut()
+ {
+ if(_state <= StateNotValidated)
+ {
+ setState(StateClosed, new ConnectTimeoutException());
+ }
+ else if(_state < StateClosing)
+ {
+ setState(StateClosed, new TimeoutException());
+ }
+ else if(_state < StateClosed)
+ {
+ setState(StateClosed, new CloseTimeoutException());
+ }
+ }
+
+ @Override
+ public String type()
+ {
+ return _type; // No mutex lock, _type is immutable.
+ }
+
+ @Override
+ public int timeout()
+ {
+ return _endpoint.timeout(); // No mutex protection necessary, _endpoint
+ // is immutable.
+ }
+
+ @Override
+ public synchronized ConnectionInfo getInfo()
+ {
+ if(_state >= StateClosed)
+ {
+ throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+ return initConnectionInfo();
+ }
+
+ @Override
+ public synchronized void setBufferSize(int rcvSize, int sndSize)
+ {
+ if(_state >= StateClosed)
+ {
+ throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+ _transceiver.setBufferSize(rcvSize, sndSize);
+ _info = null; // Invalidate the cached connection info
+ }
+
+ @Override
+ public String _toString()
+ {
+ return _desc; // No mutex lock, _desc is immutable.
+ }
+
+ public synchronized void exception(LocalException ex)
+ {
+ setState(StateClosed, ex);
+ }
+
+ public ConnectionI(Communicator communicator, IceInternal.Instance instance, IceInternal.ACMMonitor monitor,
+ IceInternal.Transceiver transceiver, IceInternal.Connector connector,
+ IceInternal.EndpointI endpoint, ObjectAdapterI adapter)
+ {
+ _communicator = communicator;
+ _instance = instance;
+ _monitor = monitor;
+ _transceiver = transceiver;
+ _desc = transceiver.toString();
+ _type = transceiver.protocol();
+ _connector = connector;
+ _endpoint = endpoint;
+ _adapter = adapter;
+ final Ice.InitializationData initData = instance.initializationData();
+ // Cached for better performance.
+ _dispatcher = initData.dispatcher != null;
+ _logger = initData.logger; // Cached for better performance.
+ _traceLevels = instance.traceLevels(); // Cached for better performance.
+ _timer = instance.timer();
+ _writeTimeout = new TimeoutCallback();
+ _writeTimeoutFuture = null;
+ _readTimeout = new TimeoutCallback();
+ _readTimeoutFuture = null;
+ _warn = initData.properties.getPropertyAsInt("Ice.Warn.Connections") > 0;
+ _warnUdp = instance.initializationData().properties.getPropertyAsInt("Ice.Warn.Datagrams") > 0;
+ _cacheBuffers = instance.cacheMessageBuffers();
+ if(_monitor != null && _monitor.getACM().timeout > 0)
+ {
+ _acmLastActivity = IceInternal.Time.currentMonotonicTimeMillis();
+ }
+ else
+ {
+ _acmLastActivity = -1;
+ }
+ _nextRequestId = 1;
+ _messageSizeMax = adapter != null ? adapter.messageSizeMax() : instance.messageSizeMax();
+ _batchRequestQueue = new IceInternal.BatchRequestQueue(instance, _endpoint.datagram());
+ _readStream = new InputStream(instance, IceInternal.Protocol.currentProtocolEncoding);
+ _readHeader = false;
+ _readStreamPos = -1;
+ _writeStream = new OutputStream(instance, IceInternal.Protocol.currentProtocolEncoding);
+ _writeStreamPos = -1;
+ _dispatchCount = 0;
+ _state = StateNotInitialized;
+
+ int compressionLevel = initData.properties.getPropertyAsIntWithDefault("Ice.Compression.Level", 1);
+ if(compressionLevel < 1)
+ {
+ compressionLevel = 1;
+ }
+ else if(compressionLevel > 9)
+ {
+ compressionLevel = 9;
+ }
+ _compressionLevel = compressionLevel;
+
+ if(adapter != null)
+ {
+ _servantManager = adapter.getServantManager();
+ }
+ else
+ {
+ _servantManager = null;
+ }
+
+ try
+ {
+ if(adapter != null)
+ {
+ _threadPool = adapter.getThreadPool();
+ }
+ else
+ {
+ _threadPool = _instance.clientThreadPool();
+ }
+ _threadPool.initialize(this);
+ }
+ catch(Ice.LocalException ex)
+ {
+ throw ex;
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new Ice.SyscallException(ex);
+ }
+ }
+
+ @Override
+ protected synchronized void finalize() throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_startCallback == null);
+ IceUtilInternal.Assert.FinalizerAssert(_state == StateFinished);
+ IceUtilInternal.Assert.FinalizerAssert(_dispatchCount == 0);
+ IceUtilInternal.Assert.FinalizerAssert(_sendStreams.isEmpty());
+ IceUtilInternal.Assert.FinalizerAssert(_asyncRequests.isEmpty());
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ private static final int StateNotInitialized = 0;
+ private static final int StateNotValidated = 1;
+ private static final int StateActive = 2;
+ private static final int StateHolding = 3;
+ private static final int StateClosing = 4;
+ private static final int StateClosingPending = 5;
+ private static final int StateClosed = 6;
+ private static final int StateFinished = 7;
+
+ private void setState(int state, LocalException ex)
+ {
+ //
+ // If setState() is called with an exception, then only closed
+ // and closing states are permissible.
+ //
+ assert state >= StateClosing;
+
+ if(_state == state) // Don't switch twice.
+ {
+ return;
+ }
+
+ if(_exception == null)
+ {
+ //
+ // If we are in closed state, an exception must be set.
+ //
+ assert (_state != StateClosed);
+
+ _exception = ex;
+
+ //
+ // We don't warn if we are not validated.
+ //
+ if(_warn && _validated)
+ {
+ //
+ // Don't warn about certain expected exceptions.
+ //
+ if(!(_exception instanceof CloseConnectionException ||
+ _exception instanceof ForcedCloseConnectionException ||
+ _exception instanceof ConnectionTimeoutException ||
+ _exception instanceof CommunicatorDestroyedException ||
+ _exception instanceof ObjectAdapterDeactivatedException ||
+ (_exception instanceof ConnectionLostException && _state >= StateClosing)))
+ {
+ warning("connection exception", _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.
+ //
+ setState(state);
+ }
+
+ private void setState(int state)
+ {
+ //
+ // We don't want to send close connection messages if the endpoint
+ // only supports oneway transmission from client to server.
+ //
+ if(_endpoint.datagram() && state == StateClosing)
+ {
+ state = StateClosed;
+ }
+
+ //
+ // Skip graceful shutdown if we are destroyed before validation.
+ //
+ if(_state <= StateNotValidated && state == StateClosing)
+ {
+ state = StateClosed;
+ }
+
+ if(_state == state) // Don't switch twice.
+ {
+ return;
+ }
+
+ try
+ {
+ switch(state)
+ {
+ case StateNotInitialized:
+ {
+ assert (false);
+ break;
+ }
+
+ case StateNotValidated:
+ {
+ if(_state != StateNotInitialized)
+ {
+ assert (_state == StateClosed);
+ return;
+ }
+ break;
+ }
+
+ case StateActive:
+ {
+ //
+ // Can only switch from holding or not validated to
+ // active.
+ //
+ if(_state != StateHolding && _state != StateNotValidated)
+ {
+ return;
+ }
+ _threadPool.register(this, IceInternal.SocketOperation.Read);
+ break;
+ }
+
+ case StateHolding:
+ {
+ //
+ // Can only switch from active or not validated to
+ // holding.
+ //
+ if(_state != StateActive && _state != StateNotValidated)
+ {
+ return;
+ }
+ if(_state == StateActive)
+ {
+ _threadPool.unregister(this, IceInternal.SocketOperation.Read);
+ }
+ break;
+ }
+
+ case StateClosing:
+ case StateClosingPending:
+ {
+ //
+ // Can't change back from closing pending.
+ //
+ if(_state >= StateClosingPending)
+ {
+ return;
+ }
+ break;
+ }
+
+ case StateClosed:
+ {
+ if(_state == StateFinished)
+ {
+ return;
+ }
+
+ _batchRequestQueue.destroy(_exception);
+
+ //
+ // Don't need to close now for connections so only close the transceiver
+ // if the selector request it.
+ //
+ if(_threadPool.finish(this, false))
+ {
+ _transceiver.close();
+ }
+ break;
+ }
+
+ case StateFinished:
+ {
+ assert (_state == StateClosed);
+ _communicator = null;
+ break;
+ }
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ String s = "unexpected connection exception:\n " + _desc + "\n" + sw.toString();
+ _instance.initializationData().logger.error(s);
+ }
+
+ //
+ // 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(_monitor != null)
+ {
+ if(state == StateActive)
+ {
+ if(_acmLastActivity > 0)
+ {
+ _acmLastActivity = IceInternal.Time.currentMonotonicTimeMillis();
+ }
+ _monitor.add(this);
+ }
+ else if(_state == StateActive)
+ {
+ _monitor.remove(this);
+ }
+ }
+
+ if(_instance.initializationData().observer != null)
+ {
+ Ice.Instrumentation.ConnectionState oldState = toConnectionState(_state);
+ Ice.Instrumentation.ConnectionState newState = toConnectionState(state);
+ if(oldState != newState)
+ {
+ _observer = _instance.initializationData().observer.getConnectionObserver(initConnectionInfo(),
+ _endpoint,
+ newState,
+ _observer);
+ if(_observer != null)
+ {
+ _observer.attach();
+ }
+ else
+ {
+ _writeStreamPos = -1;
+ _readStreamPos = -1;
+ }
+ }
+ if(_observer != null && state == StateClosed && _exception != null)
+ {
+ if(!(_exception instanceof CloseConnectionException ||
+ _exception instanceof ForcedCloseConnectionException ||
+ _exception instanceof ConnectionTimeoutException ||
+ _exception instanceof CommunicatorDestroyedException ||
+ _exception instanceof ObjectAdapterDeactivatedException ||
+ (_exception instanceof ConnectionLostException && _state >= StateClosing)))
+ {
+ _observer.failed(_exception.ice_id());
+ }
+ }
+ }
+ _state = state;
+
+ notifyAll();
+
+ if(_state == StateClosing && _dispatchCount == 0)
+ {
+ try
+ {
+ initiateShutdown();
+ }
+ catch(LocalException ex)
+ {
+ setState(StateClosed, ex);
+ }
+ }
+ }
+
+ private void initiateShutdown()
+ {
+ assert (_state == StateClosing);
+ assert (_dispatchCount == 0);
+
+ if(_shutdownInitiated)
+ {
+ return;
+ }
+ _shutdownInitiated = true;
+
+ if(!_endpoint.datagram())
+ {
+ //
+ // Before we shut down, we send a close connection message.
+ //
+ OutputStream os = new OutputStream(_instance, IceInternal.Protocol.currentProtocolEncoding);
+ os.writeBlob(IceInternal.Protocol.magic);
+ IceInternal.Protocol.currentProtocol.__write(os);
+ IceInternal.Protocol.currentProtocolEncoding.__write(os);
+ os.writeByte(IceInternal.Protocol.closeConnectionMsg);
+ os.writeByte((byte) 0); // compression status: always report 0 for
+ // CloseConnection in Java.
+ os.writeInt(IceInternal.Protocol.headerSize); // Message size.
+
+ if((sendMessage(new OutgoingMessage(os, false, false)) & IceInternal.AsyncStatus.Sent) > 0)
+ {
+ setState(StateClosingPending);
+
+ //
+ // Notify the the transceiver of the graceful connection
+ // closure.
+ //
+ int op = _transceiver.closing(true, _exception);
+ if(op != 0)
+ {
+ scheduleTimeout(op);
+ _threadPool.register(this, op);
+ }
+ }
+ }
+ }
+
+ private void heartbeat()
+ {
+ assert (_state == StateActive);
+
+ if(!_endpoint.datagram())
+ {
+ OutputStream os = new OutputStream(_instance, IceInternal.Protocol.currentProtocolEncoding);
+ os.writeBlob(IceInternal.Protocol.magic);
+ IceInternal.Protocol.currentProtocol.__write(os);
+ IceInternal.Protocol.currentProtocolEncoding.__write(os);
+ os.writeByte(IceInternal.Protocol.validateConnectionMsg);
+ os.writeByte((byte) 0);
+ os.writeInt(IceInternal.Protocol.headerSize); // Message size.
+
+ try
+ {
+ OutgoingMessage message = new OutgoingMessage(os, false, false);
+ sendMessage(message);
+ }
+ catch(Ice.LocalException ex)
+ {
+ setState(StateClosed, ex);
+ assert (_exception != null);
+ }
+ }
+ }
+
+ private boolean initialize(int operation)
+ {
+ int s = _transceiver.initialize(_readStream.getBuffer(), _writeStream.getBuffer());
+ if(s != IceInternal.SocketOperation.None)
+ {
+ scheduleTimeout(s);
+ _threadPool.update(this, operation, s);
+ return false;
+ }
+
+ //
+ // Update the connection description once the transceiver is
+ // initialized.
+ //
+ _desc = _transceiver.toString();
+ _initialized = true;
+ setState(StateNotValidated);
+
+ return true;
+ }
+
+ private boolean validate(int operation)
+ {
+ if(!_endpoint.datagram()) // Datagram connections are always implicitly
+ // validated.
+ {
+ if(_adapter != null) // The server side has the active role for
+ // connection validation.
+ {
+ if(_writeStream.isEmpty())
+ {
+ _writeStream.writeBlob(IceInternal.Protocol.magic);
+ IceInternal.Protocol.currentProtocol.__write(_writeStream);
+ IceInternal.Protocol.currentProtocolEncoding.__write(_writeStream);
+ _writeStream.writeByte(IceInternal.Protocol.validateConnectionMsg);
+ _writeStream.writeByte((byte) 0); // Compression status
+ // (always zero for
+ // validate connection).
+ _writeStream.writeInt(IceInternal.Protocol.headerSize); // Message
+ // size.
+ IceInternal.TraceUtil.traceSend(_writeStream, _logger, _traceLevels);
+ _writeStream.prepareWrite();
+ }
+
+ if(_observer != null)
+ {
+ observerStartWrite(_writeStream.getBuffer());
+ }
+
+ if(_writeStream.pos() != _writeStream.size())
+ {
+ int op = write(_writeStream.getBuffer());
+ if(op != 0)
+ {
+ scheduleTimeout(op);
+ _threadPool.update(this, operation, op);
+ return false;
+ }
+ }
+
+ if(_observer != null)
+ {
+ observerFinishWrite(_writeStream.getBuffer());
+ }
+ }
+ else
+ // The client side has the passive role for connection validation.
+ {
+ if(_readStream.isEmpty())
+ {
+ _readStream.resize(IceInternal.Protocol.headerSize);
+ _readStream.pos(0);
+ }
+
+ if(_observer != null)
+ {
+ observerStartRead(_readStream.getBuffer());
+ }
+
+ if(_readStream.pos() != _readStream.size())
+ {
+ int op = read(_readStream.getBuffer());
+ if(op != 0)
+ {
+ scheduleTimeout(op);
+ _threadPool.update(this, operation, op);
+ return false;
+ }
+ }
+
+ if(_observer != null)
+ {
+ observerFinishRead(_readStream.getBuffer());
+ }
+
+ assert (_readStream.pos() == IceInternal.Protocol.headerSize);
+ _readStream.pos(0);
+ byte[] m = _readStream.readBlob(4);
+ if(m[0] != IceInternal.Protocol.magic[0] || m[1] != IceInternal.Protocol.magic[1] ||
+ m[2] != IceInternal.Protocol.magic[2] || m[3] != IceInternal.Protocol.magic[3])
+ {
+ BadMagicException ex = new BadMagicException();
+ ex.badMagic = m;
+ throw ex;
+ }
+
+ _readProtocol.__read(_readStream);
+ IceInternal.Protocol.checkSupportedProtocol(_readProtocol);
+
+ _readProtocolEncoding.__read(_readStream);
+ IceInternal.Protocol.checkSupportedProtocolEncoding(_readProtocolEncoding);
+
+ byte messageType = _readStream.readByte();
+ if(messageType != IceInternal.Protocol.validateConnectionMsg)
+ {
+ throw new ConnectionNotValidatedException();
+ }
+ _readStream.readByte(); // Ignore compression status for
+ // validate connection.
+ int size = _readStream.readInt();
+ if(size != IceInternal.Protocol.headerSize)
+ {
+ throw new IllegalMessageSizeException();
+ }
+ IceInternal.TraceUtil.traceRecv(_readStream, _logger, _traceLevels);
+
+ _validated = true;
+ }
+ }
+
+ _writeStream.resize(0);
+ _writeStream.pos(0);
+
+ _readStream.resize(IceInternal.Protocol.headerSize);
+ _readStream.pos(0);
+ _readHeader = true;
+
+ if(_instance.traceLevels().network >= 1)
+ {
+ StringBuffer s = new StringBuffer();
+ if(_endpoint.datagram())
+ {
+ s.append("starting to ");
+ s.append(_connector != null ? "send" : "receive");
+ s.append(" ");
+ s.append(_endpoint.protocol());
+ s.append(" messages\n");
+ s.append(_transceiver.toDetailedString());
+ }
+ else
+ {
+ s.append(_connector != null ? "established" : "accepted");
+ s.append(" ");
+ s.append(_endpoint.protocol());
+ s.append(" connection\n");
+ s.append(toString());
+ }
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+
+ return true;
+ }
+
+ private int sendNextMessage(java.util.List<OutgoingMessage> callbacks)
+ {
+ if(_sendStreams.isEmpty())
+ {
+ return IceInternal.SocketOperation.None;
+ }
+ else if(_state == StateClosingPending && _writeStream.pos() == 0)
+ {
+ // Message wasn't sent, empty the _writeStream, we're not going to
+ // send more data.
+ OutgoingMessage message = _sendStreams.getFirst();
+ _writeStream.swap(message.stream);
+ return IceInternal.SocketOperation.None;
+ }
+
+ assert (!_writeStream.isEmpty() && _writeStream.pos() == _writeStream.size());
+ try
+ {
+ while(true)
+ {
+ //
+ // Notify the message that it was sent.
+ //
+ OutgoingMessage message = _sendStreams.getFirst();
+ _writeStream.swap(message.stream);
+ if(message.sent())
+ {
+ callbacks.add(message);
+ }
+ _sendStreams.removeFirst();
+
+ //
+ // If there's nothing left to send, we're done.
+ //
+ if(_sendStreams.isEmpty())
+ {
+ break;
+ }
+
+ //
+ // If we are in the closed state or if the close is
+ // pending, don't continue sending.
+ //
+ // This can occur if parseMessage (called before
+ // sendNextMessage by message()) closes the connection.
+ //
+ if(_state >= StateClosingPending)
+ {
+ return IceInternal.SocketOperation.None;
+ }
+
+ //
+ // Otherwise, prepare the next message stream for writing.
+ //
+ message = _sendStreams.getFirst();
+ assert (!message.prepared);
+ OutputStream stream = message.stream;
+
+ message.stream = doCompress(stream, message.compress);
+ message.stream.prepareWrite();
+ message.prepared = true;
+
+ IceInternal.TraceUtil.traceSend(stream, _logger, _traceLevels);
+
+ _writeStream.swap(message.stream);
+
+ //
+ // Send the message.
+ //
+ if(_observer != null)
+ {
+ observerStartWrite(_writeStream.getBuffer());
+ }
+ if(_writeStream.pos() != _writeStream.size())
+ {
+ int op = write(_writeStream.getBuffer());
+ if(op != 0)
+ {
+ return op;
+ }
+ }
+ if(_observer != null)
+ {
+ observerFinishWrite(_writeStream.getBuffer());
+ }
+ }
+
+ //
+ // 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(_state == StateClosing && _shutdownInitiated)
+ {
+ setState(StateClosingPending);
+ int op = _transceiver.closing(true, _exception);
+ if(op != 0)
+ {
+ return op;
+ }
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ setState(StateClosed, ex);
+ }
+ return IceInternal.SocketOperation.None;
+ }
+
+ private int sendMessage(OutgoingMessage message)
+ {
+ assert (_state < StateClosed);
+
+ if(!_sendStreams.isEmpty())
+ {
+ message.adopt();
+ _sendStreams.addLast(message);
+ return IceInternal.AsyncStatus.Queued;
+ }
+
+ //
+ // Attempt to send the message without blocking. If the send blocks, we
+ // register the connection with the selector thread.
+ //
+
+ assert (!message.prepared);
+
+ OutputStream stream = message.stream;
+
+ message.stream = doCompress(stream, message.compress);
+ message.stream.prepareWrite();
+ message.prepared = true;
+ int op;
+
+ IceInternal.TraceUtil.traceSend(stream, _logger, _traceLevels);
+
+ //
+ // Send the message without blocking.
+ //
+ if(_observer != null)
+ {
+ observerStartWrite(message.stream.getBuffer());
+ }
+ op = write(message.stream.getBuffer());
+ if(op == 0)
+ {
+ if(_observer != null)
+ {
+ observerFinishWrite(message.stream.getBuffer());
+ }
+
+ int status = IceInternal.AsyncStatus.Sent;
+ if(message.sent())
+ {
+ status |= IceInternal.AsyncStatus.InvokeSentCallback;
+ }
+
+ if(_acmLastActivity > 0)
+ {
+ _acmLastActivity = IceInternal.Time.currentMonotonicTimeMillis();
+ }
+ return status;
+ }
+
+ message.adopt();
+
+ _writeStream.swap(message.stream);
+ _sendStreams.addLast(message);
+ scheduleTimeout(op);
+ _threadPool.register(this, op);
+ return IceInternal.AsyncStatus.Queued;
+ }
+
+ private OutputStream doCompress(OutputStream uncompressed, boolean compress)
+ {
+ boolean compressionSupported = false;
+ if(compress)
+ {
+ //
+ // Don't check whether compression support is available unless the
+ // proxy is configured for compression.
+ //
+ compressionSupported = IceInternal.BZip2.supported();
+ }
+
+ if(compressionSupported && uncompressed.size() >= 100)
+ {
+ //
+ // Do compression.
+ //
+ IceInternal.Buffer cbuf = IceInternal.BZip2.compress(uncompressed.getBuffer(),
+ IceInternal.Protocol.headerSize, _compressionLevel);
+ if(cbuf != null)
+ {
+ OutputStream cstream =
+ new OutputStream(uncompressed.instance(), uncompressed.getEncoding(), cbuf, true);
+
+ //
+ // Set compression status.
+ //
+ cstream.pos(9);
+ cstream.writeByte((byte) 2);
+
+ //
+ // Write the size of the compressed stream into the header.
+ //
+ cstream.pos(10);
+ cstream.writeInt(cstream.size());
+
+ //
+ // Write the compression status and size of the compressed
+ // stream into the header of the uncompressed stream -- we need
+ // this to trace requests correctly.
+ //
+ uncompressed.pos(9);
+ uncompressed.writeByte((byte) 2);
+ uncompressed.writeInt(cstream.size());
+
+ return cstream;
+ }
+ }
+
+ uncompressed.pos(9);
+ uncompressed.writeByte((byte) (compressionSupported ? 1 : 0));
+
+ //
+ // Not compressed, fill in the message size.
+ //
+ uncompressed.pos(10);
+ uncompressed.writeInt(uncompressed.size());
+
+ return uncompressed;
+ }
+
+ private static class MessageInfo
+ {
+ MessageInfo(InputStream stream)
+ {
+ this.stream = stream;
+ }
+
+ InputStream stream;
+ int invokeNum;
+ int requestId;
+ byte compress;
+ IceInternal.ServantManager servantManager;
+ ObjectAdapter adapter;
+ IceInternal.OutgoingAsyncBase outAsync;
+ HeartbeatCallback heartbeatCallback;
+ int messageDispatchCount;
+ }
+
+ private int parseMessage(MessageInfo info)
+ {
+ assert (_state > StateNotValidated && _state < StateClosed);
+
+ _readStream.swap(info.stream);
+ _readStream.resize(IceInternal.Protocol.headerSize);
+ _readStream.pos(0);
+ _readHeader = true;
+
+ assert (info.stream.pos() == info.stream.size());
+
+ //
+ // 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).
+ //
+ _validated = true;
+
+ try
+ {
+ //
+ // We don't need to check magic and version here. This has already
+ // been done by the ThreadPool which provides us with the stream.
+ //
+ info.stream.pos(8);
+ byte messageType = info.stream.readByte();
+ info.compress = info.stream.readByte();
+ if(info.compress == (byte)2)
+ {
+ if(IceInternal.BZip2.supported())
+ {
+ IceInternal.Buffer ubuf = IceInternal.BZip2.uncompress(info.stream.getBuffer(),
+ IceInternal.Protocol.headerSize,
+ _messageSizeMax);
+ info.stream = new InputStream(info.stream.instance(), info.stream.getEncoding(), ubuf, true);
+ }
+ else
+ {
+ FeatureNotSupportedException ex = new FeatureNotSupportedException();
+ ex.unsupportedFeature = "Cannot uncompress compressed message: "
+ + "org.apache.tools.bzip2.CBZip2OutputStream was not found";
+ throw ex;
+ }
+ }
+ info.stream.pos(IceInternal.Protocol.headerSize);
+
+ switch(messageType)
+ {
+ case IceInternal.Protocol.closeConnectionMsg:
+ {
+ IceInternal.TraceUtil.traceRecv(info.stream, _logger, _traceLevels);
+ if(_endpoint.datagram())
+ {
+ if(_warn)
+ {
+ _logger.warning("ignoring close connection message for datagram connection:\n" + _desc);
+ }
+ }
+ else
+ {
+ setState(StateClosingPending, new CloseConnectionException());
+
+ //
+ // Notify the the transceiver of the graceful connection
+ // closure.
+ //
+ int op = _transceiver.closing(false, _exception);
+ if(op != 0)
+ {
+ return op;
+ }
+ setState(StateClosed);
+ }
+ break;
+ }
+
+ case IceInternal.Protocol.requestMsg:
+ {
+ if(_state >= StateClosing)
+ {
+ IceInternal.TraceUtil.trace("received request during closing\n"
+ + "(ignored by server, client will retry)", info.stream, _logger,
+ _traceLevels);
+ }
+ else
+ {
+ IceInternal.TraceUtil.traceRecv(info.stream, _logger, _traceLevels);
+ info.requestId = info.stream.readInt();
+ info.invokeNum = 1;
+ info.servantManager = _servantManager;
+ info.adapter = _adapter;
+ ++info.messageDispatchCount;
+ }
+ break;
+ }
+
+ case IceInternal.Protocol.requestBatchMsg:
+ {
+ if(_state >= StateClosing)
+ {
+ IceInternal.TraceUtil.trace("received batch request during closing\n"
+ + "(ignored by server, client will retry)", info.stream, _logger,
+ _traceLevels);
+ }
+ else
+ {
+ IceInternal.TraceUtil.traceRecv(info.stream, _logger, _traceLevels);
+ info.invokeNum = info.stream.readInt();
+ if(info.invokeNum < 0)
+ {
+ info.invokeNum = 0;
+ throw new UnmarshalOutOfBoundsException();
+ }
+ info.servantManager = _servantManager;
+ info.adapter = _adapter;
+ info.messageDispatchCount += info.invokeNum;
+ }
+ break;
+ }
+
+ case IceInternal.Protocol.replyMsg:
+ {
+ IceInternal.TraceUtil.traceRecv(info.stream, _logger, _traceLevels);
+ info.requestId = info.stream.readInt();
+
+ IceInternal.OutgoingAsyncBase outAsync = _asyncRequests.remove(info.requestId);
+ if(outAsync != null && outAsync.completed(info.stream))
+ {
+ info.outAsync = outAsync;
+ ++info.messageDispatchCount;
+ }
+ notifyAll(); // Notify threads blocked in close(false)
+ break;
+ }
+
+ case IceInternal.Protocol.validateConnectionMsg:
+ {
+ IceInternal.TraceUtil.traceRecv(info.stream, _logger, _traceLevels);
+ if(_heartbeatCallback != null)
+ {
+ info.heartbeatCallback = _heartbeatCallback;
+ ++info.messageDispatchCount;
+ }
+ break;
+ }
+
+ default:
+ {
+ IceInternal.TraceUtil.trace("received unknown message\n(invalid, closing connection)", info.stream,
+ _logger, _traceLevels);
+ throw new UnknownMessageException();
+ }
+ }
+ }
+ catch(LocalException ex)
+ {
+ if(_endpoint.datagram())
+ {
+ if(_warn)
+ {
+ _logger.warning("datagram connection exception:\n" + ex + '\n' + _desc);
+ }
+ }
+ else
+ {
+ setState(StateClosed, ex);
+ }
+ }
+
+ return _state == StateHolding ? IceInternal.SocketOperation.None : IceInternal.SocketOperation.Read;
+ }
+
+ private void invokeAll(InputStream stream, int invokeNum, int requestId, byte compress,
+ IceInternal.ServantManager servantManager, ObjectAdapter adapter)
+ {
+ //
+ // Note: In contrast to other private or protected methods, this
+ // operation must be called *without* the mutex locked.
+ //
+
+ IceInternal.Incoming in = null;
+ try
+ {
+ while(invokeNum > 0)
+ {
+
+ //
+ // Prepare the invocation.
+ //
+ boolean response = !_endpoint.datagram() && requestId != 0;
+ in = getIncoming(adapter, response, compress, requestId);
+
+ //
+ // Dispatch the invocation.
+ //
+ in.invoke(servantManager, stream);
+
+ --invokeNum;
+
+ reclaimIncoming(in);
+ in = null;
+ }
+
+ stream.clear();
+ }
+ catch(LocalException ex)
+ {
+ invokeException(requestId, ex, invokeNum, false);
+ }
+ catch(IceInternal.ServantError ex)
+ {
+ //
+ // ServantError is thrown when an Error has been raised by servant (or servant locator)
+ // code. We've already attempted to complete the invocation and send a response.
+ //
+ Throwable t = ex.getCause();
+ //
+ // Suppress AssertionError and OutOfMemoryError, rethrow everything else.
+ //
+ if(!(t instanceof java.lang.AssertionError || t instanceof java.lang.OutOfMemoryError))
+ {
+ throw (java.lang.Error)t;
+ }
+ }
+ catch(java.lang.Error ex)
+ {
+ //
+ // An Error was raised outside of servant code (i.e., by Ice code).
+ // Attempt to log the error and clean up. This may still fail
+ // depending on the severity of the error.
+ //
+ // Note that this does NOT send a response to the client.
+ //
+ UnknownException uex = new UnknownException(ex);
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ uex.unknown = sw.toString();
+ _logger.error(uex.unknown);
+ invokeException(requestId, uex, invokeNum, false);
+ //
+ // Suppress AssertionError and OutOfMemoryError, rethrow everything else.
+ //
+ if(!(ex instanceof java.lang.AssertionError || ex instanceof java.lang.OutOfMemoryError))
+ {
+ throw ex;
+ }
+ }
+ finally
+ {
+ if(in != null)
+ {
+ reclaimIncoming(in);
+ }
+ }
+ }
+
+ private void scheduleTimeout(int status)
+ {
+ int timeout;
+ if(_state < StateActive)
+ {
+ IceInternal.DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideConnectTimeout)
+ {
+ timeout = defaultsAndOverrides.overrideConnectTimeoutValue;
+ }
+ else
+ {
+ timeout = _endpoint.timeout();
+ }
+ }
+ else if(_state < StateClosingPending)
+ {
+ if(_readHeader) // No timeout for reading the header.
+ {
+ status &= ~IceInternal.SocketOperation.Read;
+ }
+ timeout = _endpoint.timeout();
+ }
+ else
+ {
+ IceInternal.DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideCloseTimeout)
+ {
+ timeout = defaultsAndOverrides.overrideCloseTimeoutValue;
+ }
+ else
+ {
+ timeout = _endpoint.timeout();
+ }
+ }
+
+ if(timeout < 0)
+ {
+ return;
+ }
+
+ try
+ {
+ if((status & IceInternal.SocketOperation.Read) != 0)
+ {
+ if(_readTimeoutFuture != null)
+ {
+ _readTimeoutFuture.cancel(false);
+ }
+ _readTimeoutFuture = _timer.schedule(_readTimeout, timeout, java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+ if((status & (IceInternal.SocketOperation.Write | IceInternal.SocketOperation.Connect)) != 0)
+ {
+ if(_writeTimeoutFuture != null)
+ {
+ _writeTimeoutFuture.cancel(false);
+ }
+ _writeTimeoutFuture = _timer.schedule(_writeTimeout, timeout,
+ java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+ }
+ catch(Throwable ex)
+ {
+ assert (false);
+ }
+ }
+
+ private void unscheduleTimeout(int status)
+ {
+ if((status & IceInternal.SocketOperation.Read) != 0 && _readTimeoutFuture != null)
+ {
+ _readTimeoutFuture.cancel(false);
+ _readTimeoutFuture = null;
+ }
+ if((status & (IceInternal.SocketOperation.Write | IceInternal.SocketOperation.Connect)) != 0 &&
+ _writeTimeoutFuture != null)
+ {
+ _writeTimeoutFuture.cancel(false);
+ _writeTimeoutFuture = null;
+ }
+ }
+
+ private ConnectionInfo initConnectionInfo()
+ {
+ if(_state > StateNotInitialized && _info != null) // Update the connection information until it's initialized
+ {
+ return _info;
+ }
+
+ try
+ {
+ _info = _transceiver.getInfo();
+ }
+ catch(Ice.LocalException ex)
+ {
+ _info = new ConnectionInfo();
+ }
+ for(ConnectionInfo info = _info; info != null; info = info.underlying)
+ {
+ info.connectionId = _endpoint.connectionId();
+ info.adapterName = _adapter != null ? _adapter.getName() : "";
+ info.incoming = _connector == null;
+ }
+ return _info;
+ }
+
+ private Ice.Instrumentation.ConnectionState toConnectionState(int state)
+ {
+ return connectionStateMap[state];
+ }
+
+ private void warning(String msg, java.lang.Exception ex)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ String s = msg + ":\n" + _desc + "\n" + sw.toString();
+ _logger.warning(s);
+ }
+
+ private void observerStartRead(IceInternal.Buffer buf)
+ {
+ if(_readStreamPos >= 0)
+ {
+ assert (!buf.empty());
+ _observer.receivedBytes(buf.b.position() - _readStreamPos);
+ }
+ _readStreamPos = buf.empty() ? -1 : buf.b.position();
+ }
+
+ private void observerFinishRead(IceInternal.Buffer buf)
+ {
+ if(_readStreamPos == -1)
+ {
+ return;
+ }
+ assert (buf.b.position() >= _readStreamPos);
+ _observer.receivedBytes(buf.b.position() - _readStreamPos);
+ _readStreamPos = -1;
+ }
+
+ private void observerStartWrite(IceInternal.Buffer buf)
+ {
+ if(_writeStreamPos >= 0)
+ {
+ assert (!buf.empty());
+ _observer.sentBytes(buf.b.position() - _writeStreamPos);
+ }
+ _writeStreamPos = buf.empty() ? -1 : buf.b.position();
+ }
+
+ private void observerFinishWrite(IceInternal.Buffer buf)
+ {
+ if(_writeStreamPos == -1)
+ {
+ return;
+ }
+ if(buf.b.position() > _writeStreamPos)
+ {
+ _observer.sentBytes(buf.b.position() - _writeStreamPos);
+ }
+ _writeStreamPos = -1;
+ }
+
+ private IceInternal.Incoming getIncoming(ObjectAdapter adapter, boolean response, byte compress, int requestId)
+ {
+ IceInternal.Incoming in = null;
+
+ if(_cacheBuffers > 0)
+ {
+ synchronized(_incomingCacheMutex)
+ {
+ if(_incomingCache == null)
+ {
+ in = new IceInternal.Incoming(_instance, this, this, adapter, response, compress, requestId);
+ }
+ else
+ {
+ in = _incomingCache;
+ _incomingCache = _incomingCache.next;
+ in.reset(_instance, this, this, adapter, response, compress, requestId);
+ in.next = null;
+ }
+ }
+ }
+ else
+ {
+ in = new IceInternal.Incoming(_instance, this, this, adapter, response, compress, requestId);
+ }
+
+ return in;
+ }
+
+ private void reclaimIncoming(IceInternal.Incoming in)
+ {
+ if(_cacheBuffers > 0)
+ {
+ synchronized(_incomingCacheMutex)
+ {
+ in.next = _incomingCache;
+ _incomingCache = in;
+ //
+ // Clear references to Ice objects as soon as possible.
+ //
+ _incomingCache.reclaim();
+ }
+ }
+ }
+
+ private void reap()
+ {
+ if(_monitor != null)
+ {
+ _monitor.reap(this);
+ }
+ if(_observer != null)
+ {
+ _observer.detach();
+ }
+ }
+
+ private int read(IceInternal.Buffer buf)
+ {
+ int start = buf.b.position();
+ int op = _transceiver.read(buf);
+ if(_instance.traceLevels().network >= 3 && buf.b.position() != start)
+ {
+ StringBuffer s = new StringBuffer("received ");
+ if(_endpoint.datagram())
+ {
+ s.append(buf.b.limit());
+ }
+ else
+ {
+ s.append(buf.b.position() - start);
+ s.append(" of ");
+ s.append(buf.b.limit() - start);
+ }
+ s.append(" bytes via ");
+ s.append(_endpoint.protocol());
+ s.append("\n");
+ s.append(toString());
+
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+ return op;
+ }
+
+ private int write(IceInternal.Buffer buf)
+ {
+ int start = buf.b.position();
+ int op = _transceiver.write(buf);
+ if(_instance.traceLevels().network >= 3 && buf.b.position() != start)
+ {
+ StringBuffer s = new StringBuffer("sent ");
+ s.append(buf.b.position() - start);
+ if(!_endpoint.datagram())
+ {
+ s.append(" of ");
+ s.append(buf.b.limit() - start);
+ }
+ s.append(" bytes via ");
+ s.append(_endpoint.protocol());
+ s.append("\n");
+ s.append(toString());
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+ return op;
+ }
+
+ private static class OutgoingMessage
+ {
+ OutgoingMessage(OutputStream stream, boolean compress, boolean adopt)
+ {
+ this.stream = stream;
+ this.compress = compress;
+ this.adopt = adopt;
+ this.requestId = 0;
+ }
+
+ OutgoingMessage(IceInternal.OutgoingAsyncBase out, OutputStream stream, boolean compress,
+ int requestId)
+ {
+ this.stream = stream;
+ this.compress = compress;
+ this.outAsync = out;
+ this.requestId = requestId;
+ }
+
+ public void canceled()
+ {
+ assert (outAsync != null);
+ outAsync = null;
+ }
+
+ public void adopt()
+ {
+ if(adopt)
+ {
+ OutputStream stream =
+ new OutputStream(this.stream.instance(), IceInternal.Protocol.currentProtocolEncoding);
+ stream.swap(this.stream);
+ this.stream = stream;
+ adopt = false;
+ }
+ }
+
+ public boolean sent()
+ {
+ if(outAsync != null)
+ {
+ return outAsync.sent();
+ }
+ return false;
+ }
+
+ public void completed(Ice.LocalException ex)
+ {
+ if(outAsync != null && outAsync.completed(ex))
+ {
+ outAsync.invokeCompleted();
+ }
+ }
+
+ public OutputStream stream;
+ public IceInternal.OutgoingAsyncBase outAsync;
+ public boolean compress;
+ public int requestId;
+ boolean adopt;
+ boolean prepared;
+ }
+
+ private Communicator _communicator;
+ private final IceInternal.Instance _instance;
+ private IceInternal.ACMMonitor _monitor;
+ private final IceInternal.Transceiver _transceiver;
+ private String _desc;
+ private final String _type;
+ private final IceInternal.Connector _connector;
+ private final IceInternal.EndpointI _endpoint;
+
+ private ObjectAdapter _adapter;
+ private IceInternal.ServantManager _servantManager;
+
+ private final boolean _dispatcher;
+ private final Logger _logger;
+ private final IceInternal.TraceLevels _traceLevels;
+ private final IceInternal.ThreadPool _threadPool;
+
+ private final java.util.concurrent.ScheduledExecutorService _timer;
+ private final Runnable _writeTimeout;
+ private java.util.concurrent.Future<?> _writeTimeoutFuture;
+ private final Runnable _readTimeout;
+ private java.util.concurrent.Future<?> _readTimeoutFuture;
+
+ private StartCallback _startCallback = null;
+
+ private final boolean _warn;
+ private final boolean _warnUdp;
+
+ private long _acmLastActivity;
+
+ private final int _compressionLevel;
+
+ private int _nextRequestId;
+
+ private java.util.Map<Integer, IceInternal.OutgoingAsyncBase> _asyncRequests =
+ new java.util.HashMap<Integer, IceInternal.OutgoingAsyncBase>();
+
+ private LocalException _exception;
+
+ private final int _messageSizeMax;
+ private IceInternal.BatchRequestQueue _batchRequestQueue;
+
+ private java.util.LinkedList<OutgoingMessage> _sendStreams = new java.util.LinkedList<OutgoingMessage>();
+
+ private InputStream _readStream;
+ private boolean _readHeader;
+ private OutputStream _writeStream;
+
+ private Ice.Instrumentation.ConnectionObserver _observer;
+ private int _readStreamPos;
+ private int _writeStreamPos;
+
+ private int _dispatchCount;
+
+ private int _state; // The current state.
+ private boolean _shutdownInitiated = false;
+ private boolean _initialized = false;
+ private boolean _validated = false;
+
+ private IceInternal.Incoming _incomingCache;
+ private final java.lang.Object _incomingCacheMutex = new java.lang.Object();
+
+ private Ice.ProtocolVersion _readProtocol = new Ice.ProtocolVersion();
+ private Ice.EncodingVersion _readProtocolEncoding = new Ice.EncodingVersion();
+
+ private int _cacheBuffers;
+
+ private Ice.ConnectionInfo _info;
+
+ private CloseCallback _closeCallback;
+ private HeartbeatCallback _heartbeatCallback;
+
+ private static Ice.Instrumentation.ConnectionState connectionStateMap[] = {
+ Ice.Instrumentation.ConnectionState.ConnectionStateValidating, // StateNotInitialized
+ Ice.Instrumentation.ConnectionState.ConnectionStateValidating, // StateNotValidated
+ Ice.Instrumentation.ConnectionState.ConnectionStateActive, // StateActive
+ Ice.Instrumentation.ConnectionState.ConnectionStateHolding, // StateHolding
+ Ice.Instrumentation.ConnectionState.ConnectionStateClosing, // StateClosing
+ Ice.Instrumentation.ConnectionState.ConnectionStateClosing, // StateClosingPending
+ Ice.Instrumentation.ConnectionState.ConnectionStateClosed, // StateClosed
+ Ice.Instrumentation.ConnectionState.ConnectionStateClosed, // StateFinished
+ };
+
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/DispatchInterceptor.java b/java-compat/src/Ice/src/main/java/Ice/DispatchInterceptor.java
new file mode 100644
index 00000000000..d5cb1519f58
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/DispatchInterceptor.java
@@ -0,0 +1,71 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class that allows a server intercept incoming requests.
+ * The application must derive a concrete class from <code>DispatchInterceptor</code>
+ * that implements the {@link DispatchInterceptor#dispatch} operation. An instance of this derived
+ * class can be registered with an object adapter like any other servant.
+ * <p>
+ * A dispatch interceptor is useful particularly to automatically retry requests
+ * that have failed due to a recoverable error condition.
+ **/
+public abstract class DispatchInterceptor extends ObjectImpl
+{
+ /**
+ * Called by the Ice run time to dispatch an incoming request. The implementation
+ * of <code>dispatch</code> must dispatch the request to the actual servant.
+ *
+ * @param request The details of the incoming request.
+ * @return For synchronous dispatch, the return value must be whatever is
+ * returned {@link #ice_dispatch}. For asynchronous dispatch, the return
+ * value must be <code>DispatchAsync</code>.
+ *
+ * @see Request
+ * @see DispatchStatus
+ **/
+ public abstract DispatchStatus
+ dispatch(Request request);
+
+ @Override
+ public DispatchStatus
+ __dispatch(IceInternal.Incoming in, Current current)
+ {
+ try
+ {
+ DispatchStatus status = dispatch(in);
+ if(status != DispatchStatus.DispatchAsync)
+ {
+ //
+ // Make sure 'in' owns the connection etc.
+ //
+ in.killAsync();
+ }
+ return status;
+ }
+ catch(ResponseSentException e)
+ {
+ return DispatchStatus.DispatchAsync;
+ }
+ catch(java.lang.RuntimeException e)
+ {
+ try
+ {
+ in.killAsync();
+ throw e;
+ }
+ catch(ResponseSentException rse)
+ {
+ return DispatchStatus.DispatchAsync;
+ }
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/DispatchInterceptorAsyncCallback.java b/java-compat/src/Ice/src/main/java/Ice/DispatchInterceptorAsyncCallback.java
new file mode 100644
index 00000000000..fdbf42ebe06
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/DispatchInterceptorAsyncCallback.java
@@ -0,0 +1,35 @@
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * The callback object for asynchronous dispatch.
+ **/
+public interface DispatchInterceptorAsyncCallback
+{
+ /**
+ * Called when the operation succeeded or raised a user exception,
+ * as indicated by the <code>ok</code> parameter.
+ *
+ * @param ok True if the operation succeeded, or false if the
+ * operation raised a user exception.
+ * @return True to allow the Ice run time to handle the result
+ * as it normally would, or false if the interceptor has handled
+ * the operation.
+ **/
+ boolean response(boolean ok);
+
+ /**
+ * Called when the operation failed with a run-time exception.
+ *
+ * @param ex The exception raised by the operation.
+ * @return True to allow the Ice run time to handle the result
+ * as it normally would, or false if the interceptor has handled
+ * the operation.
+ **/
+ boolean exception(java.lang.Exception ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/DispatchStatus.java b/java-compat/src/Ice/src/main/java/Ice/DispatchStatus.java
new file mode 100644
index 00000000000..beb91152d03
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/DispatchStatus.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Indicates the status of operation dispatch.
+ *
+ * @see DispatchInterceptor
+ **/
+public enum DispatchStatus implements java.io.Serializable
+{
+ /**
+ * Indicates that an operation was dispatched synchronously and successfully.
+ **/
+ DispatchOK,
+
+ /**
+ * Indicates that an operation was dispatched synchronously and raised a user exception.
+ **/
+ DispatchUserException,
+
+ /**
+ * Indicates that an operation was dispatched asynchronously.
+ **/
+ DispatchAsync;
+
+ public static final long serialVersionUID = 0L;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Dispatcher.java b/java-compat/src/Ice/src/main/java/Ice/Dispatcher.java
new file mode 100644
index 00000000000..83975f9b8c9
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Dispatcher.java
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * You can control which thread receives operation invocations and AMI
+ * callbacks by implementing the <code>Dispatcher</code> interface and
+ * supplying an instance in <code>InitializationData</code> when
+ * initializing a communicator.
+ * <p>
+ * For example, you can use this dispatching facility to ensure that
+ * all invocations and callbacks are dispatched in a GUI event loop
+ * thread so that it is safe to invoke directly on GUI objects.
+ **/
+public interface Dispatcher
+{
+ /**
+ * Responsible for dispatching an invocation or AMI callback.
+ * The method must eventually invoke <code>run</code> on the
+ * supplied <code>Runnable</code> object.
+ *
+ * @param runnable The object encapsulating the invocation or
+ * callback to be dispatched.
+ * @param con The connection associated with the dispatch.
+ **/
+ void dispatch(Runnable runnable, Ice.Connection con);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/DoubleHolder.java b/java-compat/src/Ice/src/main/java/Ice/DoubleHolder.java
new file mode 100644
index 00000000000..db51782dc22
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/DoubleHolder.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for doubles that are out- or inout-parameters.
+ **/
+public final class DoubleHolder extends Holder<Double>
+{
+ /**
+ * Instantiates the class with the value zero.
+ **/
+ public
+ DoubleHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed value.
+ *
+ * @param value The <code>double</code> value stored by this holder.
+ **/
+ public
+ DoubleHolder(double value)
+ {
+ super(value);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/DoubleOptional.java b/java-compat/src/Ice/src/main/java/Ice/DoubleOptional.java
new file mode 100644
index 00000000000..7efd476babd
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/DoubleOptional.java
@@ -0,0 +1,106 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Manages an optional double parameter.
+ **/
+public class DoubleOptional
+{
+ /**
+ * The value defaults to unset.
+ **/
+ public DoubleOptional()
+ {
+ _isSet = false;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The initial value.
+ **/
+ public DoubleOptional(double v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * Sets the value to a shallow copy of the given optional.
+ *
+ * @param opt The source value.
+ **/
+ public DoubleOptional(DoubleOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Obtains the current value.
+ *
+ * @return The current value.
+ * @throws IllegalStateException If the value is not set.
+ **/
+ public double get()
+ {
+ if(!_isSet)
+ {
+ throw new IllegalStateException("no value is set");
+ }
+ return _value;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The new value.
+ **/
+ public void set(double v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * If the given argument is set, this optional is set to a shallow copy of the argument,
+ * otherwise this optional is unset.
+ *
+ * @param opt The source value.
+ **/
+ public void set(DoubleOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Determines whether the value is set.
+ *
+ * @return True if the value is set, false otherwise.
+ **/
+ public boolean isSet()
+ {
+ return _isSet;
+ }
+
+ /**
+ * Unsets this value.
+ **/
+ public void clear()
+ {
+ _isSet = false;
+ _value = 0;
+ }
+
+ private double _value;
+ private boolean _isSet;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Exception.java b/java-compat/src/Ice/src/main/java/Ice/Exception.java
new file mode 100644
index 00000000000..2cd7cd585c1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Exception.java
@@ -0,0 +1,91 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class for Ice local and system exceptions. Those exceptions
+ * are not checked so we inherit from java.lang.RuntimeException. User
+ * exceptions are checked exceptions and therefore inherit directly
+ * from java.lang.Exception.
+ **/
+public abstract class Exception extends RuntimeException implements Cloneable
+{
+ public Exception()
+ {
+ }
+
+ public Exception(Throwable cause)
+ {
+ super(cause);
+ }
+
+ /**
+ * Creates a copy of this exception.
+ *
+ * @return The copy of this exception.
+ **/
+ @Override
+ public Exception clone()
+ {
+ Exception c = null;
+
+ try
+ {
+ c = (Exception)super.clone();
+ }
+ catch(CloneNotSupportedException ex)
+ {
+ assert false;
+ }
+ return c;
+ }
+
+ /**
+ * Returns the name of this exception.
+ *
+ * @return The name of this exception.
+ *
+ * @deprecated ice_name() is deprecated, use ice_id() instead.
+ **/
+ @Deprecated
+ public String
+ ice_name()
+ {
+ return ice_id().substring(2);
+ }
+
+ /**
+ * Returns the type id of this exception.
+ *
+ * @return The type id of this exception.
+ **/
+ public abstract String
+ ice_id();
+
+ /**
+ * Returns a string representation of this exception.
+ *
+ * @return A string representation of this exception.
+ **/
+ @Override
+ public String
+ toString()
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ IceUtilInternal.OutputBase out = new IceUtilInternal.OutputBase(pw);
+ out.setUseTab(false);
+ out.print(getClass().getName());
+ out.inc();
+ IceInternal.ValueWriter.write(this, out);
+ pw.flush();
+ return sw.toString();
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/FloatHolder.java b/java-compat/src/Ice/src/main/java/Ice/FloatHolder.java
new file mode 100644
index 00000000000..4abd74438e5
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/FloatHolder.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for floats that are out- or inout-parameters.
+ **/
+public final class FloatHolder extends Holder<Float>
+{
+ /**
+ * Instantiates the class with the value zero.
+ **/
+ public
+ FloatHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed value.
+ *
+ * @param value The <code>float</code> value stored by this holder.
+ **/
+ public
+ FloatHolder(float value)
+ {
+ super(value);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/FloatOptional.java b/java-compat/src/Ice/src/main/java/Ice/FloatOptional.java
new file mode 100644
index 00000000000..92f67c32071
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/FloatOptional.java
@@ -0,0 +1,106 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Manages an optional float parameter.
+ **/
+public class FloatOptional
+{
+ /**
+ * The value defaults to unset.
+ **/
+ public FloatOptional()
+ {
+ _isSet = false;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The initial value.
+ **/
+ public FloatOptional(float v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * Sets the value to a shallow copy of the given optional.
+ *
+ * @param opt The source value.
+ **/
+ public FloatOptional(FloatOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Obtains the current value.
+ *
+ * @return The current value.
+ * @throws IllegalStateException If the value is not set.
+ **/
+ public float get()
+ {
+ if(!_isSet)
+ {
+ throw new IllegalStateException("no value is set");
+ }
+ return _value;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The new value.
+ **/
+ public void set(float v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * If the given argument is set, this optional is set to a shallow copy of the argument,
+ * otherwise this optional is unset.
+ *
+ * @param opt The source value.
+ **/
+ public void set(FloatOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Determines whether the value is set.
+ *
+ * @return True if the value is set, false otherwise.
+ **/
+ public boolean isSet()
+ {
+ return _isSet;
+ }
+
+ /**
+ * Unsets this value.
+ **/
+ public void clear()
+ {
+ _isSet = false;
+ _value = 0;
+ }
+
+ private float _value;
+ private boolean _isSet;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/FormatType.java b/java-compat/src/Ice/src/main/java/Ice/FormatType.java
new file mode 100644
index 00000000000..7d421f259fd
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/FormatType.java
@@ -0,0 +1,29 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * This enumeration describes the possible formats for classes and exceptions.
+ **/
+public enum FormatType
+{
+ /**
+ * Indicates that no preference was specified.
+ **/
+ DefaultFormat,
+ /**
+ * A minimal format that eliminates the possibility for slicing unrecognized types.
+ **/
+ CompactFormat,
+ /**
+ * Allow slicing and preserve slices for unknown types.
+ **/
+ SlicedFormat
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Holder.java b/java-compat/src/Ice/src/main/java/Ice/Holder.java
new file mode 100644
index 00000000000..bc086b1683b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Holder.java
@@ -0,0 +1,40 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Generic holder class for values that are in- or in-out parameters.
+ **/
+public class Holder<T>
+{
+ /**
+ * Instantiates the class with the default-initialized value of type <code>T</code>.
+ **/
+ public
+ Holder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed value.
+ *
+ * @param value The value stored by this holder.
+ **/
+ public
+ Holder(T value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * The <code>T</code> value stored by this holder.
+ **/
+ public T value;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ImplicitContextI.java b/java-compat/src/Ice/src/main/java/Ice/ImplicitContextI.java
new file mode 100644
index 00000000000..8dd39e414b9
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ImplicitContextI.java
@@ -0,0 +1,318 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+//
+// The base class for all ImplicitContext implementations
+//
+public abstract class ImplicitContextI implements ImplicitContext
+{
+ public static ImplicitContextI create(String kind)
+ {
+ if(kind.equals("None") || kind.equals(""))
+ {
+ return null;
+ }
+ else if(kind.equals("Shared"))
+ {
+ return new Shared();
+ }
+ else if(kind.equals("PerThread"))
+ {
+ return new PerThread();
+ }
+ else
+ {
+ throw new Ice.InitializationException(
+ "'" + kind + "' is not a valid value for Ice.ImplicitContext");
+ }
+ }
+
+ abstract public void write(java.util.Map<String, String> prxContext, OutputStream os);
+ abstract java.util.Map<String, String> combine(java.util.Map<String, String> prxContext);
+
+ static class Shared extends ImplicitContextI
+ {
+ @Override
+ public synchronized java.util.Map<String, String> getContext()
+ {
+ return new java.util.HashMap<String, String>(_context);
+ }
+
+ @Override
+ public synchronized void setContext(java.util.Map<String, String> context)
+ {
+ _context.clear();
+ if(context != null && !context.isEmpty())
+ {
+ _context.putAll(context);
+ }
+ }
+
+ @Override
+ public synchronized boolean containsKey(String key)
+ {
+ if(key == null)
+ {
+ key = "";
+ }
+
+ return _context.containsKey(key);
+ }
+
+ @Override
+ public synchronized String get(String key)
+ {
+ if(key == null)
+ {
+ key = "";
+ }
+
+ String val = _context.get(key);
+ if(val == null)
+ {
+ val = "";
+ }
+
+ return val;
+ }
+
+ @Override
+ public synchronized String put(String key, String value)
+ {
+ if(key == null)
+ {
+ key = "";
+ }
+ if(value == null)
+ {
+ value = "";
+ }
+
+ String oldVal = _context.put(key, value);
+ if(oldVal == null)
+ {
+ oldVal = "";
+ }
+ return oldVal;
+ }
+
+ @Override
+ public synchronized String remove(String key)
+ {
+ if(key == null)
+ {
+ key = "";
+ }
+
+ String val = _context.remove(key);
+
+ if(val == null)
+ {
+ val = "";
+ }
+ return val;
+ }
+
+ @Override
+ public void write(java.util.Map<String, String> prxContext, OutputStream os)
+ {
+ if(prxContext.isEmpty())
+ {
+ synchronized(this)
+ {
+ ContextHelper.write(os, _context);
+ }
+ }
+ else
+ {
+ java.util.Map<String, String> ctx = null;
+ synchronized(this)
+ {
+ ctx = _context.isEmpty() ? prxContext : combine(prxContext);
+ }
+ ContextHelper.write(os, ctx);
+ }
+ }
+
+ @Override
+ synchronized java.util.Map<String, String> combine(java.util.Map<String, String> prxContext)
+ {
+ java.util.Map<String, String> combined = new java.util.HashMap<String, String>(_context);
+ combined.putAll(prxContext);
+ return combined;
+ }
+
+ private java.util.Map<String, String> _context = new java.util.HashMap<String, String>();
+ }
+
+ static class PerThread extends ImplicitContextI
+ {
+
+ @Override
+ public java.util.Map<String, String> getContext()
+ {
+ //
+ // Note that _map is a *synchronized* map
+ //
+ java.util.Map<String, String> threadContext = _map.get(Thread.currentThread());
+
+ if(threadContext == null)
+ {
+ threadContext = new java.util.HashMap<String, String>();
+ }
+ return threadContext;
+ }
+
+ @Override
+ public void setContext(java.util.Map<String, String> context)
+ {
+ if(context == null || context.isEmpty())
+ {
+ _map.remove(Thread.currentThread());
+ }
+ else
+ {
+ java.util.Map<String, String> threadContext = new java.util.HashMap<String, String>(context);
+ _map.put(Thread.currentThread(), threadContext);
+ }
+ }
+
+ @Override
+ public boolean containsKey(String key)
+ {
+ if(key == null)
+ {
+ key = "";
+ }
+
+ java.util.Map<String, String> threadContext = _map.get(Thread.currentThread());
+
+ if(threadContext == null)
+ {
+ return false;
+ }
+
+ return threadContext.containsKey(key);
+ }
+
+ @Override
+ public String get(String key)
+ {
+ if(key == null)
+ {
+ key = "";
+ }
+
+ java.util.Map<String, String> threadContext = _map.get(Thread.currentThread());
+
+ if(threadContext == null)
+ {
+ return "";
+ }
+ String val = threadContext.get(key);
+ if(val == null)
+ {
+ val = "";
+ }
+ return val;
+ }
+
+ @Override
+ public String put(String key, String value)
+ {
+ if(key == null)
+ {
+ key = "";
+ }
+ if(value == null)
+ {
+ value = "";
+ }
+
+ Thread currentThread = Thread.currentThread();
+ java.util.Map<String, String> threadContext = _map.get(currentThread);
+
+ if(threadContext == null)
+ {
+ threadContext = new java.util.HashMap<String, String>();
+ _map.put(currentThread, threadContext);
+ }
+
+ String oldVal = threadContext.put(key, value);
+ if(oldVal == null)
+ {
+ oldVal = "";
+ }
+ return oldVal;
+ }
+
+ @Override
+ public String remove(String key)
+ {
+ if(key == null)
+ {
+ key = "";
+ }
+
+ java.util.Map<String, String> threadContext = _map.get(Thread.currentThread());
+
+ if(threadContext == null)
+ {
+ return null;
+ }
+
+ String val = threadContext.remove(key);
+
+ if(val == null)
+ {
+ val = "";
+ }
+ return val;
+ }
+
+ @Override
+ public void write(java.util.Map<String, String> prxContext, OutputStream os)
+ {
+ java.util.Map<String, String> threadContext = _map.get(Thread.currentThread());
+
+ if(threadContext == null || threadContext.isEmpty())
+ {
+ ContextHelper.write(os, prxContext);
+ }
+ else if(prxContext.isEmpty())
+ {
+ ContextHelper.write(os, threadContext);
+ }
+ else
+ {
+ java.util.Map<String, String> combined = new java.util.HashMap<String, String>(threadContext);
+ combined.putAll(prxContext);
+ ContextHelper.write(os, combined);
+ }
+ }
+
+ @Override
+ java.util.Map<String, String> combine(java.util.Map<String, String> prxContext)
+ {
+ java.util.Map<String, String> threadContext = _map.get(Thread.currentThread());
+
+ java.util.Map<String, String> combined = new java.util.HashMap<String, String>(threadContext);
+ combined.putAll(prxContext);
+ return combined;
+ }
+
+ //
+ // Synchronized map Thread -> Context
+ //
+ private java.util.Map<Thread, java.util.Map<String, String> > _map =
+ java.util.Collections.synchronizedMap(new java.util.HashMap<Thread, java.util.Map<String, String> >());
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/InitializationData.java b/java-compat/src/Ice/src/main/java/Ice/InitializationData.java
new file mode 100644
index 00000000000..860557563e6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/InitializationData.java
@@ -0,0 +1,96 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * A class that encapsulates data to initialize a communicator.
+ *
+ * @see Util#initialize
+ * @see Properties
+ * @see Logger
+ * @see ThreadNotification
+ **/
+public final class InitializationData implements Cloneable
+{
+ /**
+ * Creates an instance with all members set to <code>null</code>.
+ **/
+ public
+ InitializationData()
+ {
+ }
+
+ /**
+ * Creates and returns a copy of this object.
+ **/
+ @Override
+ public InitializationData
+ clone()
+ {
+ //
+ // A member-wise copy is safe because the members are immutable.
+ //
+ InitializationData c = null;
+ try
+ {
+ c = (InitializationData)super.clone();
+ }
+ catch(CloneNotSupportedException ex)
+ {
+ assert false;
+ }
+ return c;
+ }
+
+ /**
+ * The properties for the communicator.
+ **/
+ public Properties properties;
+
+ /**
+ * The logger for the communicator.
+ **/
+ public Logger logger;
+
+ /**
+ * The communicator observer used by the Ice run-time.
+ **/
+ public Ice.Instrumentation.CommunicatorObserver observer;
+
+ /**
+ * The thread hook for the communicator.
+ **/
+ public ThreadNotification threadHook;
+
+ /**
+ * The custom class loader for the communicator.
+ **/
+ public ClassLoader classLoader;
+
+ /**
+ * The call dispatcher for the communicator.
+ **/
+ public Dispatcher dispatcher;
+
+ /**
+ * The compact type ID resolver.
+ **/
+ public CompactIdResolver compactIdResolver;
+
+ /**
+ * The batch request interceptor.
+ **/
+ public BatchRequestInterceptor batchRequestInterceptor;
+
+ /**
+ * The value factory manager.
+ **/
+ public ValueFactoryManager valueFactoryManager;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/InputStream.java b/java-compat/src/Ice/src/main/java/Ice/InputStream.java
new file mode 100644
index 00000000000..2027f53d03b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/InputStream.java
@@ -0,0 +1,3422 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+import java.io.IOException;
+
+/**
+ * Interface for input streams used to extract Slice types from a sequence
+ * of bytes.
+ *
+ * @see OutputStream
+ **/
+public class InputStream
+{
+ /**
+ * Constructing an InputStream without providing a communicator means the stream will
+ * use the default encoding version. A communicator is required in order to unmarshal
+ * proxies. You can supply a communicator later by calling initialize().
+ **/
+ public InputStream()
+ {
+ initialize(IceInternal.Protocol.currentEncoding);
+ _buf = new IceInternal.Buffer(false);
+ }
+
+ /**
+ * Constructing an InputStream without providing a communicator means the stream will
+ * use the default encoding version. A communicator is required in order to unmarshal
+ * proxies. You can supply a communicator later by calling initialize().
+ *
+ * @param data The byte array containing encoded Slice types.
+ **/
+ public InputStream(byte[] data)
+ {
+ initialize(IceInternal.Protocol.currentEncoding);
+ _buf = new IceInternal.Buffer(data);
+ }
+
+ /**
+ * Constructing an InputStream without providing a communicator means the stream will
+ * use the default encoding version. A communicator is required in order to unmarshal
+ * proxies. You can supply a communicator later by calling initialize().
+ *
+ * @param buf The byte buffer containing encoded Slice types.
+ **/
+ public InputStream(java.nio.ByteBuffer buf)
+ {
+ initialize(IceInternal.Protocol.currentEncoding);
+ _buf = new IceInternal.Buffer(buf);
+ }
+
+ public InputStream(IceInternal.Buffer buf)
+ {
+ this(buf, false);
+ }
+
+ public InputStream(IceInternal.Buffer buf, boolean adopt)
+ {
+ initialize(IceInternal.Protocol.currentEncoding);
+ _buf = new IceInternal.Buffer(buf, adopt);
+ }
+
+ /**
+ * This constructor uses the communicator's default encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ **/
+ public InputStream(Communicator communicator)
+ {
+ IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, instance.defaultsAndOverrides().defaultEncoding);
+ _buf = new IceInternal.Buffer(instance.cacheMessageBuffers() > 1);
+ }
+
+ /**
+ * This constructor uses the communicator's default encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ * @param data The byte array containing encoded Slice types.
+ **/
+ public InputStream(Communicator communicator, byte[] data)
+ {
+ initialize(communicator);
+ _buf = new IceInternal.Buffer(data);
+ }
+
+ /**
+ * This constructor uses the communicator's default encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ * @param buf The byte buffer containing encoded Slice types.
+ **/
+ public InputStream(Communicator communicator, java.nio.ByteBuffer buf)
+ {
+ initialize(communicator);
+ _buf = new IceInternal.Buffer(buf);
+ }
+
+ public InputStream(Communicator communicator, IceInternal.Buffer buf)
+ {
+ this(communicator, buf, false);
+ }
+
+ public InputStream(Communicator communicator, IceInternal.Buffer buf, boolean adopt)
+ {
+ initialize(communicator);
+ _buf = new IceInternal.Buffer(buf, adopt);
+ }
+
+ /**
+ * This constructor uses the given encoding version.
+ **/
+ public InputStream(EncodingVersion encoding)
+ {
+ initialize(encoding);
+ _buf = new IceInternal.Buffer(false);
+ }
+
+ /**
+ * This constructor uses the given encoding version.
+ *
+ * @param data The byte array containing encoded Slice types.
+ **/
+ public InputStream(EncodingVersion encoding, byte[] data)
+ {
+ initialize(encoding);
+ _buf = new IceInternal.Buffer(data);
+ }
+
+ /**
+ * This constructor uses the given encoding version.
+ *
+ * @param buf The byte buffer containing encoded Slice types.
+ **/
+ public InputStream(EncodingVersion encoding, java.nio.ByteBuffer buf)
+ {
+ initialize(encoding);
+ _buf = new IceInternal.Buffer(buf);
+ }
+
+ public InputStream(EncodingVersion encoding, IceInternal.Buffer buf)
+ {
+ this(encoding, buf, false);
+ }
+
+ public InputStream(EncodingVersion encoding, IceInternal.Buffer buf, boolean adopt)
+ {
+ initialize(encoding);
+ _buf = new IceInternal.Buffer(buf, adopt);
+ }
+
+ /**
+ * This constructor uses the given communicator and encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ * @param encoding The desired encoding version.
+ **/
+ public InputStream(Communicator communicator, EncodingVersion encoding)
+ {
+ IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, encoding);
+ _buf = new IceInternal.Buffer(instance.cacheMessageBuffers() > 1);
+ }
+
+ /**
+ * This constructor uses the given communicator and encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ * @param encoding The desired encoding version.
+ * @param data The byte array containing encoded Slice types.
+ **/
+ public InputStream(Communicator communicator, EncodingVersion encoding, byte[] data)
+ {
+ initialize(communicator, encoding);
+ _buf = new IceInternal.Buffer(data);
+ }
+
+ /**
+ * This constructor uses the given communicator and encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ * @param encoding The desired encoding version.
+ * @param buf The byte buffer containing encoded Slice types.
+ **/
+ public InputStream(Communicator communicator, EncodingVersion encoding, java.nio.ByteBuffer buf)
+ {
+ initialize(communicator, encoding);
+ _buf = new IceInternal.Buffer(buf);
+ }
+
+ public InputStream(Communicator communicator, EncodingVersion encoding, IceInternal.Buffer buf)
+ {
+ this(communicator, encoding, buf, false);
+ }
+
+ public InputStream(Communicator communicator, EncodingVersion encoding, IceInternal.Buffer buf, boolean adopt)
+ {
+ initialize(communicator, encoding);
+ _buf = new IceInternal.Buffer(buf, adopt);
+ }
+
+ public InputStream(IceInternal.Instance instance, EncodingVersion encoding)
+ {
+ this(instance, encoding, instance.cacheMessageBuffers() > 1);
+ }
+
+ public InputStream(IceInternal.Instance instance, EncodingVersion encoding, boolean direct)
+ {
+ initialize(instance, encoding);
+ _buf = new IceInternal.Buffer(direct);
+ }
+
+ public InputStream(IceInternal.Instance instance, EncodingVersion encoding, byte[] data)
+ {
+ initialize(instance, encoding);
+ _buf = new IceInternal.Buffer(data);
+ }
+
+ public InputStream(IceInternal.Instance instance, EncodingVersion encoding, java.nio.ByteBuffer data)
+ {
+ initialize(instance, encoding);
+ _buf = new IceInternal.Buffer(data);
+ }
+
+ public InputStream(IceInternal.Instance instance, EncodingVersion encoding, IceInternal.Buffer buf, boolean adopt)
+ {
+ initialize(instance, encoding);
+ _buf = new IceInternal.Buffer(buf, adopt);
+ }
+
+ /**
+ * Initializes the stream to use the communicator's default encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ **/
+ public void initialize(Communicator communicator)
+ {
+ IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, instance.defaultsAndOverrides().defaultEncoding);
+ }
+
+ /**
+ * Initializes the stream to use the given communicator and encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ * @param encoding The desired encoding version.
+ **/
+ public void initialize(Communicator communicator, EncodingVersion encoding)
+ {
+ IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, encoding);
+ }
+
+ private void initialize(IceInternal.Instance instance, EncodingVersion encoding)
+ {
+ initialize(encoding);
+
+ _instance = instance;
+ _traceSlicing = _instance.traceLevels().slicing > 0;
+
+ _valueFactoryManager = _instance.initializationData().valueFactoryManager;
+ _logger = _instance.initializationData().logger;
+ _classResolver = _instance;
+ }
+
+ private void initialize(EncodingVersion encoding)
+ {
+ _instance = null;
+ _encoding = encoding;
+ _encapsStack = null;
+ _encapsCache = null;
+ _traceSlicing = false;
+ _closure = null;
+ _sliceValues = true;
+ _startSeq = -1;
+ _minSeqSize = 0;
+ }
+
+ /**
+ * Resets this stream. This method allows the stream to be reused, to avoid creating
+ * unnecessary garbage.
+ **/
+ public void reset()
+ {
+ _buf.reset();
+ clear();
+ }
+
+ /**
+ * Releases any data retained by encapsulations. The {@link #reset} method internally calls </code>clear</code>.
+ **/
+ public void clear()
+ {
+ if(_encapsStack != null)
+ {
+ assert(_encapsStack.next == null);
+ _encapsStack.next = _encapsCache;
+ _encapsCache = _encapsStack;
+ _encapsCache.reset();
+ _encapsStack = null;
+ }
+
+ _startSeq = -1;
+ _sliceValues = true;
+ }
+
+ /**
+ * Sets the value factory manager to use when marshaling value instances. If the stream
+ * was initialized with a communicator, the communicator's value factory manager will
+ * be used by default.
+ *
+ * @param vfm The value factory manager.
+ **/
+ public void setValueFactoryManager(ValueFactoryManager vfm)
+ {
+ _valueFactoryManager = vfm;
+ }
+
+ /**
+ * Sets the logger to use when logging trace messages. If the stream
+ * was initialized with a communicator, the communicator's logger will
+ * be used by default.
+ *
+ * @param logger The logger to use for logging trace messages.
+ **/
+ public void setLogger(Logger logger)
+ {
+ _logger = logger;
+ }
+
+ /**
+ * Sets the compact ID resolver to use when unmarshaling value and exception
+ * instances. If the stream was initialized with a communicator, the communicator's
+ * resolver will be used by default.
+ *
+ * @param r The compact ID resolver.
+ **/
+ public void setCompactIdResolver(CompactIdResolver r)
+ {
+ _compactIdResolver = r;
+ }
+
+ /**
+ * Sets the class resolver, which the stream will use when attempting to unmarshal
+ * a value or exception. If the stream was initialized with a communicator, the communicator's
+ * resolver will be used by default.
+ *
+ * @param r The class resolver.
+ **/
+ public void setClassResolver(ClassResolver r)
+ {
+ _classResolver = r;
+ }
+
+ /**
+ * Determines the behavior of the stream when extracting instances of Slice classes.
+ * An instance is "sliced" when a factory cannot be found for a Slice type ID.
+ * The stream's default behavior is to slice instances.
+ *
+ * @param b If <code>true</code> (the default), slicing is enabled; if <code>false</code>,
+ * slicing is disabled. If slicing is disabled and the stream encounters a Slice type ID
+ * during decoding for which no value factory is installed, it raises {@link NoValueFactoryException}.
+ **/
+ public void setSliceValues(boolean b)
+ {
+ _sliceValues = b;
+ }
+
+ /**
+ * Determines whether the stream logs messages about slicing instances of Slice values.
+ *
+ * @param b True to enable logging, false to disable logging.
+ **/
+ public void setTraceSlicing(boolean b)
+ {
+ _traceSlicing = b;
+ }
+
+ /**
+ * Retrieves the closure object associated with this stream.
+ *
+ * @return The closure object.
+ **/
+ public Object getClosure()
+ {
+ return _closure;
+ }
+
+ /**
+ * Associates a closure object with this stream.
+ *
+ * @param p The new closure object.
+ * @return The previous closure object, or null.
+ **/
+ public Object setClosure(Object p)
+ {
+ Object prev = _closure;
+ _closure = p;
+ return prev;
+ }
+
+ public IceInternal.Instance instance()
+ {
+ return _instance;
+ }
+
+ /**
+ * Swaps the contents of one stream with another.
+ *
+ * @param other The other stream.
+ **/
+ public void swap(InputStream other)
+ {
+ assert(_instance == other._instance);
+
+ IceInternal.Buffer tmpBuf = other._buf;
+ other._buf = _buf;
+ _buf = tmpBuf;
+
+ EncodingVersion tmpEncoding = other._encoding;
+ other._encoding = _encoding;
+ _encoding = tmpEncoding;
+
+ boolean tmpTraceSlicing = other._traceSlicing;
+ other._traceSlicing = _traceSlicing;
+ _traceSlicing = tmpTraceSlicing;
+
+ Object tmpClosure = other._closure;
+ other._closure = _closure;
+ _closure = tmpClosure;
+
+ boolean tmpSliceValues = other._sliceValues;
+ other._sliceValues = _sliceValues;
+ _sliceValues = tmpSliceValues;
+
+ //
+ // Swap is never called for streams that have encapsulations being read. However,
+ // encapsulations might still be set in case unmarshaling failed. We just
+ // reset the encapsulations if there are still some set.
+ //
+ resetEncapsulation();
+ other.resetEncapsulation();
+
+ int tmpStartSeq = other._startSeq;
+ other._startSeq = _startSeq;
+ _startSeq = tmpStartSeq;
+
+ int tmpMinSeqSize = other._minSeqSize;
+ other._minSeqSize = _minSeqSize;
+ _minSeqSize = tmpMinSeqSize;
+
+ ValueFactoryManager tmpVfm = other._valueFactoryManager;
+ other._valueFactoryManager = _valueFactoryManager;
+ _valueFactoryManager = tmpVfm;
+
+ Logger tmpLogger = other._logger;
+ other._logger = _logger;
+ _logger = tmpLogger;
+
+ CompactIdResolver tmpCompactIdResolver = other._compactIdResolver;
+ other._compactIdResolver = _compactIdResolver;
+ _compactIdResolver = tmpCompactIdResolver;
+
+ ClassResolver tmpClassResolver = other._classResolver;
+ other._classResolver = _classResolver;
+ _classResolver = tmpClassResolver;
+ }
+
+ private void resetEncapsulation()
+ {
+ _encapsStack = null;
+ }
+
+ /**
+ * Resizes the stream to a new size.
+ *
+ * @param sz The new size.
+ **/
+ public void resize(int sz)
+ {
+ _buf.resize(sz, true);
+ _buf.b.position(sz);
+ }
+
+ public IceInternal.Buffer getBuffer()
+ {
+ return _buf;
+ }
+
+ /**
+ * Marks the start of a class instance.
+ **/
+ public void startValue()
+ {
+ assert(_encapsStack != null && _encapsStack.decoder != null);
+ _encapsStack.decoder.startInstance(SliceType.ValueSlice);
+ }
+
+ /**
+ * Marks the end of a class instance.
+ *
+ * @param preserve Pass true and the stream will preserve the unknown slices of the instance, or false
+ * to discard the unknown slices.
+ * @return An object that encapsulates the unknown slice data.
+ **/
+ public SlicedData endValue(boolean preserve)
+ {
+ assert(_encapsStack != null && _encapsStack.decoder != null);
+ return _encapsStack.decoder.endInstance(preserve);
+ }
+
+ /**
+ * Marks the start of a user exception.
+ **/
+ public void startException()
+ {
+ assert(_encapsStack != null && _encapsStack.decoder != null);
+ _encapsStack.decoder.startInstance(SliceType.ExceptionSlice);
+ }
+
+ /**
+ * Marks the end of a user exception.
+ *
+ * @param preserve Pass true and the stream will preserve the unknown slices of the exception, or false
+ * to discard the unknown slices.
+ * @return An object that encapsulates the unknown slice data.
+ **/
+ public SlicedData endException(boolean preserve)
+ {
+ assert(_encapsStack != null && _encapsStack.decoder != null);
+ return _encapsStack.decoder.endInstance(preserve);
+ }
+
+ /**
+ * Reads the start of an encapsulation.
+ *
+ * @return The encoding version used by the encapsulation.
+ **/
+ public EncodingVersion startEncapsulation()
+ {
+ Encaps curr = _encapsCache;
+ if(curr != null)
+ {
+ curr.reset();
+ _encapsCache = _encapsCache.next;
+ }
+ else
+ {
+ curr = new Encaps();
+ }
+ curr.next = _encapsStack;
+ _encapsStack = curr;
+
+ _encapsStack.start = _buf.b.position();
+
+ //
+ // I don't use readSize() 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(), it could be 1 or 5 bytes.
+ //
+ int sz = readInt();
+ if(sz < 6)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ if(sz - 4 > _buf.b.remaining())
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ _encapsStack.sz = sz;
+
+ EncodingVersion encoding = new EncodingVersion();
+ encoding.__read(this);
+ IceInternal.Protocol.checkSupportedEncoding(encoding); // Make sure the encoding is supported.
+ _encapsStack.setEncoding(encoding);
+
+ return encoding;
+ }
+
+ /**
+ * Ends the previous encapsulation.
+ **/
+ public void endEncapsulation()
+ {
+ assert(_encapsStack != null);
+
+ if(!_encapsStack.encoding_1_0)
+ {
+ skipOptionals();
+ if(_buf.b.position() != _encapsStack.start + _encapsStack.sz)
+ {
+ throw new EncapsulationException();
+ }
+ }
+ else if(_buf.b.position() != _encapsStack.start + _encapsStack.sz)
+ {
+ if(_buf.b.position() + 1 != _encapsStack.start + _encapsStack.sz)
+ {
+ throw new 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
+ {
+ _buf.b.get();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ Encaps curr = _encapsStack;
+ _encapsStack = curr.next;
+ curr.next = _encapsCache;
+ _encapsCache = curr;
+ _encapsCache.reset();
+ }
+
+ /**
+ * Skips an empty encapsulation.
+ *
+ * @return The encapsulation's encoding version.
+ **/
+ public EncodingVersion skipEmptyEncapsulation()
+ {
+ int sz = readInt();
+ if(sz < 6)
+ {
+ throw new Ice.EncapsulationException();
+ }
+ if(sz - 4 > _buf.b.remaining())
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+
+ EncodingVersion encoding = EncodingVersion.read(this, null);
+ if(encoding.equals(Ice.Util.Encoding_1_0))
+ {
+ if(sz != 6)
+ {
+ throw new Ice.EncapsulationException();
+ }
+ }
+ else
+ {
+ //
+ // Skip the optional content of the encapsulation if we are expecting an
+ // empty encapsulation.
+ //
+ _buf.b.position(_buf.b.position() + sz - 6);
+ }
+ return encoding;
+ }
+
+ /**
+ * Returns a blob of bytes representing an encapsulation. The encapsulation's encoding version
+ * is returned in the argument.
+ *
+ * @param encoding The encapsulation's encoding version.
+ * @return The encoded encapuslation.
+ **/
+ public byte[] readEncapsulation(EncodingVersion encoding)
+ {
+ int sz = readInt();
+ if(sz < 6)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+
+ if(sz - 4 > _buf.b.remaining())
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+
+ if(encoding != null)
+ {
+ encoding.__read(this);
+ _buf.b.position(_buf.b.position() - 6);
+ }
+ else
+ {
+ _buf.b.position(_buf.b.position() - 4);
+ }
+
+ byte[] v = new byte[sz];
+ try
+ {
+ _buf.b.get(v);
+ return v;
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Determines the current encoding version.
+ *
+ * @return The encoding version.
+ **/
+ public EncodingVersion getEncoding()
+ {
+ return _encapsStack != null ? _encapsStack.encoding : _encoding;
+ }
+
+ /**
+ * Determines the size of the current encapsulation, excluding the encapsulation header.
+ *
+ * @return The size of the encapsulated data.
+ **/
+ public int getEncapsulationSize()
+ {
+ assert(_encapsStack != null);
+ return _encapsStack.sz - 6;
+ }
+
+ /**
+ * Skips over an encapsulation.
+ *
+ * @return The encoding version of the skipped encapsulation.
+ **/
+ public EncodingVersion skipEncapsulation()
+ {
+ int sz = readInt();
+ if(sz < 6)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ EncodingVersion encoding = new EncodingVersion();
+ encoding.__read(this);
+ try
+ {
+ _buf.b.position(_buf.b.position() + sz - 6);
+ }
+ catch(IllegalArgumentException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ return encoding;
+ }
+
+ /**
+ * Reads the start of a value or exception slice.
+ *
+ * @return The Slice type ID for this slice.
+ **/
+ public String startSlice() // Returns type ID of next slice
+ {
+ assert(_encapsStack != null && _encapsStack.decoder != null);
+ return _encapsStack.decoder.startSlice();
+ }
+
+ /**
+ * Indicates that the end of a value or exception slice has been reached.
+ **/
+ public void endSlice()
+ {
+ assert(_encapsStack != null && _encapsStack.decoder != null);
+ _encapsStack.decoder.endSlice();
+ }
+
+ /**
+ * Skips over a value or exception slice.
+ **/
+ public void skipSlice()
+ {
+ assert(_encapsStack != null && _encapsStack.decoder != null);
+ _encapsStack.decoder.skipSlice();
+ }
+
+ /**
+ * Indicates that unmarshaling is complete, except for any class instances. The application must call this method
+ * only if the stream actually contains class instances. Calling <code>readPendingValues</code> triggers the
+ * calls to {@link ReadValueCallback#valueReady} that inform the application that unmarshaling of an instance
+ * is complete.
+ **/
+ public void readPendingValues()
+ {
+ if(_encapsStack != null && _encapsStack.decoder != null)
+ {
+ _encapsStack.decoder.readPendingValues();
+ }
+ else if(_encapsStack != null ? _encapsStack.encoding_1_0 : _encoding.equals(Util.Encoding_1_0))
+ {
+ //
+ // If using the 1.0 encoding and no instances were read, we
+ // still read an empty sequence of pending instances if
+ // requested (i.e.: if this is called).
+ //
+ // This is required by the 1.0 encoding, even if no instances
+ // are written we do marshal an empty sequence if marshaled
+ // data types use classes.
+ //
+ skipSize();
+ }
+ }
+
+ /**
+ * Extracts a size from the stream.
+ *
+ * @return The extracted size.
+ **/
+ public int readSize()
+ {
+ try
+ {
+ byte b = _buf.b.get();
+ if(b == -1)
+ {
+ int v = _buf.b.getInt();
+ if(v < 0)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ return v;
+ }
+ else
+ {
+ return b < 0 ? b + 256 : b;
+ }
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Reads and validates a sequence size.
+ *
+ * @return The extracted size.
+ **/
+ public int readAndCheckSeqSize(int minSize)
+ {
+ int sz = 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(_startSeq == -1 || _buf.b.position() > (_startSeq + _minSeqSize))
+ {
+ _startSeq = _buf.b.position();
+ _minSeqSize = sz * minSize;
+ }
+ else
+ {
+ _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(_startSeq + _minSeqSize > _buf.size())
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+
+ return sz;
+ }
+
+ /**
+ * Reads a blob of bytes from the stream.
+ *
+ * @param sz The number of bytes to read.
+ * @return The requested bytes as a byte array.
+ **/
+ public byte[] readBlob(int sz)
+ {
+ if(_buf.b.remaining() < sz)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ byte[] v = new byte[sz];
+ try
+ {
+ _buf.b.get(v);
+ return v;
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Determine if an optional value is available for reading.
+ *
+ * @param tag The tag associated with the value.
+ * @param expectedFormat The optional format for the value.
+ * @return True if the value is present, false otherwise.
+ **/
+ public boolean readOptional(int tag, OptionalFormat expectedFormat)
+ {
+ assert(_encapsStack != null);
+ if(_encapsStack.decoder != null)
+ {
+ return _encapsStack.decoder.readOptional(tag, expectedFormat);
+ }
+ else
+ {
+ return readOptImpl(tag, expectedFormat);
+ }
+ }
+
+ /**
+ * Extracts a byte value from the stream.
+ *
+ * @return The extracted byte.
+ **/
+ public byte readByte()
+ {
+ try
+ {
+ return _buf.b.get();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional byte value from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readByte(int tag, ByteOptional v)
+ {
+ if(readOptional(tag, OptionalFormat.F1))
+ {
+ v.set(readByte());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a sequence of byte values from the stream.
+ *
+ * @return The extracted byte sequence.
+ **/
+ public byte[] readByteSeq()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(1);
+ byte[] v = new byte[sz];
+ _buf.b.get(v);
+ return v;
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional byte sequence from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readByteSeq(int tag, Optional<byte[]> v)
+ {
+ if(readOptional(tag, OptionalFormat.VSize))
+ {
+ v.set(readByteSeq());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Returns a byte buffer representing a sequence of bytes. This method does not copy the data.
+ *
+ * @return A byte buffer "slice" of the internal buffer.
+ **/
+ public java.nio.ByteBuffer readByteBuffer()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(1);
+ java.nio.ByteBuffer v = _buf.b.slice();
+ v.limit(sz);
+ _buf.b.position(_buf.b.position() + sz);
+ return v.asReadOnlyBuffer();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts a serializable Java object from the stream.
+ *
+ * @return The deserialized Java object.
+ **/
+ public java.io.Serializable readSerializable()
+ {
+ int sz = readAndCheckSeqSize(1);
+ if (sz == 0)
+ {
+ return null;
+ }
+ IceInternal.ObjectInputStream in = null;
+ try
+ {
+ IceInternal.InputStreamWrapper w = new IceInternal.InputStreamWrapper(sz, _buf.b);
+ in = new IceInternal.ObjectInputStream(_instance, w);
+ return (java.io.Serializable)in.readObject();
+ }
+ catch(LocalException ex)
+ {
+ throw ex;
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new MarshalException("cannot deserialize object", ex);
+ }
+ finally
+ {
+ if(in != null)
+ {
+ try
+ {
+ in.close();
+ }
+ catch (IOException ex)
+ {
+ throw new MarshalException("cannot deserialize object", ex);
+ }
+ }
+ }
+ }
+
+ /**
+ * Extracts a boolean value from the stream.
+ *
+ * @return The extracted boolean.
+ **/
+ public boolean readBool()
+ {
+ try
+ {
+ return _buf.b.get() == 1;
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional boolean value from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readBool(int tag, BooleanOptional v)
+ {
+ if(readOptional(tag, OptionalFormat.F1))
+ {
+ v.set(readBool());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a sequence of boolean values from the stream.
+ *
+ * @return The extracted boolean sequence.
+ **/
+ public boolean[] readBoolSeq()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(1);
+ boolean[] v = new boolean[sz];
+ for(int i = 0; i < sz; i++)
+ {
+ v[i] = _buf.b.get() == 1;
+ }
+ return v;
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional boolean sequence from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readBoolSeq(int tag, Optional<boolean[]> v)
+ {
+ if(readOptional(tag, OptionalFormat.VSize))
+ {
+ v.set(readBoolSeq());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a short value from the stream.
+ *
+ * @return The extracted short.
+ **/
+ public short readShort()
+ {
+ try
+ {
+ return _buf.b.getShort();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional short value from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readShort(int tag, ShortOptional v)
+ {
+ if(readOptional(tag, OptionalFormat.F2))
+ {
+ v.set(readShort());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a sequence of short values from the stream.
+ *
+ * @return The extracted short sequence.
+ **/
+ public short[] readShortSeq()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(2);
+ short[] v = new short[sz];
+ java.nio.ShortBuffer shortBuf = _buf.b.asShortBuffer();
+ shortBuf.get(v);
+ _buf.b.position(_buf.b.position() + sz * 2);
+ return v;
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional short sequence from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readShortSeq(int tag, Optional<short[]> v)
+ {
+ if(readOptional(tag, OptionalFormat.VSize))
+ {
+ skipSize();
+ v.set(readShortSeq());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Returns a short buffer representing a sequence of shorts. This method does not copy the data.
+ *
+ * @return A short buffer "slice" of the internal buffer.
+ **/
+ public java.nio.ShortBuffer readShortBuffer()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(2);
+ java.nio.ShortBuffer shortBuf = _buf.b.asShortBuffer();
+ java.nio.ShortBuffer v = shortBuf.slice();
+ v.limit(sz);
+ _buf.b.position(_buf.b.position() + sz * 2);
+ return v.asReadOnlyBuffer();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an int value from the stream.
+ *
+ * @return The extracted int.
+ **/
+ public int readInt()
+ {
+ try
+ {
+ return _buf.b.getInt();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional int value from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readInt(int tag, IntOptional v)
+ {
+ if(readOptional(tag, OptionalFormat.F4))
+ {
+ v.set(readInt());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a sequence of int values from the stream.
+ *
+ * @return The extracted int sequence.
+ **/
+ public int[] readIntSeq()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(4);
+ int[] v = new int[sz];
+ java.nio.IntBuffer intBuf = _buf.b.asIntBuffer();
+ intBuf.get(v);
+ _buf.b.position(_buf.b.position() + sz * 4);
+ return v;
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional int sequence from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readIntSeq(int tag, Optional<int[]> v)
+ {
+ if(readOptional(tag, OptionalFormat.VSize))
+ {
+ skipSize();
+ v.set(readIntSeq());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Returns an int buffer representing a sequence of ints. This method does not copy the data.
+ *
+ * @return An int buffer "slice" of the internal buffer.
+ **/
+ public java.nio.IntBuffer readIntBuffer()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(4);
+ java.nio.IntBuffer intBuf = _buf.b.asIntBuffer();
+ java.nio.IntBuffer v = intBuf.slice();
+ v.limit(sz);
+ _buf.b.position(_buf.b.position() + sz * 4);
+ return v.asReadOnlyBuffer();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts a long value from the stream.
+ *
+ * @return The extracted long.
+ **/
+ public long readLong()
+ {
+ try
+ {
+ return _buf.b.getLong();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional long value from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readLong(int tag, LongOptional v)
+ {
+ if(readOptional(tag, OptionalFormat.F8))
+ {
+ v.set(readLong());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a sequence of long values from the stream.
+ *
+ * @return The extracted long sequence.
+ **/
+ public long[] readLongSeq()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(8);
+ long[] v = new long[sz];
+ java.nio.LongBuffer longBuf = _buf.b.asLongBuffer();
+ longBuf.get(v);
+ _buf.b.position(_buf.b.position() + sz * 8);
+ return v;
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional long sequence from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readLongSeq(int tag, Optional<long[]> v)
+ {
+ if(readOptional(tag, OptionalFormat.VSize))
+ {
+ skipSize();
+ v.set(readLongSeq());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Returns a long buffer representing a sequence of longs. This method does not copy the data.
+ *
+ * @return A long buffer "slice" of the internal buffer.
+ **/
+ public java.nio.LongBuffer readLongBuffer()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(8);
+ java.nio.LongBuffer longBuf = _buf.b.asLongBuffer();
+ java.nio.LongBuffer v = longBuf.slice();
+ v.limit(sz);
+ _buf.b.position(_buf.b.position() + sz * 8);
+ return v.asReadOnlyBuffer();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts a float value from the stream.
+ *
+ * @return The extracted float.
+ **/
+ public float readFloat()
+ {
+ try
+ {
+ return _buf.b.getFloat();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional float value from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readFloat(int tag, FloatOptional v)
+ {
+ if(readOptional(tag, OptionalFormat.F4))
+ {
+ v.set(readFloat());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a sequence of float values from the stream.
+ *
+ * @return The extracted float sequence.
+ **/
+ public float[] readFloatSeq()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(4);
+ float[] v = new float[sz];
+ java.nio.FloatBuffer floatBuf = _buf.b.asFloatBuffer();
+ floatBuf.get(v);
+ _buf.b.position(_buf.b.position() + sz * 4);
+ return v;
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional float sequence from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readFloatSeq(int tag, Optional<float[]> v)
+ {
+ if(readOptional(tag, OptionalFormat.VSize))
+ {
+ skipSize();
+ v.set(readFloatSeq());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Returns a float buffer representing a sequence of floats. This method does not copy the data.
+ *
+ * @return A float buffer "slice" of the internal buffer.
+ **/
+ public java.nio.FloatBuffer readFloatBuffer()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(4);
+ java.nio.FloatBuffer floatBuf = _buf.b.asFloatBuffer();
+ java.nio.FloatBuffer v = floatBuf.slice();
+ v.limit(sz);
+ _buf.b.position(_buf.b.position() + sz * 4);
+ return v.asReadOnlyBuffer();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts a double value from the stream.
+ *
+ * @return The extracted double.
+ **/
+ public double readDouble()
+ {
+ try
+ {
+ return _buf.b.getDouble();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional double value from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readDouble(int tag, DoubleOptional v)
+ {
+ if(readOptional(tag, OptionalFormat.F8))
+ {
+ v.set(readDouble());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a sequence of double values from the stream.
+ *
+ * @return The extracted double sequence.
+ **/
+ public double[] readDoubleSeq()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(8);
+ double[] v = new double[sz];
+ java.nio.DoubleBuffer doubleBuf = _buf.b.asDoubleBuffer();
+ doubleBuf.get(v);
+ _buf.b.position(_buf.b.position() + sz * 8);
+ return v;
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Extracts an optional double sequence from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readDoubleSeq(int tag, Optional<double[]> v)
+ {
+ if(readOptional(tag, OptionalFormat.VSize))
+ {
+ skipSize();
+ v.set(readDoubleSeq());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Returns a double buffer representing a sequence of doubles. This method does not copy the data.
+ *
+ * @return A double buffer "slice" of the internal buffer.
+ **/
+ public java.nio.DoubleBuffer readDoubleBuffer()
+ {
+ try
+ {
+ final int sz = readAndCheckSeqSize(8);
+ java.nio.DoubleBuffer doubleBuf = _buf.b.asDoubleBuffer();
+ java.nio.DoubleBuffer v = doubleBuf.slice();
+ v.limit(sz);
+ _buf.b.position(_buf.b.position() + sz * 8);
+ return v.asReadOnlyBuffer();
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+
+ final static java.nio.charset.Charset _utf8 = java.nio.charset.Charset.forName("UTF8");
+ private java.nio.charset.CharsetEncoder _charEncoder = null;
+
+ /**
+ * Extracts a string from the stream.
+ *
+ * @return The extracted string.
+ **/
+ public String readString()
+ {
+ final int len = readSize();
+
+ if(len == 0)
+ {
+ return "";
+ }
+ else
+ {
+ //
+ // Check the buffer has enough bytes to read.
+ //
+ if(_buf.b.remaining() < len)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+
+ try
+ {
+ //
+ // We reuse the _stringBytes array to avoid creating
+ // excessive garbage.
+ //
+ if(_stringBytes == null || len > _stringBytes.length)
+ {
+ _stringBytes = new byte[len];
+ }
+ if(_stringChars == null || len > _stringChars.length)
+ {
+ _stringChars = new char[len];
+ }
+ _buf.b.get(_stringBytes, 0, len);
+
+ //
+ // It's more efficient to construct a string using a
+ // character array instead of a byte array, because
+ // byte arrays require conversion.
+ //
+ for(int i = 0; i < len; i++)
+ {
+ if(_stringBytes[i] < 0)
+ {
+ //
+ // Multi-byte character found - we must use
+ // conversion.
+ //
+ // TODO: If the string contains garbage bytes
+ // that won't correctly decode as UTF, the
+ // behavior of this constructor is
+ // undefined. It would be better to explicitly
+ // decode using
+ // java.nio.charset.CharsetDecoder and to
+ // throw MarshalException if the string won't
+ // decode.
+ //
+ return new String(_stringBytes, 0, len, "UTF8");
+ }
+ else
+ {
+ _stringChars[i] = (char)_stringBytes[i];
+ }
+ }
+ return new String(_stringChars, 0, len);
+ }
+ catch(java.io.UnsupportedEncodingException ex)
+ {
+ assert(false);
+ return "";
+ }
+ catch(java.nio.BufferUnderflowException ex)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+ }
+
+ /**
+ * Extracts an optional string value from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readString(int tag, Optional<String> v)
+ {
+ if(readOptional(tag, OptionalFormat.VSize))
+ {
+ v.set(readString());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a sequence of string values from the stream.
+ *
+ * @return The extracted string sequence.
+ **/
+ public String[] readStringSeq()
+ {
+ final int sz = readAndCheckSeqSize(1);
+ String[] v = new String[sz];
+ for(int i = 0; i < sz; i++)
+ {
+ v[i] = readString();
+ }
+ return v;
+ }
+
+ /**
+ * Extracts an optional string sequence from the stream.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readStringSeq(int tag, Optional<String[]> v)
+ {
+ if(readOptional(tag, OptionalFormat.FSize))
+ {
+ skip(4);
+ v.set(readStringSeq());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a proxy from the stream. The stream must have been initialized with a communicator.
+ *
+ * @return The extracted proxy.
+ **/
+ public ObjectPrx readProxy()
+ {
+ if(_instance == null)
+ {
+ throw new MarshalException("cannot unmarshal a proxy without a communicator");
+ }
+
+ return _instance.proxyFactory().streamToProxy(this);
+ }
+
+ /**
+ * Extracts an optional proxy from the stream. The stream must have been initialized with a communicator.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param v Holds the optional value (if any).
+ **/
+ public void readProxy(int tag, Optional<ObjectPrx> v)
+ {
+ if(readOptional(tag, OptionalFormat.FSize))
+ {
+ skip(4);
+ v.set(readProxy());
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Read an enumerated value.
+ *
+ * @param maxValue The maximum enumerator value in the definition.
+ * @return The enumerator.
+ **/
+ public int readEnum(int maxValue)
+ {
+ if(getEncoding().equals(Util.Encoding_1_0))
+ {
+ if(maxValue < 127)
+ {
+ return readByte();
+ }
+ else if(maxValue < 32767)
+ {
+ return readShort();
+ }
+ else
+ {
+ return readInt();
+ }
+ }
+ else
+ {
+ return readSize();
+ }
+ }
+
+ /**
+ * Extracts the index of a Slice value from the stream.
+ *
+ * @param cb The callback to notify the application when the extracted instance is available.
+ * The stream extracts Slice values in stages. The Ice run time calls {@link ReadValueCallback#valueReady}
+ * when the corresponding instance has been fully unmarshaled.
+ *
+ * @see ReadValueCallback
+ **/
+ public void readValue(ReadValueCallback cb)
+ {
+ initEncaps();
+ _encapsStack.decoder.readValue(cb);
+ }
+
+ /**
+ * Extracts the index of an optional Slice value from the stream.
+ *
+ * @param v Holds the optional value (if any). If a value is present, it will not be set in the
+ * argument until after {@link #readPendingValues} has completed.
+ **/
+ public void readValue(int tag, Optional<Ice.Object> v)
+ {
+ if(readOptional(tag, OptionalFormat.Class))
+ {
+ OptionalObject opt = new OptionalObject(v, Ice.Object.class, ObjectImpl.ice_staticId());
+ readValue(opt);
+ }
+ else
+ {
+ v.clear();
+ }
+ }
+
+ /**
+ * Extracts a user exception from the stream and throws it.
+ **/
+ public void throwException()
+ throws UserException
+ {
+ throwException(null);
+ }
+
+ /**
+ * Extracts a user exception from the stream and throws it. The caller can supply a factory
+ * to instantiate exception instances.
+ *
+ * @param factory The user exception factory, or null to use the stream's default behavior.
+ **/
+ public void throwException(UserExceptionFactory factory)
+ throws UserException
+ {
+ initEncaps();
+ _encapsStack.decoder.throwException(factory);
+ }
+
+ private boolean readOptImpl(int readTag, OptionalFormat expectedFormat)
+ {
+ if(isEncoding_1_0())
+ {
+ return false; // Optional members aren't supported with the 1.0 encoding.
+ }
+
+ while(true)
+ {
+ if(_buf.b.position() >= _encapsStack.start + _encapsStack.sz)
+ {
+ return false; // End of encapsulation also indicates end of optionals.
+ }
+
+ final byte b = readByte();
+ final int v = b < 0 ? b + 256 : b;
+ if(v == IceInternal.Protocol.OPTIONAL_END_MARKER)
+ {
+ _buf.b.position(_buf.b.position() - 1); // Rewind.
+ return false;
+ }
+
+ OptionalFormat format = OptionalFormat.valueOf(v & 0x07); // First 3 bits.
+ int tag = v >> 3;
+ if(tag == 30)
+ {
+ tag = readSize();
+ }
+
+ if(tag > readTag)
+ {
+ int offset = tag < 30 ? 1 : (tag < 255 ? 2 : 6); // Rewind
+ _buf.b.position(_buf.b.position() - offset);
+ return false; // No optional data members with the requested tag.
+ }
+ else if(tag < readTag)
+ {
+ skipOptional(format); // Skip optional data members
+ }
+ else
+ {
+ if(format != expectedFormat)
+ {
+ throw new MarshalException("invalid optional data member `" + tag + "': unexpected format");
+ }
+ return true;
+ }
+ }
+ }
+
+ private void skipOptional(OptionalFormat format)
+ {
+ switch(format)
+ {
+ case F1:
+ {
+ skip(1);
+ break;
+ }
+ case F2:
+ {
+ skip(2);
+ break;
+ }
+ case F4:
+ {
+ skip(4);
+ break;
+ }
+ case F8:
+ {
+ skip(8);
+ break;
+ }
+ case Size:
+ {
+ skipSize();
+ break;
+ }
+ case VSize:
+ {
+ skip(readSize());
+ break;
+ }
+ case FSize:
+ {
+ skip(readInt());
+ break;
+ }
+ case Class:
+ {
+ readValue(null);
+ break;
+ }
+ }
+ }
+
+ private void skipOptionals()
+ {
+ //
+ // Skip remaining un-read optional members.
+ //
+ while(true)
+ {
+ if(_buf.b.position() >= _encapsStack.start + _encapsStack.sz)
+ {
+ return; // End of encapsulation also indicates end of optionals.
+ }
+
+ final byte b = readByte();
+ final int v = b < 0 ? b + 256 : b;
+ if(v == IceInternal.Protocol.OPTIONAL_END_MARKER)
+ {
+ return;
+ }
+
+ OptionalFormat format = OptionalFormat.valueOf(v & 0x07); // Read first 3 bits.
+ if((v >> 3) == 30)
+ {
+ skipSize();
+ }
+ skipOptional(format);
+ }
+ }
+
+ /**
+ * Skip the given number of bytes.
+ *
+ * @param size The number of bytes to skip.
+ **/
+ public void skip(int size)
+ {
+ if(size < 0 || size > _buf.b.remaining())
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ _buf.b.position(_buf.b.position() + size);
+ }
+
+ /**
+ * Skip over a size value.
+ **/
+ public void skipSize()
+ {
+ byte b = readByte();
+ if(b == -1)
+ {
+ skip(4);
+ }
+ }
+
+ /**
+ * Determines the current position in the stream.
+ *
+ * @return The current position.
+ **/
+ public int pos()
+ {
+ return _buf.b.position();
+ }
+
+ /**
+ * Sets the current position in the stream.
+ *
+ * @param n The new position.
+ **/
+ public void pos(int n)
+ {
+ _buf.b.position(n);
+ }
+
+ /**
+ * Determines the current size of the stream.
+ *
+ * @return The current size.
+ **/
+ public int size()
+ {
+ return _buf.size();
+ }
+
+ /**
+ * Determines whether the stream is empty.
+ *
+ * @return True if the internal buffer has no data, false otherwise.
+ **/
+ public boolean isEmpty()
+ {
+ return _buf.empty();
+ }
+
+ private UserException createUserException(String id)
+ {
+ UserException userEx = null;
+
+ try
+ {
+ if(_classResolver != null)
+ {
+ Class<?> c = _classResolver.resolveClass(id);
+ if(c != null)
+ {
+ userEx = (UserException)c.newInstance();
+ }
+ }
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new MarshalException(ex);
+ }
+
+ return userEx;
+ }
+
+ private IceInternal.Instance _instance;
+ private IceInternal.Buffer _buf;
+ private Object _closure;
+ private byte[] _stringBytes; // Reusable array for reading strings.
+ private char[] _stringChars; // Reusable array for reading strings.
+
+ private enum SliceType { NoSlice, ValueSlice, ExceptionSlice }
+
+ abstract private static class EncapsDecoder
+ {
+ EncapsDecoder(InputStream stream, boolean sliceValues, ValueFactoryManager f, ClassResolver cr)
+ {
+ _stream = stream;
+ _sliceValues = sliceValues;
+ _valueFactoryManager = f;
+ _classResolver = cr;
+ _typeIdIndex = 0;
+ _unmarshaledMap = new java.util.TreeMap<Integer, Ice.Object>();
+ }
+
+ abstract void readValue(ReadValueCallback cb);
+ abstract void throwException(UserExceptionFactory factory)
+ throws UserException;
+
+ abstract void startInstance(SliceType type);
+ abstract SlicedData endInstance(boolean preserve);
+ abstract String startSlice();
+ abstract void endSlice();
+ abstract void skipSlice();
+
+ boolean readOptional(int tag, OptionalFormat format)
+ {
+ return false;
+ }
+
+ void readPendingValues()
+ {
+ }
+
+ protected String readTypeId(boolean isIndex)
+ {
+ if(_typeIdMap == null) // Lazy initialization
+ {
+ _typeIdMap = new java.util.TreeMap<Integer, String>();
+ }
+
+ if(isIndex)
+ {
+ int index = _stream.readSize();
+ String typeId = _typeIdMap.get(index);
+ if(typeId == null)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ return typeId;
+ }
+ else
+ {
+ String typeId = _stream.readString();
+ _typeIdMap.put(++_typeIdIndex, typeId);
+ return typeId;
+ }
+ }
+
+ protected Class<?> resolveClass(String typeId)
+ {
+ Class<?> cls = null;
+ if(_typeIdCache == null)
+ {
+ _typeIdCache = new java.util.HashMap<String, Class<?> >(); // Lazy initialization.
+ }
+ else
+ {
+ cls = _typeIdCache.get(typeId);
+ }
+
+ if(cls == EncapsDecoder.class) // Marker for non-existent class.
+ {
+ cls = null;
+ }
+ else if(cls == null)
+ {
+ try
+ {
+ if(_classResolver != null)
+ {
+ cls = _classResolver.resolveClass(typeId);
+ _typeIdCache.put(typeId, cls != null ? cls : EncapsDecoder.class);
+ }
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new NoValueFactoryException("no value factory", typeId, ex);
+ }
+ }
+
+ return cls;
+ }
+
+ protected Ice.Object newInstance(String typeId)
+ {
+ //
+ // Try to find a factory registered for the specific type.
+ //
+ ValueFactory userFactory = _valueFactoryManager.find(typeId);
+ Ice.Object v = null;
+ if(userFactory != null)
+ {
+ v = userFactory.create(typeId);
+ }
+
+ //
+ // If that fails, invoke the default factory if one has been
+ // registered.
+ //
+ if(v == null)
+ {
+ userFactory = _valueFactoryManager.find("");
+ if(userFactory != null)
+ {
+ v = userFactory.create(typeId);
+ }
+ }
+
+ //
+ // Last chance: try to instantiate the class dynamically.
+ //
+ if(v == null)
+ {
+ Class<?> cls = resolveClass(typeId);
+
+ if(cls != null)
+ {
+ try
+ {
+ v = (Ice.Object)cls.newInstance();
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new NoValueFactoryException("no value factory", typeId, ex);
+ }
+ }
+ }
+
+ return v;
+ }
+
+ protected void addPatchEntry(int index, ReadValueCallback cb)
+ {
+ assert(index > 0);
+
+ //
+ // Check if we have already unmarshalled the instance. If that's the case,
+ // just invoke the callback and we're done.
+ //
+ Ice.Object obj = _unmarshaledMap.get(index);
+ if(obj != null)
+ {
+ cb.valueReady(obj);
+ return;
+ }
+
+ if(_patchMap == null) // Lazy initialization
+ {
+ _patchMap = new java.util.TreeMap<Integer, java.util.LinkedList<ReadValueCallback> >();
+ }
+
+ //
+ // Add patch entry if the instance isn't unmarshaled yet,
+ // the callback will be called when the instance is
+ // unmarshaled.
+ //
+ java.util.LinkedList<ReadValueCallback> l = _patchMap.get(index);
+ if(l == null)
+ {
+ //
+ // We have no outstanding instances to be patched for this
+ // index, so make a new entry in the patch map.
+ //
+ l = new java.util.LinkedList<ReadValueCallback>();
+ _patchMap.put(index, l);
+ }
+
+ //
+ // Append a patch entry for this instance.
+ //
+ l.add(cb);
+ }
+
+ protected void unmarshal(int index, Ice.Object v)
+ {
+ //
+ // Add the instance to the map of unmarshaled instances, this must
+ // be done before reading the instances (for circular references).
+ //
+ _unmarshaledMap.put(index, v);
+
+ //
+ // Read the instance.
+ //
+ v.__read(_stream);
+
+ if(_patchMap != null)
+ {
+ //
+ // Patch all instances now that the instance is unmarshaled.
+ //
+ java.util.LinkedList<ReadValueCallback> l = _patchMap.get(index);
+ if(l != null)
+ {
+ assert(l.size() > 0);
+
+ //
+ // Patch all pointers that refer to the instance.
+ //
+ for(ReadValueCallback cb : l)
+ {
+ cb.valueReady(v);
+ }
+
+ //
+ // Clear out the patch map for that index -- there is nothing left
+ // to patch for that index for the time being.
+ //
+ _patchMap.remove(index);
+ }
+ }
+
+ if((_patchMap == null || _patchMap.isEmpty()) && _valueList == null)
+ {
+ try
+ {
+ v.ice_postUnmarshal();
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception raised by ice_postUnmarshal:\n" + IceInternal.Ex.toString(ex);
+ _stream.instance().initializationData().logger.warning(s);
+ }
+ }
+ else
+ {
+ if(_valueList == null) // Lazy initialization
+ {
+ _valueList = new java.util.ArrayList<Ice.Object>();
+ }
+ _valueList.add(v);
+
+ if(_patchMap == null || _patchMap.isEmpty())
+ {
+ //
+ // Iterate over the instance list and invoke ice_postUnmarshal on
+ // each instance. We must do this after all instances have been
+ // unmarshaled in order to ensure that any instance data members
+ // have been properly patched.
+ //
+ for(Ice.Object p : _valueList)
+ {
+ try
+ {
+ p.ice_postUnmarshal();
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception raised by ice_postUnmarshal:\n" + IceInternal.Ex.toString(ex);
+ _stream.instance().initializationData().logger.warning(s);
+ }
+ }
+ _valueList.clear();
+ }
+ }
+ }
+
+ protected final InputStream _stream;
+ protected final boolean _sliceValues;
+ protected ValueFactoryManager _valueFactoryManager;
+ protected ClassResolver _classResolver;
+
+ //
+ // Encapsulation attributes for value unmarshaling.
+ //
+ protected java.util.TreeMap<Integer, java.util.LinkedList<ReadValueCallback> > _patchMap;
+ private java.util.TreeMap<Integer, Ice.Object> _unmarshaledMap;
+ private java.util.TreeMap<Integer, String> _typeIdMap;
+ private int _typeIdIndex;
+ private java.util.List<Ice.Object> _valueList;
+ private java.util.HashMap<String, Class<?> > _typeIdCache;
+ }
+
+ private static final class EncapsDecoder10 extends EncapsDecoder
+ {
+ EncapsDecoder10(InputStream stream, boolean sliceValues, ValueFactoryManager f, ClassResolver cr)
+ {
+ super(stream, sliceValues, f, cr);
+ _sliceType = SliceType.NoSlice;
+ }
+
+ @Override
+ void readValue(ReadValueCallback cb)
+ {
+ assert(cb != null);
+
+ //
+ // Object references are encoded as a negative integer in 1.0.
+ //
+ int index = _stream.readInt();
+ if(index > 0)
+ {
+ throw new MarshalException("invalid object id");
+ }
+ index = -index;
+
+ if(index == 0)
+ {
+ cb.valueReady(null);
+ }
+ else
+ {
+ addPatchEntry(index, cb);
+ }
+ }
+
+ @Override
+ void throwException(UserExceptionFactory factory)
+ throws UserException
+ {
+ assert(_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 instances even if some part of
+ // the exception was sliced.
+ //
+ boolean usesClasses = _stream.readBool();
+
+ _sliceType = SliceType.ExceptionSlice;
+ _skipFirstSlice = false;
+
+ //
+ // Read the first slice header.
+ //
+ startSlice();
+ final String mostDerivedId = _typeId;
+ while(true)
+ {
+ UserException userEx = null;
+
+ //
+ // Use a factory if one was provided.
+ //
+ if(factory != null)
+ {
+ try
+ {
+ factory.createAndThrow(_typeId);
+ }
+ catch(UserException ex)
+ {
+ userEx = ex;
+ }
+ }
+
+ if(userEx == null)
+ {
+ userEx = _stream.createUserException(_typeId);
+ }
+
+ //
+ // We found the exception.
+ //
+ if(userEx != null)
+ {
+ userEx.__read(_stream);
+ if(usesClasses)
+ {
+ readPendingValues();
+ }
+ throw userEx;
+
+ // Never reached.
+ }
+
+ //
+ // Slice off what we don't understand.
+ //
+ skipSlice();
+ try
+ {
+ startSlice();
+ }
+ catch(UnmarshalOutOfBoundsException 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.
+ //
+ ex.reason = "unknown exception type `" + mostDerivedId + "'";
+ throw ex;
+ }
+ }
+ }
+
+ @Override
+ void startInstance(SliceType sliceType)
+ {
+ assert(_sliceType == sliceType);
+ _skipFirstSlice = true;
+ }
+
+ @Override
+ SlicedData endInstance(boolean preserve)
+ {
+ //
+ // Read the Ice::Object slice.
+ //
+ if(_sliceType == SliceType.ValueSlice)
+ {
+ startSlice();
+ int sz = _stream.readSize(); // For compatibility with the old AFM.
+ if(sz != 0)
+ {
+ throw new MarshalException("invalid Object slice");
+ }
+ endSlice();
+ }
+
+ _sliceType = SliceType.NoSlice;
+ return null;
+ }
+
+ @Override
+ String startSlice()
+ {
+ //
+ // If first slice, don't read the header, it was already read in
+ // readInstance or throwException to find the factory.
+ //
+ if(_skipFirstSlice)
+ {
+ _skipFirstSlice = false;
+ return _typeId;
+ }
+
+ //
+ // For class instances, 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(_sliceType == SliceType.ValueSlice) // For exceptions, the type ID is always encoded as a string
+ {
+ boolean isIndex = _stream.readBool();
+ _typeId = readTypeId(isIndex);
+ }
+ else
+ {
+ _typeId = _stream.readString();
+ }
+
+ _sliceSize = _stream.readInt();
+ if(_sliceSize < 4)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+
+ return _typeId;
+ }
+
+ @Override
+ void endSlice()
+ {
+ }
+
+ @Override
+ void skipSlice()
+ {
+ _stream.traceSkipSlice(_typeId, _sliceType);
+ assert(_sliceSize >= 4);
+ _stream.skip(_sliceSize - 4);
+ }
+
+ @Override
+ void readPendingValues()
+ {
+ int num;
+ do
+ {
+ num = _stream.readSize();
+ for(int k = num; k > 0; --k)
+ {
+ readInstance();
+ }
+ }
+ while(num > 0);
+
+ if(_patchMap != null && !_patchMap.isEmpty())
+ {
+ //
+ // 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 MarshalException("index for class received, but no instance");
+ }
+ }
+
+ private void readInstance()
+ {
+ int index = _stream.readInt();
+
+ if(index <= 0)
+ {
+ throw new MarshalException("invalid object id");
+ }
+
+ _sliceType = SliceType.ValueSlice;
+ _skipFirstSlice = false;
+
+ //
+ // Read the first slice header.
+ //
+ startSlice();
+ final String mostDerivedId = _typeId;
+ Ice.Object v = null;
+ while(true)
+ {
+ //
+ // For the 1.0 encoding, the type ID for the base Object class
+ // marks the last slice.
+ //
+ if(_typeId.equals(ObjectImpl.ice_staticId()))
+ {
+ throw new NoValueFactoryException("", mostDerivedId);
+ }
+
+ v = newInstance(_typeId);
+
+ //
+ // We found a factory, we get out of this loop.
+ //
+ if(v != null)
+ {
+ break;
+ }
+
+ //
+ // If slicing is disabled, stop unmarshaling.
+ //
+ if(!_sliceValues)
+ {
+ throw new NoValueFactoryException("no value factory found and slicing is disabled", _typeId);
+ }
+
+ //
+ // Slice off what we don't understand.
+ //
+ skipSlice();
+ startSlice(); // Read next Slice header for next iteration.
+ }
+
+ //
+ // Unmarshal the instance and add it to the map of unmarshaled instances.
+ //
+ unmarshal(index, v);
+ }
+
+ // Value/exception attributes
+ private SliceType _sliceType;
+ private boolean _skipFirstSlice;
+
+ // Slice attributes
+ private int _sliceSize;
+ private String _typeId;
+ }
+
+ private static class EncapsDecoder11 extends EncapsDecoder
+ {
+ EncapsDecoder11(InputStream stream, boolean sliceValues, ValueFactoryManager f, ClassResolver cr,
+ CompactIdResolver r)
+ {
+ super(stream, sliceValues, f, cr);
+ _compactIdResolver = r;
+ _current = null;
+ _valueIdIndex = 1;
+ }
+
+ @Override
+ void readValue(ReadValueCallback cb)
+ {
+ int index = _stream.readSize();
+ if(index < 0)
+ {
+ throw new MarshalException("invalid object id");
+ }
+ else if(index == 0)
+ {
+ if(cb != null)
+ {
+ cb.valueReady(null);
+ }
+ }
+ else if(_current != null && (_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_INDIRECTION_TABLE) != 0)
+ {
+ //
+ // When reading a class instance within a slice and there's an
+ // indirect instance table, always read an indirect reference
+ // that points to an instance from the indirect instance 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(cb != null)
+ {
+ if(_current.indirectPatchList == null) // Lazy initialization
+ {
+ _current.indirectPatchList = new java.util.ArrayDeque<IndirectPatchEntry>();
+ }
+ IndirectPatchEntry e = new IndirectPatchEntry();
+ e.index = index - 1;
+ e.cb = cb;
+ _current.indirectPatchList.push(e);
+ }
+ }
+ else
+ {
+ readInstance(index, cb);
+ }
+ }
+
+ @Override
+ void throwException(UserExceptionFactory factory)
+ throws UserException
+ {
+ assert(_current == null);
+
+ push(SliceType.ExceptionSlice);
+
+ //
+ // Read the first slice header.
+ //
+ startSlice();
+ final String mostDerivedId = _current.typeId;
+ while(true)
+ {
+ UserException userEx = null;
+
+ //
+ // Use a factory if one was provided.
+ //
+ if(factory != null)
+ {
+ try
+ {
+ factory.createAndThrow(_current.typeId);
+ }
+ catch(UserException ex)
+ {
+ userEx = ex;
+ }
+ }
+
+ if(userEx == null)
+ {
+ userEx = _stream.createUserException(_current.typeId);
+ }
+
+ //
+ // We found the exception.
+ //
+ if(userEx != null)
+ {
+ userEx.__read(_stream);
+ throw userEx;
+
+ // Never reached.
+ }
+
+ //
+ // Slice off what we don't understand.
+ //
+ skipSlice();
+
+ if((_current.sliceFlags & IceInternal.Protocol.FLAG_IS_LAST_SLICE) != 0)
+ {
+ if(mostDerivedId.startsWith("::"))
+ {
+ throw new UnknownUserException(mostDerivedId.substring(2));
+ }
+ else
+ {
+ throw new UnknownUserException(mostDerivedId);
+ }
+ }
+
+ startSlice();
+ }
+ }
+
+ @Override
+ void startInstance(SliceType sliceType)
+ {
+ assert(_current.sliceType == sliceType);
+ _current.skipFirstSlice = true;
+ }
+
+ @Override
+ SlicedData endInstance(boolean preserve)
+ {
+ SlicedData slicedData = null;
+ if(preserve)
+ {
+ slicedData = readSlicedData();
+ }
+ if(_current.slices != null)
+ {
+ _current.slices.clear();
+ _current.indirectionTables.clear();
+ }
+ _current = _current.previous;
+ return slicedData;
+ }
+
+ @Override
+ String startSlice()
+ {
+ //
+ // If first slice, don't read the header, it was already read in
+ // readInstance or throwException to find the factory.
+ //
+ if(_current.skipFirstSlice)
+ {
+ _current.skipFirstSlice = false;
+ return _current.typeId;
+ }
+
+ _current.sliceFlags = _stream.readByte();
+
+ //
+ // Read the type ID, for value slices the type ID is encoded as a
+ // string or as an index, for exceptions it's always encoded as a
+ // string.
+ //
+ if(_current.sliceType == SliceType.ValueSlice)
+ {
+ if((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_TYPE_ID_COMPACT) ==
+ IceInternal.Protocol.FLAG_HAS_TYPE_ID_COMPACT) // Must be checked 1st!
+ {
+ _current.typeId = "";
+ _current.compactId = _stream.readSize();
+ }
+ else if((_current.sliceFlags & (IceInternal.Protocol.FLAG_HAS_TYPE_ID_INDEX |
+ IceInternal.Protocol.FLAG_HAS_TYPE_ID_STRING)) != 0)
+ {
+ _current.typeId =
+ readTypeId((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_TYPE_ID_INDEX) != 0);
+ _current.compactId = -1;
+ }
+ else
+ {
+ //
+ // Only the most derived slice encodes the type ID for the compact format.
+ //
+ _current.typeId = "";
+ _current.compactId = -1;
+ }
+ }
+ else
+ {
+ _current.typeId = _stream.readString();
+ _current.compactId = -1;
+ }
+
+ //
+ // Read the slice size if necessary.
+ //
+ if((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_SLICE_SIZE) != 0)
+ {
+ _current.sliceSize = _stream.readInt();
+ if(_current.sliceSize < 4)
+ {
+ throw new UnmarshalOutOfBoundsException();
+ }
+ }
+ else
+ {
+ _current.sliceSize = 0;
+ }
+
+ return _current.typeId;
+ }
+
+ @Override
+ void endSlice()
+ {
+ if((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_OPTIONAL_MEMBERS) != 0)
+ {
+ _stream.skipOptionals();
+ }
+
+ //
+ // Read the indirection table if one is present and transform the
+ // indirect patch list into patch entries with direct references.
+ //
+ if((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_INDIRECTION_TABLE) != 0)
+ {
+ //
+ // The table is written as a sequence<size> to conserve space.
+ //
+ int[] indirectionTable = new int[_stream.readAndCheckSeqSize(1)];
+ for(int i = 0; i < indirectionTable.length; ++i)
+ {
+ indirectionTable[i] = readInstance(_stream.readSize(), null);
+ }
+
+ //
+ // Sanity checks. If there are optional members, it's possible
+ // that not all instance references were read if they are from
+ // unknown optional data members.
+ //
+ if(indirectionTable.length == 0)
+ {
+ throw new MarshalException("empty indirection table");
+ }
+ if((_current.indirectPatchList == null || _current.indirectPatchList.isEmpty()) &&
+ (_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_OPTIONAL_MEMBERS) == 0)
+ {
+ throw new MarshalException("no references to indirection table");
+ }
+
+ //
+ // Convert indirect references into direct references.
+ //
+ if(_current.indirectPatchList != null)
+ {
+ for(IndirectPatchEntry e : _current.indirectPatchList)
+ {
+ assert(e.index >= 0);
+ if(e.index >= indirectionTable.length)
+ {
+ throw new MarshalException("indirection out of range");
+ }
+ addPatchEntry(indirectionTable[e.index], e.cb);
+ }
+ _current.indirectPatchList.clear();
+ }
+ }
+ }
+
+ @Override
+ void skipSlice()
+ {
+ _stream.traceSkipSlice(_current.typeId, _current.sliceType);
+
+ int start = _stream.pos();
+
+ if((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_SLICE_SIZE) != 0)
+ {
+ assert(_current.sliceSize >= 4);
+ _stream.skip(_current.sliceSize - 4);
+ }
+ else
+ {
+ if(_current.sliceType == SliceType.ValueSlice)
+ {
+ throw new NoValueFactoryException("no value factory found and compact format prevents " +
+ "slicing (the sender should use the sliced format instead)",
+ _current.typeId);
+ }
+ else
+ {
+ if(_current.typeId.startsWith("::"))
+ {
+ throw new UnknownUserException(_current.typeId.substring(2));
+ }
+ else
+ {
+ throw new UnknownUserException(_current.typeId);
+ }
+ }
+ }
+
+ //
+ // Preserve this slice.
+ //
+ SliceInfo info = new SliceInfo();
+ info.typeId = _current.typeId;
+ info.compactId = _current.compactId;
+ info.hasOptionalMembers = (_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_OPTIONAL_MEMBERS) != 0;
+ info.isLastSlice = (_current.sliceFlags & IceInternal.Protocol.FLAG_IS_LAST_SLICE) != 0;
+ java.nio.ByteBuffer b = _stream.getBuffer().b;
+ final int end = b.position();
+ int 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;
+ }
+ info.bytes = new byte[dataEnd - start];
+ b.position(start);
+ b.get(info.bytes);
+ b.position(end);
+
+ if(_current.slices == null) // Lazy initialization
+ {
+ _current.slices = new java.util.ArrayList<SliceInfo>();
+ _current.indirectionTables = new java.util.ArrayList<int[]>();
+ }
+
+ //
+ // Read the indirect instance table. We read the instances or their
+ // IDs if the instance is a reference to an already unmarhsaled
+ // instance.
+ //
+ // The SliceInfo object sequence is initialized only if
+ // readSlicedData is called.
+ //
+
+ if((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_INDIRECTION_TABLE) != 0)
+ {
+ int[] indirectionTable = new int[_stream.readAndCheckSeqSize(1)];
+ for(int i = 0; i < indirectionTable.length; ++i)
+ {
+ indirectionTable[i] = readInstance(_stream.readSize(), null);
+ }
+ _current.indirectionTables.add(indirectionTable);
+ }
+ else
+ {
+ _current.indirectionTables.add(null);
+ }
+
+ _current.slices.add(info);
+ }
+
+ @Override
+ boolean readOptional(int readTag, OptionalFormat expectedFormat)
+ {
+ if(_current == null)
+ {
+ return _stream.readOptImpl(readTag, expectedFormat);
+ }
+ else if((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_OPTIONAL_MEMBERS) != 0)
+ {
+ return _stream.readOptImpl(readTag, expectedFormat);
+ }
+ return false;
+ }
+
+ private int readInstance(int index, ReadValueCallback cb)
+ {
+ assert(index > 0);
+
+ if(index > 1)
+ {
+ if(cb != null)
+ {
+ addPatchEntry(index, cb);
+ }
+ return index;
+ }
+
+ push(SliceType.ValueSlice);
+
+ //
+ // Get the instance ID before we start reading slices. If some
+ // slices are skipped, the indirect instance table is still read and
+ // might read other instances.
+ //
+ index = ++_valueIdIndex;
+
+ //
+ // Read the first slice header.
+ //
+ startSlice();
+ final String mostDerivedId = _current.typeId;
+ Ice.Object v = null;
+ while(true)
+ {
+ boolean updateCache = false;
+
+ if(_current.compactId >= 0)
+ {
+ updateCache = true;
+
+ //
+ // Translate a compact (numeric) type ID into a class.
+ //
+ if(_compactIdCache == null)
+ {
+ _compactIdCache = new java.util.TreeMap<Integer, Class<?> >(); // Lazy initialization.
+ }
+ else
+ {
+ //
+ // Check the cache to see if we've already translated the compact type ID into a class.
+ //
+ Class<?> cls = _compactIdCache.get(_current.compactId);
+ if(cls != null)
+ {
+ try
+ {
+ v = (Ice.Object)cls.newInstance();
+ updateCache = false;
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new NoValueFactoryException("no value factory", "compact ID " +
+ _current.compactId, ex);
+ }
+ }
+ }
+
+ //
+ // If we haven't already cached a class for the compact ID, then try to translate the
+ // compact ID into a type ID.
+ //
+ if(v == null)
+ {
+ _current.typeId = "";
+ if(_compactIdResolver != null)
+ {
+ try
+ {
+ _current.typeId = _compactIdResolver.resolve(_current.compactId);
+ }
+ catch(Ice.LocalException ex)
+ {
+ throw ex;
+ }
+ catch(Throwable ex)
+ {
+ throw new Ice.MarshalException("exception in CompactIdResolver for ID " +
+ _current.compactId, ex);
+ }
+ }
+
+ if(_current.typeId.isEmpty())
+ {
+ _current.typeId = _stream.instance().resolveCompactId(_current.compactId);
+ }
+ }
+ }
+
+ if(v == null && !_current.typeId.isEmpty())
+ {
+ v = newInstance(_current.typeId);
+ }
+
+ if(v != null)
+ {
+ if(updateCache)
+ {
+ assert(_current.compactId >= 0);
+ _compactIdCache.put(_current.compactId, v.getClass());
+ }
+
+ //
+ // We have an instance, get out of this loop.
+ //
+ break;
+ }
+
+ //
+ // If slicing is disabled, stop unmarshaling.
+ //
+ if(!_sliceValues)
+ {
+ throw new NoValueFactoryException("no value factory found and slicing is disabled",
+ _current.typeId);
+ }
+
+ //
+ // Slice off what we don't understand.
+ //
+ skipSlice();
+
+ //
+ // If this is the last slice, keep the instance as an opaque
+ // UnknownSlicedValue object.
+ //
+ if((_current.sliceFlags & IceInternal.Protocol.FLAG_IS_LAST_SLICE) != 0)
+ {
+ //
+ // Provide a factory with an opportunity to supply the instance.
+ // We pass the "::Ice::Object" ID to indicate that this is the
+ // last chance to preserve the instance.
+ //
+ v = newInstance(ObjectImpl.ice_staticId());
+ if(v == null)
+ {
+ v = new UnknownSlicedValue(mostDerivedId);
+ }
+
+ break;
+ }
+
+ startSlice(); // Read next Slice header for next iteration.
+ }
+
+ //
+ // Unmarshal the instance.
+ //
+ unmarshal(index, v);
+
+ if(_current == null && _patchMap != null && !_patchMap.isEmpty())
+ {
+ //
+ // If any entries remain in the patch map, the sender has sent an index for an instance, but failed
+ // to supply the instance.
+ //
+ throw new MarshalException("index for class received, but no instance");
+ }
+
+ if(cb != null)
+ {
+ cb.valueReady(v);
+ }
+
+ return index;
+ }
+
+ private SlicedData readSlicedData()
+ {
+ if(_current.slices == null) // No preserved slices.
+ {
+ return null;
+ }
+
+ //
+ // The _indirectionTables member holds the indirection table for each slice
+ // in _slices.
+ //
+ assert(_current.slices.size() == _current.indirectionTables.size());
+ for(int n = 0; n < _current.slices.size(); ++n)
+ {
+ //
+ // We use the "instances" list in SliceInfo to hold references
+ // to the target instances. Note that the instances might not have
+ // been read yet in the case of a circular reference to an
+ // enclosing instance.
+ //
+ final int[] table = _current.indirectionTables.get(n);
+ SliceInfo info = _current.slices.get(n);
+ info.instances = new Ice.Object[table != null ? table.length : 0];
+ for(int j = 0; j < info.instances.length; ++j)
+ {
+ addPatchEntry(table[j], new IceInternal.SequencePatcher(info.instances, Ice.Object.class, j));
+ }
+ }
+
+ SliceInfo[] arr = new SliceInfo[_current.slices.size()];
+ _current.slices.toArray(arr);
+ return new SlicedData(arr);
+ }
+
+ private void push(SliceType sliceType)
+ {
+ if(_current == null)
+ {
+ _current = new InstanceData(null);
+ }
+ else
+ {
+ _current = _current.next == null ? new InstanceData(_current) : _current.next;
+ }
+ _current.sliceType = sliceType;
+ _current.skipFirstSlice = false;
+ }
+
+ private static final class IndirectPatchEntry
+ {
+ int index;
+ ReadValueCallback cb;
+ }
+
+ private static final class InstanceData
+ {
+ InstanceData(InstanceData previous)
+ {
+ if(previous != null)
+ {
+ previous.next = this;
+ }
+ this.previous = previous;
+ this.next = null;
+ }
+
+ // Instance attributes
+ SliceType sliceType;
+ boolean skipFirstSlice;
+ java.util.List<SliceInfo> slices; // Preserved slices.
+ java.util.List<int[]> indirectionTables;
+
+ // Slice attributes
+ byte sliceFlags;
+ int sliceSize;
+ String typeId;
+ int compactId;
+ java.util.Deque<IndirectPatchEntry> indirectPatchList;
+
+ final InstanceData previous;
+ InstanceData next;
+ }
+
+ private CompactIdResolver _compactIdResolver;
+ private InstanceData _current;
+ private int _valueIdIndex; // The ID of the next instance to unmarshal.
+ private java.util.TreeMap<Integer, Class<?> > _compactIdCache; // Cache of compact type IDs.
+ }
+
+ private static final class Encaps
+ {
+ void reset()
+ {
+ decoder = null;
+ }
+
+ void setEncoding(EncodingVersion encoding)
+ {
+ this.encoding = encoding;
+ encoding_1_0 = encoding.equals(Util.Encoding_1_0);
+ }
+
+ int start;
+ int sz;
+ EncodingVersion encoding;
+ boolean encoding_1_0;
+
+ EncapsDecoder decoder;
+
+ Encaps next;
+ }
+
+ //
+ // The encoding version to use when there's no encapsulation to
+ // read from. This is for example used to read message headers.
+ //
+ private EncodingVersion _encoding;
+
+ private boolean isEncoding_1_0()
+ {
+ return _encapsStack != null ? _encapsStack.encoding_1_0 : _encoding.equals(Util.Encoding_1_0);
+ }
+
+ private Encaps _encapsStack;
+ private Encaps _encapsCache;
+
+ private void initEncaps()
+ {
+ if(_encapsStack == null) // Lazy initialization
+ {
+ _encapsStack = _encapsCache;
+ if(_encapsStack != null)
+ {
+ _encapsCache = _encapsCache.next;
+ }
+ else
+ {
+ _encapsStack = new Encaps();
+ }
+ _encapsStack.setEncoding(_encoding);
+ _encapsStack.sz = _buf.b.limit();
+ }
+
+ if(_encapsStack.decoder == null) // Lazy initialization.
+ {
+ if(_encapsStack.encoding_1_0)
+ {
+ _encapsStack.decoder = new EncapsDecoder10(this, _sliceValues, _valueFactoryManager, _classResolver);
+ }
+ else
+ {
+ _encapsStack.decoder = new EncapsDecoder11(this, _sliceValues, _valueFactoryManager, _classResolver,
+ _compactIdResolver);
+ }
+ }
+ }
+
+ private void traceSkipSlice(String typeId, SliceType sliceType)
+ {
+ if(_traceSlicing && _logger != null)
+ {
+ IceInternal.TraceUtil.traceSlicing(sliceType == SliceType.ExceptionSlice ? "exception" : "object", typeId,
+ "Slicing", _logger);
+ }
+ }
+
+ private boolean _sliceValues;
+ private boolean _traceSlicing;
+
+ private int _startSeq;
+ private int _minSeqSize;
+
+ private ValueFactoryManager _valueFactoryManager;
+ private Logger _logger;
+ private CompactIdResolver _compactIdResolver;
+ private ClassResolver _classResolver;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/IntHolder.java b/java-compat/src/Ice/src/main/java/Ice/IntHolder.java
new file mode 100644
index 00000000000..c79285985d6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/IntHolder.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for integers that are out- or inout-parameters.
+ **/
+public final class IntHolder extends Holder<Integer>
+{
+ /**
+ * Instantiates the class with the value zero.
+ **/
+ public
+ IntHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed value.
+ *
+ * The <code>int</code> value for this holder.
+ **/
+ public
+ IntHolder(int value)
+ {
+ super(value);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/IntOptional.java b/java-compat/src/Ice/src/main/java/Ice/IntOptional.java
new file mode 100644
index 00000000000..825ae76b1d7
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/IntOptional.java
@@ -0,0 +1,106 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Manages an optional int parameter.
+ **/
+public class IntOptional
+{
+ /**
+ * The value defaults to unset.
+ **/
+ public IntOptional()
+ {
+ _isSet = false;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The initial value.
+ **/
+ public IntOptional(int v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * Sets the value to a shallow copy of the given optional.
+ *
+ * @param opt The source value.
+ **/
+ public IntOptional(IntOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Obtains the current value.
+ *
+ * @return The current value.
+ * @throws IllegalStateException If the value is not set.
+ **/
+ public int get()
+ {
+ if(!_isSet)
+ {
+ throw new IllegalStateException("no value is set");
+ }
+ return _value;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The new value.
+ **/
+ public void set(int v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * If the given argument is set, this optional is set to a shallow copy of the argument,
+ * otherwise this optional is unset.
+ *
+ * @param opt The source value.
+ **/
+ public void set(IntOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Determines whether the value is set.
+ *
+ * @return True if the value is set, false otherwise.
+ **/
+ public boolean isSet()
+ {
+ return _isSet;
+ }
+
+ /**
+ * Unsets this value.
+ **/
+ public void clear()
+ {
+ _isSet = false;
+ _value = 0;
+ }
+
+ private int _value;
+ private boolean _isSet;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/LocalException.java b/java-compat/src/Ice/src/main/java/Ice/LocalException.java
new file mode 100644
index 00000000000..2052b64a0c7
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/LocalException.java
@@ -0,0 +1,25 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class for all Ice run-time exceptions.
+ **/
+public abstract class LocalException extends Exception
+{
+ public LocalException()
+ {
+ }
+
+ public LocalException(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/LocalObjectHolder.java b/java-compat/src/Ice/src/main/java/Ice/LocalObjectHolder.java
new file mode 100644
index 00000000000..704aa31b234
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/LocalObjectHolder.java
@@ -0,0 +1,33 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for local objects that are out- or inout-parameters.
+ **/
+public final class LocalObjectHolder extends Holder<java.lang.Object>
+{
+ /**
+ * Instantiates the class with a <code>null</code> value.
+ **/
+ public
+ LocalObjectHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed local object.
+ **/
+ public
+ LocalObjectHolder(java.lang.Object value)
+ {
+ super(value);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/LoggerI.java b/java-compat/src/Ice/src/main/java/Ice/LoggerI.java
new file mode 100644
index 00000000000..a1108e6df55
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/LoggerI.java
@@ -0,0 +1,163 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public class LoggerI implements Logger
+{
+ public
+ LoggerI(String prefix, String file)
+ {
+ _prefix = prefix;
+
+ if(prefix.length() > 0)
+ {
+ _formattedPrefix = prefix + ": ";
+ }
+
+ _lineSeparator = System.getProperty("line.separator");
+ _date = java.text.DateFormat.getDateInstance(java.text.DateFormat.SHORT);
+ _time = new java.text.SimpleDateFormat(" HH:mm:ss:SSS");
+
+ if(file.length() != 0)
+ {
+ _file = file;
+ try
+ {
+ _out = new java.io.FileOutputStream(new java.io.File(_file), true);
+ }
+ catch(java.io.FileNotFoundException ex)
+ {
+ throw new InitializationException("FileLogger: cannot open " + _file);
+ }
+ }
+ }
+
+ @Override
+ public void
+ print(String message)
+ {
+ StringBuilder s = new StringBuilder(256);
+ s.append(message);
+ write(s, false);
+ }
+
+ @Override
+ public void
+ trace(String category, String message)
+ {
+ StringBuilder s = new StringBuilder(256);
+ s.append("-- ");
+ synchronized(this)
+ {
+ java.util.Date date = new java.util.Date();
+ s.append(_date.format(date));
+ s.append(_time.format(date));
+ }
+ s.append(' ');
+ s.append(_formattedPrefix);
+ s.append(category);
+ s.append(": ");
+ s.append(message);
+ write(s, true);
+ }
+
+ @Override
+ public void
+ warning(String message)
+ {
+ StringBuilder s = new StringBuilder(256);
+ s.append("-! ");
+ synchronized(this)
+ {
+ s.append(_date.format(new java.util.Date()));
+ s.append(_time.format(new java.util.Date()));
+ }
+ s.append(' ');
+ s.append(_formattedPrefix);
+ s.append("warning: ");
+ s.append(Thread.currentThread().getName());
+ s.append(": ");
+ s.append(message);
+ write(s, true);
+ }
+
+ @Override
+ public void
+ error(String message)
+ {
+ StringBuilder s = new StringBuilder(256);
+ s.append("!! ");
+ synchronized(this)
+ {
+ s.append(_date.format(new java.util.Date()));
+ s.append(_time.format(new java.util.Date()));
+ }
+ s.append(' ');
+ s.append(_formattedPrefix);
+ s.append("error: ");
+ s.append(Thread.currentThread().getName());
+ s.append(": ");
+ s.append(message);
+ write(s, true);
+ }
+
+
+ @Override
+ public String
+ getPrefix()
+ {
+ return _prefix;
+ }
+
+ @Override
+ public Logger
+ cloneWithPrefix(String prefix)
+ {
+ return new LoggerI(prefix, _file);
+ }
+
+ private void
+ write(StringBuilder message, boolean indent)
+ {
+ if(indent)
+ {
+ int idx = 0;
+ while((idx = message.indexOf("\n", idx)) != -1)
+ {
+ message.insert(idx + 1, " ");
+ ++idx;
+ }
+ }
+ message.append(_lineSeparator);
+
+ if(_out == null)
+ {
+ System.err.print(message.toString());
+ }
+ else
+ {
+ try
+ {
+ _out.write(message.toString().getBytes());
+ }
+ catch(java.io.IOException ex)
+ {
+ }
+ }
+ }
+
+ String _prefix = "";
+ String _formattedPrefix = "";
+ String _file = "";
+ String _lineSeparator;
+ java.text.DateFormat _date;
+ java.text.SimpleDateFormat _time;
+ java.io.FileOutputStream _out = null;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/LoggerPlugin.java b/java-compat/src/Ice/src/main/java/Ice/LoggerPlugin.java
new file mode 100644
index 00000000000..90af9141202
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/LoggerPlugin.java
@@ -0,0 +1,70 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Class to support custom loggers. Applications using a custom logger
+ * instantiate a <code>LoggerPlugin</code> with a custom logger and
+ * return the instance from their {@link PluginFactory} implementation.
+ *
+ * @see PluginFactory
+ * @see Plugin
+ **/
+public class LoggerPlugin implements Ice.Plugin
+{
+ /**
+ * Installs a custom logger for a communicator.
+ *
+ * @param communicator The communicator using the custom logger.
+ * @param logger The custom logger for the communicator.
+ **/
+ public
+ LoggerPlugin(Communicator communicator, Logger logger)
+ {
+ if(communicator == null)
+ {
+ PluginInitializationException ex = new PluginInitializationException();
+ ex.reason = "Communicator cannot be null";
+ throw ex;
+ }
+
+ if(logger == null)
+ {
+ PluginInitializationException ex = new PluginInitializationException();
+ ex.reason = "Logger cannot be null";
+ throw ex;
+ }
+
+ IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ instance.setLogger(logger);
+ }
+
+ /**
+ * Called by the Ice run time during communicator initialization. The derived class
+ * can override this method to perform any initialization that might be required
+ * by a custom logger.
+ **/
+ @Override
+ public void
+ initialize()
+ {
+ }
+
+ /**
+ * Called by the Ice run time when the communicator is destroyed. The derived class
+ * can override this method to perform any finalization that might be required
+ * by a custom logger.
+ **/
+ @Override
+ public void
+ destroy()
+ {
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/LongHolder.java b/java-compat/src/Ice/src/main/java/Ice/LongHolder.java
new file mode 100644
index 00000000000..6027d071be6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/LongHolder.java
@@ -0,0 +1,33 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for longs that are out- or inout-parameters.
+ **/
+public final class LongHolder extends Holder<Long>
+{
+ /**
+ * Instantiates the class with the value zero.
+ **/
+ public
+ LongHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed value.
+ **/
+ public
+ LongHolder(long value)
+ {
+ super(value);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/LongOptional.java b/java-compat/src/Ice/src/main/java/Ice/LongOptional.java
new file mode 100644
index 00000000000..e7301ae8dc6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/LongOptional.java
@@ -0,0 +1,106 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Manages an optional long parameter.
+ **/
+public class LongOptional
+{
+ /**
+ * The value defaults to unset.
+ **/
+ public LongOptional()
+ {
+ _isSet = false;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The initial value.
+ **/
+ public LongOptional(long v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * Sets the value to a shallow copy of the given optional.
+ *
+ * @param opt The source value.
+ **/
+ public LongOptional(LongOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Obtains the current value.
+ *
+ * @return The current value.
+ * @throws IllegalStateException If the value is not set.
+ **/
+ public long get()
+ {
+ if(!_isSet)
+ {
+ throw new IllegalStateException("no value is set");
+ }
+ return _value;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The new value.
+ **/
+ public void set(long v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * If the given argument is set, this optional is set to a shallow copy of the argument,
+ * otherwise this optional is unset.
+ *
+ * @param opt The source value.
+ **/
+ public void set(LongOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Determines whether the value is set.
+ *
+ * @return True if the value is set, false otherwise.
+ **/
+ public boolean isSet()
+ {
+ return _isSet;
+ }
+
+ /**
+ * Unsets this value.
+ **/
+ public void clear()
+ {
+ _isSet = false;
+ _value = 0;
+ }
+
+ private long _value;
+ private boolean _isSet;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/NativePropertiesAdmin.java b/java-compat/src/Ice/src/main/java/Ice/NativePropertiesAdmin.java
new file mode 100644
index 00000000000..1e5df346592
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/NativePropertiesAdmin.java
@@ -0,0 +1,16 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface NativePropertiesAdmin
+{
+ void addUpdateCallback(PropertiesAdminUpdateCallback callback);
+ void removeUpdateCallback(PropertiesAdminUpdateCallback callback);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Object.java b/java-compat/src/Ice/src/main/java/Ice/Object.java
new file mode 100644
index 00000000000..e83fc29756f
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Object.java
@@ -0,0 +1,162 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * The base interface for servants.
+ **/
+public interface Object
+{
+ /**
+ * Returns a copy of the object. The cloned object contains field-for-field copies
+ * of the state.
+ *
+ * @return The cloned object.
+ **/
+ Object clone() throws java.lang.CloneNotSupportedException;
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param s The type ID of the Slice interface to test against.
+ * @return <code>true</code> if this object has the interface
+ * specified by <code>s</code> or derives from the interface
+ * specified by <code>s</code>.
+ **/
+ boolean ice_isA(String s);
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param s The type ID of the Slice interface to test against.
+ * @param current The {@link Current} object for the invocation.
+ * @return <code>true</code> if this object has the interface
+ * specified by <code>s</code> or derives from the interface
+ * specified by <code>s</code>.
+ **/
+ boolean ice_isA(String s, Current current);
+
+ /**
+ * Tests whether this object can be reached.
+ **/
+ void ice_ping();
+
+ /**
+ * Tests whether this object can be reached.
+ *
+ * @param current The {@link Current} object for the invocation.
+ **/
+ void ice_ping(Current current);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by this object.
+ *
+ * @return The Slice type IDs of the interfaces supported by this object, in base-to-derived
+ * order. The first element of the returned array is always <code>::Ice::Object</code>.
+ **/
+ String[] ice_ids();
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by this object.
+ *
+ * @param current The {@link Current} object for the invocation.
+ * @return The Slice type IDs of the interfaces supported by this object, in base-to-derived
+ * order. The first element of the returned array is always <code>::Ice::Object</code>.
+ **/
+ String[] ice_ids(Current current);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by this object.
+ *
+ * @return The Slice type ID of the most-derived interface.
+ **/
+ String ice_id();
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by this object.
+ *
+ * @param current The {@link Current} object for the invocation.
+ * @return The Slice type ID of the most-derived interface.
+ **/
+ String ice_id(Current current);
+
+ /**
+ * Returns the Freeze metadata attributes for an operation.
+ *
+ * @param operation The name of the operation.
+ * @return The least significant bit indicates whether the operation is a read
+ * or write operation. If the bit is set, the operation is a write operation.
+ * The expression <code>ice_operationAttributes("op") & 0x1</code> is true if
+ * the operation has a <code>["freeze:write"]</code> metadata directive.
+ * <p>
+ * The second- and third least significant bit indicate the transactional mode
+ * of the operation. The expression <code>ice_operationAttributes("op") & 0x6 >> 1</code>
+ * indicates the transactional mode as follows:
+ * <dl>
+ * <dt>0</dt>
+ * <dd><code>["freeze:read:supports"]</code></dd>
+ * <dt>1</dt>
+ * <dd><code>["freeze:read:mandatory"]</code> or <code>["freeze:write:mandatory"]</code></dd>
+ * <dt>2</dt>
+ * <dd><code>["freeze:read:required"]</code> or <code>["freeze:write:required"]</code></dd>
+ * <dt>3</dt>
+ * <dd><code>["freeze:read:never"]</code></dd>
+ * </dl>
+ *
+ * Refer to the Freeze manual for more information on the TransactionalEvictor.
+ **/
+ int ice_operationAttributes(String operation);
+
+ /**
+ * The Ice run time invokes this method prior to marshaling an object's data members. This allows a subclass
+ * to override this method in order to validate its data members.
+ **/
+ void ice_preMarshal();
+
+ /**
+ * The Ice run time invokes this method vafter unmarshaling an object's data members. This allows a
+ * subclass to override this method in order to perform additional initialization.
+ **/
+ void ice_postUnmarshal();
+
+ /**
+ * Dispatches an invocation to a servant. This method is used by dispatch interceptors to forward an invocation
+ * to a servant (or to another interceptor).
+ *
+ * @param request The details of the invocation.
+ * @param cb The callback object for asynchronous dispatch. For synchronous dispatch, the callback object
+ * must be <code>null</code>.
+ * @return The dispatch status for the operation.
+ *
+ * @see DispatchInterceptor
+ * @see DispatchInterceptorAsyncCallback
+ * @see DispatchStatus
+ **/
+ DispatchStatus ice_dispatch(Request request, DispatchInterceptorAsyncCallback cb);
+
+ /**
+ * Dispatches an invocation to a servant. This method is used by dispatch interceptors to forward an invocation
+ * to a servant (or to another interceptor).
+ *
+ * @param request The details of the invocation.
+ * @return The dispatch status for the operation.
+ *
+ * @see DispatchInterceptor
+ * @see DispatchStatus
+ **/
+ DispatchStatus ice_dispatch(Request request);
+
+ DispatchStatus __dispatch(IceInternal.Incoming in, Current current);
+
+ void __write(OutputStream __os);
+ void __read(InputStream __is);
+
+ public static final String ice_staticId = "::Ice::Object";
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java b/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java
new file mode 100644
index 00000000000..1aeef2206fa
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java
@@ -0,0 +1,1559 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+import IceInternal.IncomingConnectionFactory;
+
+public final class ObjectAdapterI implements ObjectAdapter
+{
+ @Override
+ public String
+ getName()
+ {
+ //
+ // No mutex lock necessary, _name is immutable.
+ //
+ return _noConfig ? "" : _name;
+ }
+
+ @Override
+ public Communicator
+ getCommunicator()
+ {
+ return _communicator;
+ }
+
+ @Override
+ public void
+ activate()
+ {
+ IceInternal.LocatorInfo locatorInfo = null;
+ boolean printAdapterReady = false;
+
+ synchronized(this)
+ {
+ checkForDeactivation();
+
+ //
+ // If we've previously been initialized we just need to activate the
+ // incoming connection factories and we're done.
+ //
+ if(_state != StateUninitialized)
+ {
+ for(IncomingConnectionFactory factory : _incomingConnectionFactories)
+ {
+ factory.activate();
+ }
+ return;
+ }
+
+ //
+ // One off initializations of the adapter: update the
+ // locator registry and print the "adapter ready"
+ // message. We set set state to StateActivating to prevent
+ // deactivation from other threads while these one off
+ // initializations are done.
+ //
+ _state = StateActivating;
+
+ locatorInfo = _locatorInfo;
+ if(!_noConfig)
+ {
+ final Properties properties = _instance.initializationData().properties;
+ printAdapterReady = properties.getPropertyAsInt("Ice.PrintAdapterReady") > 0;
+ }
+ }
+
+ try
+ {
+ Ice.Identity dummy = new Ice.Identity();
+ dummy.name = "dummy";
+ updateLocatorRegistry(locatorInfo, createDirectProxy(dummy));
+ }
+ catch(Ice.LocalException ex)
+ {
+ //
+ // If we couldn't update the locator registry, we let the
+ // exception go through and don't activate the adapter to
+ // allow to user code to retry activating the adapter
+ // later.
+ //
+ synchronized(this)
+ {
+ _state = StateUninitialized;
+ notifyAll();
+ }
+ throw ex;
+ }
+
+ if(printAdapterReady)
+ {
+ System.out.println(_name + " ready");
+ }
+
+ synchronized(this)
+ {
+ assert(_state == StateActivating);
+
+ //
+ // Signal threads waiting for the activation.
+ //
+ _state = StateActive;
+ notifyAll();
+
+ for(IncomingConnectionFactory factory : _incomingConnectionFactories)
+ {
+ factory.activate();
+ }
+ }
+ }
+
+ @Override
+ public synchronized void
+ hold()
+ {
+ checkForDeactivation();
+ _state = StateHeld;
+ for(IncomingConnectionFactory factory : _incomingConnectionFactories)
+ {
+ factory.hold();
+ }
+ }
+
+ @Override
+ public void
+ waitForHold()
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+
+ List<IncomingConnectionFactory> incomingConnectionFactories;
+ synchronized(this)
+ {
+ checkForDeactivation();
+ incomingConnectionFactories = new ArrayList<IncomingConnectionFactory>(_incomingConnectionFactories);
+ }
+
+ for(IncomingConnectionFactory factory : incomingConnectionFactories)
+ {
+ try
+ {
+ factory.waitUntilHolding();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+ }
+
+
+ @Override
+ public void
+ deactivate()
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+
+ synchronized(this)
+ {
+ //
+ // Wait for activation to complete. This is necessary to
+ // not get out of order locator updates.
+ //
+ while(_state == StateActivating)
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+ if(_state > StateDeactivating)
+ {
+ return;
+ }
+ _state = StateDeactivating;
+ }
+
+ //
+ // NOTE: the router/locator infos and incoming connection
+ // facatory list are immutable at this point.
+ //
+
+ if(_routerInfo != null)
+ {
+ //
+ // Remove entry from the router manager.
+ //
+ _instance.routerManager().erase(_routerInfo.getRouter());
+
+ //
+ // Clear this object adapter with the router.
+ //
+ _routerInfo.setAdapter(null);
+ }
+
+ try
+ {
+ updateLocatorRegistry(_locatorInfo, null);
+ }
+ catch(Ice.LocalException ex)
+ {
+ //
+ // We can't throw exceptions in deactivate so we ignore
+ // failures to update the locator registry.
+ //
+ }
+
+ //
+ // Must be called outside the thread synchronization, because
+ // Connection::destroy() might block when sending a
+ // CloseConnection message.
+ //
+ for(IncomingConnectionFactory factory : _incomingConnectionFactories)
+ {
+ factory.destroy();
+ }
+
+ //
+ // Must be called outside the thread synchronization, because
+ // changing the object adapter might block if there are still
+ // requests being dispatched.
+ //
+ _instance.outgoingConnectionFactory().removeAdapter(this);
+
+ synchronized(this)
+ {
+ _state = StateDeactivated;
+ notifyAll();
+ }
+ }
+
+ @Override
+ public void
+ waitForDeactivate()
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+
+ try
+ {
+ List<IncomingConnectionFactory> incomingConnectionFactories;
+ synchronized(this)
+ {
+ //
+ // Wait for deactivation of the adapter itself, and
+ // for the return of all direct method calls using
+ // this adapter.
+ //
+ while((_state < StateDeactivated) || _directCount > 0)
+ {
+ wait();
+ }
+ if(_state > StateDeactivated)
+ {
+ return;
+ }
+ incomingConnectionFactories = new ArrayList<IncomingConnectionFactory>(_incomingConnectionFactories);
+ }
+
+ //
+ // Now we wait for until all incoming connection factories are
+ // finished (the incoming connection factory list is immutable
+ // at this point).
+ //
+ for(IncomingConnectionFactory f : incomingConnectionFactories)
+ {
+ f.waitUntilFinished();
+ }
+ }
+ catch(InterruptedException e)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+
+ @Override
+ public synchronized boolean
+ isDeactivated()
+ {
+ return _state >= StateDeactivated;
+ }
+
+ @Override
+ public void
+ destroy()
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+
+ //
+ // Deactivate and wait for completion.
+ //
+ deactivate();
+ waitForDeactivate();
+
+ synchronized(this)
+ {
+ assert(_state >= StateDeactivated);
+
+ //
+ // Only a single thread is allowed to destroy the object
+ // adapter. Other threads wait for the destruction to be
+ // completed.
+ //
+ while(_state == StateDestroying)
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+ if(_state == StateDestroyed)
+ {
+ return;
+ }
+
+ _state = StateDestroying;
+ }
+
+ //
+ // Now it's also time to clean up our servants and servant
+ // locators.
+ //
+ _servantManager.destroy();
+
+ //
+ // Destroy the thread pool.
+ //
+ if(_threadPool != null)
+ {
+ _threadPool.destroy();
+ try
+ {
+ _threadPool.joinWithAllThreads();
+ }
+ catch (InterruptedException e)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+
+ _objectAdapterFactory.removeObjectAdapter(this);
+
+ synchronized(this)
+ {
+ _incomingConnectionFactories.clear();
+
+ //
+ // Remove object references (some of them cyclic).
+ //
+ _instance = null;
+ _threadPool = null;
+ _routerEndpoints = null;
+ _routerInfo = null;
+ _publishedEndpoints = null;
+ _locatorInfo = null;
+ _reference = null;
+ _objectAdapterFactory = null;
+
+ //
+ // Signal that destroying is complete.
+ //
+ _state = StateDestroyed;
+ notifyAll();
+ }
+ }
+
+ @Override
+ public ObjectPrx
+ add(Ice.Object object, Identity ident)
+ {
+ return addFacet(object, ident, "");
+ }
+
+ @Override
+ public synchronized ObjectPrx
+ addFacet(Ice.Object object, Identity ident, String facet)
+ {
+ checkForDeactivation();
+ checkIdentity(ident);
+ checkServant(object);
+
+ //
+ // Create a copy of the Identity argument, in case the caller
+ // reuses it.
+ //
+ Identity id = new Identity();
+ id.category = ident.category;
+ id.name = ident.name;
+
+ _servantManager.addServant(object, id, facet);
+
+ return newProxy(id, facet);
+ }
+
+ @Override
+ public ObjectPrx
+ addWithUUID(Ice.Object object)
+ {
+ return addFacetWithUUID(object, "");
+ }
+
+ @Override
+ public ObjectPrx
+ addFacetWithUUID(Ice.Object object, String facet)
+ {
+ Identity ident = new Identity();
+ ident.category = "";
+ ident.name = java.util.UUID.randomUUID().toString();
+
+ return addFacet(object, ident, facet);
+ }
+
+ @Override
+ public synchronized void
+ addDefaultServant(Ice.Object servant, String category)
+ {
+ checkServant(servant);
+ checkForDeactivation();
+
+ _servantManager.addDefaultServant(servant, category);
+ }
+
+ @Override
+ public Ice.Object
+ remove(Identity ident)
+ {
+ return removeFacet(ident, "");
+ }
+
+ @Override
+ public synchronized Ice.Object
+ removeFacet(Identity ident, String facet)
+ {
+ checkForDeactivation();
+ checkIdentity(ident);
+
+ return _servantManager.removeServant(ident, facet);
+ }
+
+ @Override
+ public synchronized Map<String, Object>
+ removeAllFacets(Identity ident)
+ {
+ checkForDeactivation();
+ checkIdentity(ident);
+
+ return _servantManager.removeAllFacets(ident);
+ }
+
+ @Override
+ public synchronized Ice.Object
+ removeDefaultServant(String category)
+ {
+ checkForDeactivation();
+
+ return _servantManager.removeDefaultServant(category);
+ }
+
+ @Override
+ public Ice.Object
+ find(Identity ident)
+ {
+ return findFacet(ident, "");
+ }
+
+ @Override
+ public synchronized Ice.Object
+ findFacet(Identity ident, String facet)
+ {
+ checkForDeactivation();
+ checkIdentity(ident);
+
+ return _servantManager.findServant(ident, facet);
+ }
+
+ @Override
+ public synchronized java.util.Map<String, Ice.Object>
+ findAllFacets(Identity ident)
+ {
+ checkForDeactivation();
+ checkIdentity(ident);
+
+ return _servantManager.findAllFacets(ident);
+ }
+
+ @Override
+ public synchronized Ice.Object
+ findByProxy(ObjectPrx proxy)
+ {
+ checkForDeactivation();
+
+ IceInternal.Reference ref = ((ObjectPrxHelperBase)proxy).__reference();
+ return findFacet(ref.getIdentity(), ref.getFacet());
+ }
+
+ @Override
+ public synchronized Ice.Object
+ findDefaultServant(String category)
+ {
+ checkForDeactivation();
+
+ return _servantManager.findDefaultServant(category);
+ }
+
+ @Override
+ public synchronized void
+ addServantLocator(ServantLocator locator, String prefix)
+ {
+ checkForDeactivation();
+
+ _servantManager.addServantLocator(locator, prefix);
+ }
+
+ @Override
+ public synchronized ServantLocator
+ removeServantLocator(String prefix)
+ {
+ checkForDeactivation();
+
+ return _servantManager.removeServantLocator(prefix);
+ }
+
+ @Override
+ public synchronized ServantLocator
+ findServantLocator(String prefix)
+ {
+ checkForDeactivation();
+
+ return _servantManager.findServantLocator(prefix);
+ }
+
+ @Override
+ public synchronized ObjectPrx
+ createProxy(Identity ident)
+ {
+ checkForDeactivation();
+ checkIdentity(ident);
+
+ return newProxy(ident, "");
+ }
+
+ @Override
+ public synchronized ObjectPrx
+ createDirectProxy(Identity ident)
+ {
+ checkForDeactivation();
+ checkIdentity(ident);
+
+ return newDirectProxy(ident, "");
+ }
+
+ @Override
+ public synchronized ObjectPrx
+ createIndirectProxy(Identity ident)
+ {
+ checkForDeactivation();
+ checkIdentity(ident);
+
+ return newIndirectProxy(ident, "", _id);
+ }
+
+ @Override
+ public synchronized void
+ setLocator(LocatorPrx locator)
+ {
+ checkForDeactivation();
+
+ _locatorInfo = _instance.locatorManager().get(locator);
+ }
+
+ @Override
+ public synchronized LocatorPrx
+ getLocator()
+ {
+ if(_locatorInfo == null)
+ {
+ return null;
+ }
+ else
+ {
+ return _locatorInfo.getLocator();
+ }
+ }
+
+ @Override
+ public void
+ refreshPublishedEndpoints()
+ {
+ IceInternal.LocatorInfo locatorInfo = null;
+ List<IceInternal.EndpointI> oldPublishedEndpoints;
+
+ synchronized(this)
+ {
+ checkForDeactivation();
+
+ oldPublishedEndpoints = _publishedEndpoints;
+ _publishedEndpoints = parsePublishedEndpoints();
+
+ locatorInfo = _locatorInfo;
+ }
+
+ try
+ {
+ Ice.Identity dummy = new Ice.Identity();
+ dummy.name = "dummy";
+ updateLocatorRegistry(locatorInfo, createDirectProxy(dummy));
+ }
+ catch(Ice.LocalException ex)
+ {
+ synchronized(this)
+ {
+ //
+ // Restore the old published endpoints.
+ //
+ _publishedEndpoints = oldPublishedEndpoints;
+ throw ex;
+ }
+ }
+ }
+
+ @Override
+ public synchronized Endpoint[]
+ getEndpoints()
+ {
+ List<Endpoint> endpoints = new ArrayList<Endpoint>();
+ for(IncomingConnectionFactory factory : _incomingConnectionFactories)
+ {
+ endpoints.add(factory.endpoint());
+ }
+ return endpoints.toArray(new Endpoint[0]);
+ }
+
+ @Override
+ public synchronized Endpoint[]
+ getPublishedEndpoints()
+ {
+ return _publishedEndpoints.toArray(new Endpoint[0]);
+ }
+
+ public boolean
+ isLocal(ObjectPrx proxy)
+ {
+ //
+ // NOTE: it's important that isLocal() doesn't perform any blocking operations as
+ // it can be called for AMI invocations if the proxy has no delegate set yet.
+ //
+
+ IceInternal.Reference ref = ((ObjectPrxHelperBase)proxy).__reference();
+ if(ref.isWellKnown())
+ {
+ //
+ // Check the active servant map to see if the well-known
+ // proxy is for a local object.
+ //
+ return _servantManager.hasServant(ref.getIdentity());
+ }
+ else if(ref.isIndirect())
+ {
+ //
+ // Proxy is local if the reference adapter id matches this
+ // adapter id or replica group id.
+ //
+ return ref.getAdapterId().equals(_id) || ref.getAdapterId().equals(_replicaGroupId);
+ }
+ else
+ {
+ IceInternal.EndpointI[] endpoints = ref.getEndpoints();
+
+ synchronized(this)
+ {
+ checkForDeactivation();
+
+ //
+ // Proxies which have at least one endpoint in common with the
+ // endpoints used by this object adapter's incoming connection
+ // factories are considered local.
+ //
+ for(IceInternal.EndpointI endpoint : endpoints)
+ {
+ for(IceInternal.EndpointI p : _publishedEndpoints)
+ {
+ if(endpoint.equivalent(p))
+ {
+ return true;
+ }
+ }
+ for(IncomingConnectionFactory p : _incomingConnectionFactories)
+ {
+ if(endpoint.equivalent(p.endpoint()))
+ {
+ return true;
+ }
+ }
+ }
+
+ //
+ // Proxies which have at least one endpoint in common with the
+ // router's server proxy endpoints (if any), are also considered
+ // local.
+ //
+ if(_routerInfo != null && _routerInfo.getRouter().equals(proxy.ice_getRouter()))
+ {
+ for(IceInternal.EndpointI endpoint : endpoints)
+ {
+ for(IceInternal.EndpointI p : _routerEndpoints)
+ {
+ if(endpoint.equivalent(p))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public void
+ flushAsyncBatchRequests(IceInternal.CommunicatorFlushBatch outAsync)
+ {
+ List<IncomingConnectionFactory> f;
+ synchronized(this)
+ {
+ f = new ArrayList<IncomingConnectionFactory>(_incomingConnectionFactories);
+ }
+ for(IncomingConnectionFactory p : f)
+ {
+ p.flushAsyncBatchRequests(outAsync);
+ }
+ }
+
+ public void
+ updateConnectionObservers()
+ {
+ List<IncomingConnectionFactory> f;
+ synchronized(this)
+ {
+ f = new ArrayList<IncomingConnectionFactory>(_incomingConnectionFactories);
+ }
+ for(IncomingConnectionFactory p : f)
+ {
+ p.updateConnectionObservers();
+ }
+ }
+
+ public void
+ updateThreadObservers()
+ {
+ IceInternal.ThreadPool threadPool = null;
+ synchronized(this)
+ {
+ threadPool = _threadPool;
+ }
+ if(threadPool != null)
+ {
+ threadPool.updateObservers();
+ }
+ }
+
+ public synchronized void
+ incDirectCount()
+ {
+ checkForDeactivation();
+
+ assert(_directCount >= 0);
+ ++_directCount;
+ }
+
+ public synchronized void
+ decDirectCount()
+ {
+ // Not check for deactivation here!
+
+ assert(_instance != null); // Must not be called after destroy().
+
+ assert(_directCount > 0);
+ if(--_directCount == 0)
+ {
+ notifyAll();
+ }
+ }
+
+ public IceInternal.ThreadPool
+ getThreadPool()
+ {
+ // No mutex lock necessary, _threadPool and _instance are
+ // immutable after creation until they are removed in
+ // destroy().
+
+ // Not check for deactivation here!
+
+ assert(_instance != null); // Must not be called after destroy().
+
+ if(_threadPool != null)
+ {
+ return _threadPool;
+ }
+ else
+ {
+ return _instance.serverThreadPool();
+ }
+ }
+
+ public IceInternal.ServantManager
+ getServantManager()
+ {
+ //
+ // No mutex lock necessary, _servantManager is immutable.
+ //
+ return _servantManager;
+ }
+
+ public IceInternal.ACMConfig
+ getACM()
+ {
+ // No check for deactivation here!
+ assert(_instance != null); // Must not be called after destroy().
+ return _acm;
+ }
+
+ public int
+ messageSizeMax()
+ {
+ // No mutex lock, immutable.
+ return _messageSizeMax;
+ }
+
+ //
+ // Only for use by IceInternal.ObjectAdapterFactory
+ //
+ public
+ ObjectAdapterI(IceInternal.Instance instance, Communicator communicator,
+ IceInternal.ObjectAdapterFactory objectAdapterFactory, String name,
+ RouterPrx router, boolean noConfig)
+ {
+ _instance = instance;
+ _communicator = communicator;
+ _objectAdapterFactory = objectAdapterFactory;
+ _servantManager = new IceInternal.ServantManager(instance, name);
+ _name = name;
+ _directCount = 0;
+ _noConfig = noConfig;
+
+ if(_noConfig)
+ {
+ _id = "";
+ _replicaGroupId = "";
+ _reference = _instance.referenceFactory().create("dummy -t", "");
+ _acm = _instance.serverACM();
+ _messageSizeMax = _instance.messageSizeMax();
+ return;
+ }
+
+ final Properties properties = _instance.initializationData().properties;
+ List<String> unknownProps = new ArrayList<String>();
+ boolean noProps = filterProperties(unknownProps);
+
+ //
+ // Warn about unknown object adapter properties.
+ //
+ if(unknownProps.size() != 0 && properties.getPropertyAsIntWithDefault("Ice.Warn.UnknownProperties", 1) > 0)
+ {
+ StringBuffer message = new StringBuffer("found unknown properties for object adapter `");
+ message.append(_name);
+ message.append("':");
+ for(String p : unknownProps)
+ {
+ message.append("\n ");
+ message.append(p);
+ }
+ _instance.initializationData().logger.warning(message.toString());
+ }
+
+ //
+ // Make sure named adapter has some configuration.
+ //
+ if(router == null && noProps)
+ {
+ //
+ // These need to be set to prevent finalizer from complaining.
+ //
+ _state = StateDestroyed;
+ _instance = null;
+ _incomingConnectionFactories = null;
+
+ InitializationException ex = new InitializationException();
+ ex.reason = "object adapter `" + _name + "' requires configuration";
+ throw ex;
+ }
+
+ _id = properties.getProperty(_name + ".AdapterId");
+ _replicaGroupId = properties.getProperty(_name + ".ReplicaGroupId");
+
+ //
+ // Setup a reference to be used to get the default proxy options
+ // when creating new proxies. By default, create twoway proxies.
+ //
+ String proxyOptions = properties.getPropertyWithDefault(_name + ".ProxyOptions", "-t");
+ try
+ {
+ _reference = _instance.referenceFactory().create("dummy " + proxyOptions, "");
+ }
+ catch(ProxyParseException e)
+ {
+ InitializationException ex = new InitializationException();
+ ex.reason = "invalid proxy options `" + proxyOptions + "' for object adapter `" + _name + "'";
+ throw ex;
+ }
+
+ _acm = new IceInternal.ACMConfig(properties, communicator.getLogger(), _name + ".ACM", instance.serverACM());
+
+ {
+ final int defaultMessageSizeMax = instance.messageSizeMax() / 1024;
+ int num = properties.getPropertyAsIntWithDefault(_name + ".MessageSizeMax", defaultMessageSizeMax);
+ if(num < 1 || num > 0x7fffffff / 1024)
+ {
+ _messageSizeMax = 0x7fffffff;
+ }
+ else
+ {
+ _messageSizeMax = num * 1024; // Property is in kilobytes, _messageSizeMax in bytes
+ }
+ }
+
+ try
+ {
+ int threadPoolSize = properties.getPropertyAsInt(_name + ".ThreadPool.Size");
+ int threadPoolSizeMax = properties.getPropertyAsInt(_name + ".ThreadPool.SizeMax");
+
+ //
+ // Create the per-adapter thread pool, if necessary.
+ //
+ if(threadPoolSize > 0 || threadPoolSizeMax > 0)
+ {
+ _threadPool = new IceInternal.ThreadPool(_instance, _name + ".ThreadPool", 0);
+ }
+
+ if(router == null)
+ {
+ router = RouterPrxHelper.uncheckedCast(_instance.proxyFactory().propertyToProxy(name + ".Router"));
+ }
+ if(router != null)
+ {
+ _routerInfo = _instance.routerManager().get(router);
+ if(_routerInfo != null)
+ {
+ //
+ // Make sure this router is not already registered with another adapter.
+ //
+ if(_routerInfo.getAdapter() != null)
+ {
+ throw new AlreadyRegisteredException("object adapter with router",
+ Ice.Util.identityToString(router.ice_getIdentity()));
+ }
+
+ //
+ // Add the router's server proxy endpoints to this object
+ // adapter.
+ //
+ IceInternal.EndpointI[] endpoints = _routerInfo.getServerEndpoints();
+ for(IceInternal.EndpointI endpoint : endpoints)
+ {
+ _routerEndpoints.add(endpoint);
+ }
+ java.util.Collections.sort(_routerEndpoints); // Must be sorted.
+
+ //
+ // Remove duplicate endpoints, so we have a list of unique
+ // endpoints.
+ //
+ for(int i = 0; i < _routerEndpoints.size() - 1;)
+ {
+ IceInternal.EndpointI e1 = _routerEndpoints.get(i);
+ IceInternal.EndpointI e2 = _routerEndpoints.get(i + 1);
+ if(e1.equals(e2))
+ {
+ _routerEndpoints.remove(i);
+ }
+ 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.
+ //
+ _routerInfo.setAdapter(this);
+
+ //
+ // Also modify all existing outgoing connections to the
+ // router's client proxy to use this object adapter for
+ // callbacks.
+ //
+ _instance.outgoingConnectionFactory().setRouterInfo(_routerInfo);
+ }
+ }
+ else
+ {
+ //
+ // Parse the endpoints, but don't store them in the adapter. The connection
+ // factory might change it, for example, to fill in the real port number.
+ //
+ List<IceInternal.EndpointI> endpoints =
+ parseEndpoints(properties.getProperty(_name + ".Endpoints"), true);
+ for(IceInternal.EndpointI endp : endpoints)
+ {
+ IncomingConnectionFactory factory = new IncomingConnectionFactory(instance, endp, this);
+ _incomingConnectionFactories.add(factory);
+ }
+ if(endpoints.size() == 0)
+ {
+ IceInternal.TraceLevels tl = _instance.traceLevels();
+ if(tl.network >= 2)
+ {
+ _instance.initializationData().logger.trace(tl.networkCat,
+ "created adapter `" + name + "' without endpoints");
+ }
+ }
+
+ //
+ // Parse the publsihed endpoints.
+ //
+ _publishedEndpoints = parsePublishedEndpoints();
+ }
+
+ if(properties.getProperty(_name + ".Locator").length() > 0)
+ {
+ setLocator(LocatorPrxHelper.uncheckedCast(
+ _instance.proxyFactory().propertyToProxy(_name + ".Locator")));
+ }
+ else
+ {
+ setLocator(_instance.referenceFactory().getDefaultLocator());
+ }
+ }
+ catch(LocalException ex)
+ {
+ destroy();
+ throw ex;
+ }
+ }
+
+ @Override
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ try
+ {
+ if(_state < StateDeactivated)
+ {
+ _instance.initializationData().logger.warning("object adapter `" + getName() +
+ "' has not been deactivated");
+ }
+ else if(_state != StateDestroyed)
+ {
+ _instance.initializationData().logger.warning("object adapter `" + getName() +
+ "' has not been destroyed");
+ }
+ else
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_threadPool == null);
+ // Not cleared, it needs to be immutable.
+ //IceUtilInternal.Assert.FinalizerAssert(_servantManager == null);
+ //IceUtilInternal.Assert.FinalizerAssert(_incomingConnectionFactories.isEmpty());
+ IceUtilInternal.Assert.FinalizerAssert(_directCount == 0);
+ }
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ private ObjectPrx
+ newProxy(Identity ident, String facet)
+ {
+ if(_id.length() == 0)
+ {
+ return newDirectProxy(ident, facet);
+ }
+ else if(_replicaGroupId.length() == 0)
+ {
+ return newIndirectProxy(ident, facet, _id);
+ }
+ else
+ {
+ return newIndirectProxy(ident, facet, _replicaGroupId);
+ }
+ }
+
+ private ObjectPrx
+ newDirectProxy(Identity ident, String facet)
+ {
+ IceInternal.EndpointI[] endpoints;
+
+ int sz = _publishedEndpoints.size();
+ endpoints = new IceInternal.EndpointI[sz + _routerEndpoints.size()];
+ _publishedEndpoints.toArray(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(int i = 0; i < _routerEndpoints.size(); ++i)
+ {
+ endpoints[sz + i] = _routerEndpoints.get(i);
+ }
+
+ //
+ // Create a reference and return a proxy for this reference.
+ //
+ IceInternal.Reference ref = _instance.referenceFactory().create(ident, facet, _reference, endpoints);
+ return _instance.proxyFactory().referenceToProxy(ref);
+ }
+
+ private ObjectPrx
+ newIndirectProxy(Identity ident, String facet, String id)
+ {
+ //
+ // Create a reference with the adapter id and return a proxy
+ // for the reference.
+ //
+ IceInternal.Reference ref = _instance.referenceFactory().create(ident, facet, _reference, id);
+ return _instance.proxyFactory().referenceToProxy(ref);
+ }
+
+ private void
+ checkForDeactivation()
+ {
+ if(_state >= StateDeactivating)
+ {
+ ObjectAdapterDeactivatedException ex = new ObjectAdapterDeactivatedException();
+ ex.name = getName();
+ throw ex;
+ }
+ }
+
+ private static void
+ checkIdentity(Identity ident)
+ {
+ if(ident.name == null || ident.name.length() == 0)
+ {
+ throw new IllegalIdentityException(ident);
+ }
+
+ if(ident.category == null)
+ {
+ ident.category = "";
+ }
+ }
+
+ private static void
+ checkServant(Ice.Object servant)
+ {
+ if(servant == null)
+ {
+ throw new IllegalServantException("cannot add null servant to Object Adapter");
+ }
+ }
+
+ private List<IceInternal.EndpointI>
+ parseEndpoints(String endpts, boolean oaEndpoints)
+ {
+ int beg;
+ int end = 0;
+
+ final String delim = " \t\n\r";
+
+ List<IceInternal.EndpointI> endpoints = new ArrayList<IceInternal.EndpointI>();
+ while(end < endpts.length())
+ {
+ beg = IceUtilInternal.StringUtil.findFirstNotOf(endpts, delim, end);
+ if(beg == -1)
+ {
+ break;
+ }
+
+ end = beg;
+ while(true)
+ {
+ end = endpts.indexOf(':', end);
+ if(end == -1)
+ {
+ end = endpts.length();
+ break;
+ }
+ else
+ {
+ boolean quoted = false;
+ int quote = beg;
+ while(true)
+ {
+ quote = endpts.indexOf('\"', quote);
+ if(quote == -1 || end < quote)
+ {
+ break;
+ }
+ else
+ {
+ quote = endpts.indexOf('\"', ++quote);
+ if(quote == -1)
+ {
+ break;
+ }
+ else if(end < quote)
+ {
+ quoted = true;
+ break;
+ }
+ ++quote;
+ }
+ }
+ if(!quoted)
+ {
+ break;
+ }
+ ++end;
+ }
+ }
+
+ if(end == beg)
+ {
+ ++end;
+ continue;
+ }
+
+ String s = endpts.substring(beg, end);
+ IceInternal.EndpointI endp = _instance.endpointFactoryManager().create(s, oaEndpoints);
+ if(endp == null)
+ {
+ Ice.EndpointParseException e = new Ice.EndpointParseException();
+ e.str = "invalid object adapter endpoint `" + s + "'";
+ throw e;
+ }
+ endpoints.add(endp);
+
+ ++end;
+ }
+
+ return endpoints;
+ }
+
+ private List<IceInternal.EndpointI>
+ parsePublishedEndpoints()
+ {
+ //
+ // Parse published endpoints. If set, these are used in proxies
+ // instead of the connection factory Endpoints.
+ //
+ String endpts = _instance.initializationData().properties.getProperty(_name + ".PublishedEndpoints");
+ List<IceInternal.EndpointI> endpoints = parseEndpoints(endpts, false);
+ if(endpoints.isEmpty())
+ {
+ //
+ // If the PublishedEndpoints property isn't set, we compute the published enpdoints
+ // from the OA endpoints, expanding any endpoints that may be listening on INADDR_ANY
+ // to include actual addresses in the published endpoints.
+ //
+ for(IncomingConnectionFactory factory : _incomingConnectionFactories)
+ {
+ endpoints.addAll(factory.endpoint().expand());
+ }
+ }
+
+ if(_instance.traceLevels().network >= 1 && !endpoints.isEmpty())
+ {
+ StringBuffer s = new StringBuffer("published endpoints for object adapter `");
+ s.append(_name);
+ s.append("':\n");
+ boolean first = true;
+ for(IceInternal.EndpointI endpoint : endpoints)
+ {
+ if(!first)
+ {
+ s.append(":");
+ }
+ s.append(endpoint.toString());
+ first = false;
+ }
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+ return endpoints;
+ }
+
+ private void
+ updateLocatorRegistry(IceInternal.LocatorInfo locatorInfo, Ice.ObjectPrx proxy)
+ {
+ if(_id.length() == 0 || locatorInfo == null)
+ {
+ return; // Nothing to update.
+ }
+
+ //
+ // Call on the locator registry outside the synchronization to
+ // blocking other threads that need to lock this OA.
+ //
+ LocatorRegistryPrx locatorRegistry = locatorInfo.getLocatorRegistry();
+ if(locatorRegistry == null)
+ {
+ return;
+ }
+
+ try
+ {
+ if(_replicaGroupId.length() == 0)
+ {
+ locatorRegistry.setAdapterDirectProxy(_id, proxy);
+ }
+ else
+ {
+ locatorRegistry.setReplicatedAdapterDirectProxy(_id, _replicaGroupId, proxy);
+ }
+ }
+ catch(AdapterNotFoundException ex)
+ {
+ if(_instance.traceLevels().location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("couldn't update object adapter `");
+ s.append(_id);
+ s.append("' endpoints with the locator registry:\n");
+ s.append("the object adapter is not known to the locator registry");
+ _instance.initializationData().logger.trace(_instance.traceLevels().locationCat, s.toString());
+ }
+
+ NotRegisteredException ex1 = new NotRegisteredException();
+ ex1.kindOfObject = "object adapter";
+ ex1.id = _id;
+ throw ex1;
+ }
+ catch(InvalidReplicaGroupIdException ex)
+ {
+ if(_instance.traceLevels().location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("couldn't update object adapter `");
+ s.append(_id);
+ s.append("' endpoints with the locator registry:\n");
+ s.append("the replica group `");
+ s.append(_replicaGroupId);
+ s.append("' is not known to the locator registry");
+ _instance.initializationData().logger.trace(_instance.traceLevels().locationCat, s.toString());
+ }
+
+ NotRegisteredException ex1 = new NotRegisteredException();
+ ex1.kindOfObject = "replica group";
+ ex1.id = _replicaGroupId;
+ throw ex1;
+ }
+ catch(AdapterAlreadyActiveException ex)
+ {
+ if(_instance.traceLevels().location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("couldn't update object adapter `");
+ s.append(_id);
+ s.append("' endpoints with the locator registry:\n");
+ s.append("the object adapter endpoints are already set");
+ _instance.initializationData().logger.trace(_instance.traceLevels().locationCat, s.toString());
+ }
+
+ ObjectAdapterIdInUseException ex1 = new ObjectAdapterIdInUseException();
+ ex1.id = _id;
+ throw ex1;
+ }
+ catch(ObjectAdapterDeactivatedException e)
+ {
+ // Expected if collocated call and OA is deactivated, ignore.
+ }
+ catch(CommunicatorDestroyedException e)
+ {
+ // Ignore
+ }
+ catch(LocalException e)
+ {
+ if(_instance.traceLevels().location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("couldn't update object adapter `");
+ s.append(_id);
+ s.append("' endpoints with the locator registry:\n");
+ s.append(e.toString());
+ _instance.initializationData().logger.trace(_instance.traceLevels().locationCat, s.toString());
+ }
+ throw e; // TODO: Shall we raise a special exception instead of a non obvious local exception?
+ }
+
+ if(_instance.traceLevels().location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("updated object adapter `");
+ s.append(_id);
+ s.append("' endpoints with the locator registry\n");
+ s.append("endpoints = ");
+ if(proxy != null)
+ {
+ Ice.Endpoint[] endpoints = proxy.ice_getEndpoints();
+ for(int i = 0; i < endpoints.length; i++)
+ {
+ s.append(endpoints[i].toString());
+ if(i + 1 < endpoints.length)
+ {
+ s.append(":");
+ }
+ }
+ }
+ _instance.initializationData().logger.trace(_instance.traceLevels().locationCat, s.toString());
+ }
+ }
+
+ static private String[] _suffixes =
+ {
+ "ACM",
+ "ACM.Timeout",
+ "ACM.Heartbeat",
+ "ACM.Close",
+ "AdapterId",
+ "Endpoints",
+ "Locator",
+ "Locator.EncodingVersion",
+ "Locator.EndpointSelection",
+ "Locator.ConnectionCached",
+ "Locator.PreferSecure",
+ "Locator.CollocationOptimized",
+ "Locator.Router",
+ "MessageSizeMax",
+ "PublishedEndpoints",
+ "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.Locator.InvocationTimeout",
+ "Router.LocatorCacheTimeout",
+ "Router.InvocationTimeout",
+ "ProxyOptions",
+ "ThreadPool.Size",
+ "ThreadPool.SizeMax",
+ "ThreadPool.SizeWarn",
+ "ThreadPool.StackSize",
+ "ThreadPool.Serialize"
+ };
+
+ boolean
+ filterProperties(List<String> unknownProps)
+ {
+ //
+ // Do not create unknown properties list if Ice prefix, ie Ice, Glacier2, etc
+ //
+ boolean addUnknown = true;
+ String prefix = _name + ".";
+ for(int i = 0; IceInternal.PropertyNames.clPropNames[i] != null; ++i)
+ {
+ if(prefix.startsWith(IceInternal.PropertyNames.clPropNames[i] + "."))
+ {
+ addUnknown = false;
+ break;
+ }
+ }
+
+ boolean noProps = true;
+ Map<String, String> props = _instance.initializationData().properties.getPropertiesForPrefix(prefix);
+ for(String prop : props.keySet())
+ {
+ boolean valid = false;
+ for(String suffix : _suffixes)
+ {
+ if(prop.equals(prefix + suffix))
+ {
+ noProps = false;
+ valid = true;
+ break;
+ }
+ }
+
+ if(!valid && addUnknown)
+ {
+ unknownProps.add(prop);
+ }
+ }
+
+ return noProps;
+ }
+
+ private static final int StateUninitialized = 0; // Just constructed.
+ private static final int StateHeld = 1;
+ private static final int StateActivating = 2;
+ private static final int StateActive = 3;
+ private static final int StateDeactivating = 4;
+ private static final int StateDeactivated = 5;
+ private static final int StateDestroying = 6;
+ private static final int StateDestroyed = 7;
+
+ private int _state = StateUninitialized;
+ private IceInternal.Instance _instance;
+ private Communicator _communicator;
+ private IceInternal.ObjectAdapterFactory _objectAdapterFactory;
+ private IceInternal.ThreadPool _threadPool;
+ private IceInternal.ACMConfig _acm;
+ private IceInternal.ServantManager _servantManager;
+ final private String _name;
+ final private String _id;
+ final private String _replicaGroupId;
+ private IceInternal.Reference _reference;
+ private List<IncomingConnectionFactory> _incomingConnectionFactories = new ArrayList<IncomingConnectionFactory>();
+ private List<IceInternal.EndpointI> _routerEndpoints = new ArrayList<IceInternal.EndpointI>();
+ private IceInternal.RouterInfo _routerInfo = null;
+ private List<IceInternal.EndpointI> _publishedEndpoints = new ArrayList<IceInternal.EndpointI>();
+ private IceInternal.LocatorInfo _locatorInfo;
+ private int _directCount; // The number of direct proxies dispatching on this object adapter.
+ private boolean _noConfig;
+ private final int _messageSizeMax;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectHolder.java b/java-compat/src/Ice/src/main/java/Ice/ObjectHolder.java
new file mode 100644
index 00000000000..c570288a292
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectHolder.java
@@ -0,0 +1,41 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for Ice objects that are out- or inout-parameters.
+ **/
+public final class ObjectHolder extends ObjectHolderBase<Ice.Object>
+{
+ /**
+ * Instantiates the class with a <code>null</code> value.
+ **/
+ public ObjectHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed Ice object.
+ **/
+ public ObjectHolder(Ice.Object value)
+ {
+ super(value);
+ }
+
+ /**
+ * Sets the value of this holder to the passed instance.
+ *
+ * @param v The new value for this holder.
+ **/
+ public void valueReady(Ice.Object v)
+ {
+ value = v;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectHolderBase.java b/java-compat/src/Ice/src/main/java/Ice/ObjectHolderBase.java
new file mode 100644
index 00000000000..62fa4ac1591
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectHolderBase.java
@@ -0,0 +1,38 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder base class for Ice objects that are in- or inout-parameters.
+ **/
+public abstract class ObjectHolderBase<T extends Ice.Object> implements ReadValueCallback
+{
+ /**
+ * Instantiates the class with a <code>null</code> value.
+ **/
+ public
+ ObjectHolderBase()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed Ice object.
+ **/
+ public
+ ObjectHolderBase(T obj)
+ {
+ this.value = obj;
+ }
+
+ /**
+ * The Ice object stored by this holder.
+ **/
+ public T value;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectImpl.java b/java-compat/src/Ice/src/main/java/Ice/ObjectImpl.java
new file mode 100644
index 00000000000..b6a253d13ef
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectImpl.java
@@ -0,0 +1,429 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class for all Slice classes.
+ **/
+public abstract class ObjectImpl implements Object, java.lang.Cloneable, java.io.Serializable
+{
+ /**
+ * Instantiates an Ice object.
+ **/
+ public
+ ObjectImpl()
+ {
+ }
+
+ /**
+ * Returns a copy of the object. The cloned object contains field-for-field copies
+ * of the state.
+ *
+ * @return The cloned object.
+ **/
+ @Override
+ public ObjectImpl
+ clone()
+ {
+ ObjectImpl c = null;
+
+ try
+ {
+ c = (ObjectImpl)super.clone();
+ }
+ catch(CloneNotSupportedException ex)
+ {
+ assert false;
+ }
+ return c;
+ }
+
+ public final static String[] __ids =
+ {
+ "::Ice::Object"
+ };
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param s The type ID of the Slice interface to test against.
+ * @return The return value is <code>true</code> if <code>s</code> is
+ * <code>::Ice::Object</code>.
+ **/
+ @Override
+ public boolean
+ ice_isA(String s)
+ {
+ return s.equals(__ids[0]);
+ }
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param s The type ID of the Slice interface to test against.
+ * @param current The current object for the invocation.
+ * @return The return value is <code>true</code> if <code>s</code> is
+ * <code>::Ice::Object</code>.
+ **/
+ @Override
+ public boolean
+ ice_isA(String s, Current current)
+ {
+ return s.equals(__ids[0]);
+ }
+
+ public static DispatchStatus
+ ___ice_isA(Ice.Object __obj, IceInternal.Incoming __inS, Current __current)
+ {
+ InputStream __is = __inS.startReadParams();
+ String __id = __is.readString();
+ __inS.endReadParams();
+ boolean __ret = __obj.ice_isA(__id, __current);
+ OutputStream __os = __inS.__startWriteParams(Ice.FormatType.DefaultFormat);
+ __os.writeBool(__ret);
+ __inS.__endWriteParams(true);
+ return DispatchStatus.DispatchOK;
+ }
+
+ /**
+ * Tests whether this object can be reached.
+ **/
+ @Override
+ public void
+ ice_ping()
+ {
+ // Nothing to do.
+ }
+
+ /**
+ * Tests whether this object can be reached.
+ *
+ * @param current The current object for the invocation.
+ **/
+ @Override
+ public void
+ ice_ping(Current current)
+ {
+ // Nothing to do.
+ }
+
+ public static DispatchStatus
+ ___ice_ping(Ice.Object __obj, IceInternal.Incoming __inS, Current __current)
+ {
+ __inS.readEmptyParams();
+ __obj.ice_ping(__current);
+ __inS.__writeEmptyParams();
+ return DispatchStatus.DispatchOK;
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by this object.
+ *
+ * @return An array whose only element is <code>::Ice::Object</code>.
+ **/
+ @Override
+ public String[]
+ ice_ids()
+ {
+ return __ids;
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by this object.
+ *
+ * @param current The current object for the invocation.
+ * @return An array whose only element is <code>::Ice::Object</code>.
+ **/
+ @Override
+ public String[]
+ ice_ids(Current current)
+ {
+ return __ids;
+ }
+
+ public static DispatchStatus
+ ___ice_ids(Ice.Object __obj, IceInternal.Incoming __inS, Current __current)
+ {
+ __inS.readEmptyParams();
+ String[] __ret = __obj.ice_ids(__current);
+ OutputStream __os = __inS.__startWriteParams(Ice.FormatType.DefaultFormat);
+ __os.writeStringSeq(__ret);
+ __inS.__endWriteParams(true);
+ return DispatchStatus.DispatchOK;
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by this object.
+ *
+ * @return The return value is always <code>::Ice::Object</code>.
+ **/
+ @Override
+ public String
+ ice_id()
+ {
+ return __ids[0];
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by this object.
+ *
+ * @param current The current object for the invocation.
+ * @return A Slice type ID.
+ **/
+ @Override
+ public String
+ ice_id(Current current)
+ {
+ return __ids[0];
+ }
+
+ public static DispatchStatus
+ ___ice_id(Ice.Object __obj, IceInternal.Incoming __inS, Current __current)
+ {
+ __inS.readEmptyParams();
+ String __ret = __obj.ice_id(__current);
+ OutputStream __os = __inS.__startWriteParams(Ice.FormatType.DefaultFormat);
+ __os.writeString(__ret);
+ __inS.__endWriteParams(true);
+ return DispatchStatus.DispatchOK;
+ }
+
+ /**
+ * Returns the Slice type ID of the interface supported by this object.
+ *
+ * @return The return value is always ::Ice::Object.
+ **/
+ public static String
+ ice_staticId()
+ {
+ return __ids[0];
+ }
+
+ /**
+ * Returns the Freeze metadata attributes for an operation.
+ *
+ * @param operation The name of the operation.
+ * @return The least significant bit indicates whether the operation is a read
+ * or write operation. If the bit is set, the operation is a write operation.
+ * The expression <code>ice_operationAttributes("op") & 0x1</code> is true if
+ * the operation has a <code>["freeze:write"]</code> metadata directive.
+ * <p>
+ * The second- and third least significant bit indicate the transactional mode
+ * of the operation. The expression <code>ice_operationAttributes("op") & 0x6 >> 1</code>
+ * indicates the transactional mode as follows:
+ * <dl>
+ * <dt>0</dt>
+ * <dd><code>["freeze:read:supports"]</code></dd>
+ * <dt>1</dt>
+ * <dd><code>["freeze:read:mandatory"]</code> or <code>["freeze:write:mandatory"]</code></dd>
+ * <dt>2</dt>
+ * <dd><code>["freeze:read:required"]</code> or <code>["freeze:write:required"]</code></dd>
+ * <dt>3</dt>
+ * <dd><code>["freeze:read:never"]</code></dd>
+ * </dl>
+ *
+ * Refer to the Freeze manual for more information on the TransactionalEvictor.
+ **/
+ @Override
+ public int ice_operationAttributes(String operation)
+ {
+ return 0;
+ }
+
+ /**
+ * The Ice run time invokes this method prior to marshaling an object's data members. This allows a subclass
+ * to override this method in order to validate its data members. This default implementation does nothing.
+ **/
+ @Override
+ public void
+ ice_preMarshal()
+ {
+ }
+
+ /**
+ * This Ice run time invokes this method vafter unmarshaling an object's data members. This allows a
+ * subclass to override this method in order to perform additional initialization. This default
+ * implementation does nothing.
+ **/
+ @Override
+ public void
+ ice_postUnmarshal()
+ {
+ }
+
+ private final static String[] __all =
+ {
+ "ice_id",
+ "ice_ids",
+ "ice_isA",
+ "ice_ping"
+ };
+
+ /**
+ * Dispatches an invocation to a servant. This method is used by dispatch interceptors to forward an invocation
+ * to a servant (or to another interceptor).
+ *
+ * @param request The details of the invocation.
+ * @param cb The callback object for asynchchronous dispatch. For synchronous dispatch, the callback object must
+ * be <code>null</code>.
+ * @return The dispatch status for the operation.
+ *
+ * @see DispatchInterceptor
+ * @see DispatchInterceptorAsyncCallback
+ * @see DispatchStatus
+ **/
+ @Override
+ public DispatchStatus
+ ice_dispatch(Request request, DispatchInterceptorAsyncCallback cb)
+ {
+ IceInternal.Incoming in = (IceInternal.Incoming)request;
+ if(cb != null)
+ {
+ in.push(cb);
+ }
+ try
+ {
+ in.startOver(); // may raise ResponseSentException
+ return __dispatch(in, in.getCurrent());
+ }
+ finally
+ {
+ if(cb != null)
+ {
+ in.pop();
+ }
+ }
+ }
+
+ /**
+ * Dispatches an invocation to a servant. This method is used by dispatch interceptors to forward an invocation
+ * to a servant (or to another interceptor).
+ *
+ * @param request The details of the invocation.
+ * @return The dispatch status for the operation.
+ *
+ * @see DispatchInterceptor
+ * @see DispatchStatus
+ **/
+ @Override
+ public DispatchStatus
+ ice_dispatch(Request request)
+ {
+ return ice_dispatch(request, null);
+ }
+
+ @Override
+ public DispatchStatus
+ __dispatch(IceInternal.Incoming in, Current current)
+ {
+ int pos = java.util.Arrays.binarySearch(__all, current.operation);
+ if(pos < 0)
+ {
+ throw new Ice.OperationNotExistException(current.id, current.facet, current.operation);
+ }
+
+ switch(pos)
+ {
+ case 0:
+ {
+ return ___ice_id(this, in, current);
+ }
+ case 1:
+ {
+ return ___ice_ids(this, in, current);
+ }
+ case 2:
+ {
+ return ___ice_isA(this, in, current);
+ }
+ case 3:
+ {
+ return ___ice_ping(this, in, current);
+ }
+ }
+
+ assert(false);
+ throw new Ice.OperationNotExistException(current.id, current.facet, current.operation);
+ }
+
+ @Override
+ public void
+ __write(OutputStream os)
+ {
+ os.startValue(null);
+ __writeImpl(os);
+ os.endValue();
+ }
+
+ @Override
+ public void
+ __read(InputStream is)
+ {
+ is.startValue();
+ __readImpl(is);
+ is.endValue(false);
+ }
+
+ protected void
+ __writeImpl(OutputStream os)
+ {
+ }
+
+ protected void
+ __readImpl(InputStream is)
+ {
+ }
+
+ private static String
+ operationModeToString(OperationMode mode)
+ {
+ if(mode == Ice.OperationMode.Normal)
+ {
+ return "::Ice::Normal";
+ }
+ if(mode == Ice.OperationMode.Nonmutating)
+ {
+ return "::Ice::Nonmutating";
+ }
+
+ if(mode == Ice.OperationMode.Idempotent)
+ {
+ return "::Ice::Idempotent";
+ }
+
+ return "???";
+ }
+
+ protected static void
+ __checkMode(OperationMode expected, OperationMode received)
+ {
+ if(expected != received)
+ {
+ if(expected == Ice.OperationMode.Idempotent
+ && received == Ice.OperationMode.Nonmutating)
+ {
+ //
+ // Fine: typically an old client still using the
+ // deprecated nonmutating keyword
+ //
+ }
+ else
+ {
+ Ice.MarshalException ex = new Ice.MarshalException();
+ ex.reason = "unexpected operation mode. expected = "
+ + operationModeToString(expected) + " received = "
+ + operationModeToString(received);
+ throw ex;
+ }
+ }
+ }
+
+ public static final long serialVersionUID = 0L;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectInputStream.java b/java-compat/src/Ice/src/main/java/Ice/ObjectInputStream.java
new file mode 100644
index 00000000000..0d635b49b32
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectInputStream.java
@@ -0,0 +1,43 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * For deserialization of Slice types that contain a proxy, the application
+ * must instantiate a subclass of <code>ObjectInputStream</code> and supply
+ * a communicator that is used to reconstruct the proxy.
+ **/
+public class ObjectInputStream extends java.io.ObjectInputStream
+{
+ /**
+ * Instantiates this class for the specified communicator and input stream.
+ *
+ * @param communicator The communicator to use to deserialize proxies.
+ * @param stream The input stream to read from.
+ **/
+ public
+ ObjectInputStream(Communicator communicator, java.io.InputStream stream)
+ throws java.io.IOException
+ {
+ super(stream);
+ _communicator = communicator;
+ }
+
+ /**
+ * Returns the communicator for this stream.
+ **/
+ public Communicator
+ getCommunicator()
+ {
+ return _communicator;
+ }
+
+ private Communicator _communicator;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectPrx.java b/java-compat/src/Ice/src/main/java/Ice/ObjectPrx.java
new file mode 100644
index 00000000000..ad077d2edb1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectPrx.java
@@ -0,0 +1,1214 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base interface of all object proxies.
+ **/
+public interface ObjectPrx
+{
+ /**
+ * Returns the communicator that created this proxy.
+ *
+ * @return The communicator that created this proxy.
+ **/
+ Communicator ice_getCommunicator();
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param __id The type ID of the Slice interface to test against.
+ * @return <code>true</code> if the target object has the interface
+ * specified by <code>__id</code> or derives from the interface
+ * specified by <code>__id</code>.
+ **/
+ boolean ice_isA(String __id);
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param __id The type ID of the Slice interface to test against.
+ * @param __context The context map for the invocation.
+ * @return <code>true</code> if the target object has the interface
+ * specified by <code>__id</code> or derives from the interface
+ * specified by <code>__id</code>.
+ **/
+ boolean ice_isA(String __id, java.util.Map<String, String> __context);
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param __id The type ID of the Slice interface to test against.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_isA(String __id);
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param __id The type ID of the Slice interface to test against.
+ * @param __context The context map for the invocation.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_isA(String __id, java.util.Map<String, String> __context);
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param __id The type ID of the Slice interface to test against.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_isA(String __id, Callback __cb);
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param __id The type ID of the Slice interface to test against.
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_isA(String __id, java.util.Map<String, String> __context, Callback __cb);
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param __id The type ID of the Slice interface to test against.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_isA(String __id, Callback_Object_ice_isA __cb);
+
+ /**
+ * Tests whether this object supports a specific Slice interface.
+ *
+ * @param __id The type ID of the Slice interface to test against.
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_isA(String __id, java.util.Map<String, String> __context, Callback_Object_ice_isA __cb);
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_isA(String __id, IceInternal.Functional_BoolCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_isA(String __id, IceInternal.Functional_BoolCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __context The <code>Context</code> map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_isA(String __id, java.util.Map<String, String> __context,
+ IceInternal.Functional_BoolCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __context The <code>Context</code> map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_isA(String __id, java.util.Map<String, String> __context,
+ IceInternal.Functional_BoolCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Completes the asynchronous ice_isA request.
+ *
+ * @param __result The asynchronous result.
+ * @return <code>true</code> if this proxy supports the specified interface; <code>false</code>, otherwise.
+ **/
+ boolean end_ice_isA(AsyncResult __result);
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ **/
+ void ice_ping();
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ **/
+ void ice_ping(java.util.Map<String, String> __context);
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ping();
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ping(java.util.Map<String, String> __context);
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ping(Callback __cb);
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ping(java.util.Map<String, String> __context, Callback __cb);
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ping(Callback_Object_ice_ping __cb);
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ping(java.util.Map<String, String> __context, Callback_Object_ice_ping __cb);
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ping(IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ping(IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ping(java.util.Map<String, String> __context,
+ IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ping(java.util.Map<String, String> __context,
+ IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Completes the asynchronous ice_ping request.
+ *
+ * @param __result The asynchronous result.
+ **/
+ void end_ice_ping(AsyncResult __result);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @return The Slice type IDs of the interfaces supported by the target object, in base-to-derived
+ * order. The first element of the returned array is always <code>::Ice::Object</code>.
+ **/
+ String[] ice_ids();
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @return The Slice type IDs of the interfaces supported by the target object, in base-to-derived
+ * order. The first element of the returned array is always <code>::Ice::Object</code>.
+ **/
+ String[] ice_ids(java.util.Map<String, String> __context);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ids();
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ids(java.util.Map<String, String> __context);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ids(Callback __cb);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ids(java.util.Map<String, String> __context, Callback __cb);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ids(Callback_Object_ice_ids __cb);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ids(java.util.Map<String, String> __context, Callback_Object_ice_ids __cb);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ids(IceInternal.Functional_GenericCallback1<String[]> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ids(IceInternal.Functional_GenericCallback1<String[]> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ids(java.util.Map<String, String> __context,
+ IceInternal.Functional_GenericCallback1<String[]> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_ids(java.util.Map<String, String> __context,
+ IceInternal.Functional_GenericCallback1<String[]> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Completes the asynchronous ice_ids request.
+ *
+ * @param __result The asynchronous result.
+ * @return The Slice type IDs of the interfaces supported by the target object, in base-to-derived
+ * order. The first element of the returned array is always <code>::Ice::Object</code>.
+ **/
+ String[] end_ice_ids(AsyncResult __result);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @return The Slice type ID of the most-derived interface.
+ **/
+ String ice_id();
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @return The Slice type ID of the most-derived interface.
+ **/
+ String ice_id(java.util.Map<String, String> __context);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_id();
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_id(java.util.Map<String, String> __context);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_id(Callback __cb);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_id(java.util.Map<String, String> __context, Callback __cb);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_id(Callback_Object_ice_id __cb);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_id(java.util.Map<String, String> __context, Callback_Object_ice_id __cb);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_id(IceInternal.Functional_GenericCallback1<String> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_id(IceInternal.Functional_GenericCallback1<String> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_id(java.util.Map<String, String> __context,
+ IceInternal.Functional_GenericCallback1<String> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_id(java.util.Map<String, String> __context,
+ IceInternal.Functional_GenericCallback1<String> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Completes the asynchronous ice_id request.
+ *
+ * @param __result The asynchronous result.
+ * @return The Slice type ID of the most-derived interface.
+ **/
+ String end_ice_id(AsyncResult __result);
+
+ /**
+ * Invokes an operation dynamically.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * @param outParams The encoded out-paramaters and return value
+ * for the operation. The return value follows any out-parameters.
+ * @return If the operation completed successfully, the return value
+ * is <code>true</code>. If the operation raises a user exception,
+ * the return value is <code>false</code>; in this case, <code>outParams</code>
+ * contains the encoded user exception. If the operation raises a run-time exception,
+ * it throws it directly.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ boolean ice_invoke(String operation, OperationMode mode, byte[] inParams, ByteSeqHolder outParams);
+
+ /**
+ * Invokes an operation dynamically.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * @param outParams The encoded out-paramaters and return value
+ * for the operation. The return value follows any out-parameters.
+ * @param __context The context map for the invocation.
+ * @return If the operation completed successfully, the return value
+ * is <code>true</code>. If the operation raises a user exception,
+ * the return value is <code>false</code>; in this case, <code>outParams</code>
+ * contains the encoded user exception. If the operation raises a run-time exception,
+ * it throws it directly.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ boolean ice_invoke(String operation, OperationMode mode, byte[] inParams, ByteSeqHolder outParams,
+ java.util.Map<String, String> __context);
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams);
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __context The context map for the invocation.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ java.util.Map<String, String> __context);
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams, Callback __cb);
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ java.util.Map<String, String> __context, Callback __cb);
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ Callback_Object_ice_invoke __cb);
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ java.util.Map<String, String> __context, Callback_Object_ice_invoke __cb);
+
+ public interface FunctionalCallback_Object_ice_invoke_Response
+ {
+ void apply(boolean result, byte[] outArgs);
+ }
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ FunctionalCallback_Object_ice_invoke_Response __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ FunctionalCallback_Object_ice_invoke_Response __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * @param __context The context map for the invocation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ java.util.Map<String, String> __context,
+ FunctionalCallback_Object_ice_invoke_Response __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * @param __context The context map for the invocation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ java.util.Map<String, String> __context,
+ FunctionalCallback_Object_ice_invoke_Response __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Completes the asynchronous ice_invoke request.
+ *
+ * @param outParams The encoded out-paramaters and return value.
+ * @param __result The asynchronous result.
+ * @return If the operation completed successfully, the return value
+ * is <code>true</code>. If the operation raises a user exception,
+ * the return value is <code>false</code>; in this case, <code>outParams</code>
+ * contains the encoded user exception. If the operation raises a run-time exception,
+ * it throws it directly.
+ **/
+ boolean end_ice_invoke(ByteSeqHolder outParams, AsyncResult __result);
+
+ /**
+ * Returns the identity embedded in this proxy.
+ *
+ * @return The identity of the target object.
+ **/
+ Identity ice_getIdentity();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the identity.
+ *
+ * @param newIdentity The identity for the new proxy.
+ * @return The proxy with the new identity.
+ **/
+ ObjectPrx ice_identity(Identity newIdentity);
+
+ /**
+ * Returns the per-proxy context for this proxy.
+ *
+ * @return The per-proxy context. If the proxy does not have a per-proxy (implicit) context, the return value
+ * is <code>null</code>.
+ **/
+ java.util.Map<String, String> ice_getContext();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the per-proxy context.
+ *
+ * @param newContext The context for the new proxy.
+ * @return The proxy with the new per-proxy context.
+ **/
+ ObjectPrx ice_context(java.util.Map<String, String> newContext);
+
+ /**
+ * Returns the facet for this proxy.
+ *
+ * @return The facet for this proxy. If the proxy uses the default facet, the return value is the empty string.
+ **/
+ String ice_getFacet();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the facet.
+ *
+ * @param newFacet The facet for the new proxy.
+ * @return The proxy with the new facet.
+ **/
+ ObjectPrx ice_facet(String newFacet);
+
+ /**
+ * Returns the adapter ID for this proxy.
+ *
+ * @return The adapter ID. If the proxy does not have an adapter ID, the return value is the empty string.
+ **/
+ String ice_getAdapterId();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the adapter ID.
+ *
+ * @param newAdapterId The adapter ID for the new proxy.
+ * @return The proxy with the new adapter ID.
+ **/
+ ObjectPrx ice_adapterId(String newAdapterId);
+
+ /**
+ * Returns the endpoints used by this proxy.
+ *
+ * @return The endpoints used by this proxy.
+ *
+ * @see Endpoint
+ **/
+ Endpoint[] ice_getEndpoints();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the endpoints.
+ *
+ * @param newEndpoints The endpoints for the new proxy.
+ * @return The proxy with the new endpoints.
+ **/
+ ObjectPrx ice_endpoints(Endpoint[] newEndpoints);
+
+ /**
+ * Returns the locator cache timeout of this proxy.
+ *
+ * @return The locator cache timeout value (in seconds).
+ *
+ * @see Locator
+ **/
+ int ice_getLocatorCacheTimeout();
+
+ /**
+ * Returns the invocation timeout of this proxy.
+ *
+ * @return The invocation timeout value (in seconds).
+ **/
+ int ice_getInvocationTimeout();
+
+ /**
+ * Returns the connection id of this proxy.
+ *
+ * @return The connection id.
+ *
+ **/
+ String ice_getConnectionId();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the locator cache timeout.
+ *
+ * @param newTimeout The new locator cache timeout (in seconds).
+ *
+ * @see Locator
+ **/
+ ObjectPrx ice_locatorCacheTimeout(int newTimeout);
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the invocation timeout.
+ *
+ * @param newTimeout The new invocation timeout (in seconds).
+ *
+ **/
+ ObjectPrx ice_invocationTimeout(int newTimeout);
+
+ /**
+ * Returns whether this proxy caches connections.
+ *
+ * @return <code>true</code> if this proxy caches connections; <code>false</code>, otherwise.
+ **/
+ boolean ice_isConnectionCached();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for connection caching.
+ *
+ * @param newCache <code>true</code> if the new proxy should cache connections; <code>false</code>, otherwise.
+ * @return The new proxy with the specified caching policy.
+ **/
+ ObjectPrx ice_connectionCached(boolean newCache);
+
+ /**
+ * Returns how this proxy selects endpoints (randomly or ordered).
+ *
+ * @return The endpoint selection policy.
+ *
+ * @see EndpointSelectionType
+ **/
+ EndpointSelectionType ice_getEndpointSelection();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the endpoint selection policy.
+ *
+ * @param newType The new endpoint selection policy.
+ * @return The new proxy with the specified endpoint selection policy.
+ *
+ * @see EndpointSelectionType
+ **/
+ ObjectPrx ice_endpointSelection(EndpointSelectionType newType);
+
+ /**
+ * Returns whether this proxy uses only secure endpoints.
+ *
+ * @return <code>True</code> if this proxy communicates only via secure endpoints; <code>false</code>, otherwise.
+ **/
+ boolean ice_isSecure();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for how it selects endpoints.
+ *
+ * @param b If <code>b</code> is <code>true</code>, only endpoints that use a secure transport are
+ * used by the new proxy. If <code>b</code> is false, the returned proxy uses both secure and insecure
+ * endpoints.
+ * @return The new proxy with the specified selection policy.
+ **/
+ ObjectPrx ice_secure(boolean b);
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the encoding used to marshal
+ * parameters.
+ *
+ * @param e The encoding version to use to marshal requests parameters.
+ * @return The new proxy with the specified encoding version.
+ **/
+ ObjectPrx ice_encodingVersion(Ice.EncodingVersion e);
+
+ /**
+ * Returns the encoding version used to marshal requests parameters.
+ *
+ * @return The encoding version.
+ **/
+ Ice.EncodingVersion ice_getEncodingVersion();
+
+ /**
+ * Returns whether this proxy prefers secure endpoints.
+ *
+ * @return <code>true</code> if the proxy always attempts to invoke via secure endpoints before it
+ * attempts to use insecure endpoints; <code>false</code>, otherwise.
+ **/
+ boolean ice_isPreferSecure();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for its endpoint selection policy.
+ *
+ * @param b If <code>b</code> is <code>true</code>, the new proxy will use secure endpoints for invocations
+ * and only use insecure endpoints if an invocation cannot be made via secure endpoints. If <code>b</code> is
+ * <code>false</code>, the proxy prefers insecure endpoints to secure ones.
+ * @return The new proxy with the new endpoint selection policy.
+ **/
+ ObjectPrx ice_preferSecure(boolean b);
+
+ /**
+ * Returns the router for this proxy.
+ *
+ * @return The router for the proxy. If no router is configured for the proxy, the return value
+ * is <code>null</code>.
+ **/
+ Ice.RouterPrx ice_getRouter();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the router.
+ *
+ * @param router The router for the new proxy.
+ * @return The new proxy with the specified router.
+ **/
+ ObjectPrx ice_router(Ice.RouterPrx router);
+
+ /**
+ * Returns the locator for this proxy.
+ *
+ * @return The locator for this proxy. If no locator is configured, the return value is <code>null</code>.
+ **/
+ Ice.LocatorPrx ice_getLocator();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the locator.
+ *
+ * @param locator The locator for the new proxy.
+ * @return The new proxy with the specified locator.
+ **/
+ ObjectPrx ice_locator(Ice.LocatorPrx locator);
+
+ /**
+ * Returns whether this proxy uses collocation optimization.
+ *
+ * @return <code>true</code> if the proxy uses collocation optimization; <code>false</code>, otherwise.
+ **/
+ boolean ice_isCollocationOptimized();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for collocation optimization.
+ *
+ * @param b <code>true</code> if the new proxy enables collocation optimization; <code>false</code>, otherwise.
+ * @return The new proxy the specified collocation optimization.
+ **/
+ ObjectPrx ice_collocationOptimized(boolean b);
+
+ /**
+ * Creates a new proxy that is identical to this proxy, but uses twoway invocations.
+ *
+ * @return A new proxy that uses twoway invocations.
+ **/
+ ObjectPrx ice_twoway();
+
+ /**
+ * Returns whether this proxy uses twoway invocations.
+ * @return <code>true</code> if this proxy uses twoway invocations; <code>false</code>, otherwise.
+ **/
+ boolean ice_isTwoway();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, but uses oneway invocations.
+ *
+ * @return A new proxy that uses oneway invocations.
+ **/
+ ObjectPrx ice_oneway();
+
+ /**
+ * Returns whether this proxy uses oneway invocations.
+ * @return <code>true</code> if this proxy uses oneway invocations; <code>false</code>, otherwise.
+ **/
+ boolean ice_isOneway();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, but uses batch oneway invocations.
+ *
+ * @return A new proxy that uses batch oneway invocations.
+ **/
+ ObjectPrx ice_batchOneway();
+
+ /**
+ * Returns whether this proxy uses batch oneway invocations.
+ * @return <code>true</code> if this proxy uses batch oneway invocations; <code>false</code>, otherwise.
+ **/
+ boolean ice_isBatchOneway();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, but uses datagram invocations.
+ *
+ * @return A new proxy that uses datagram invocations.
+ **/
+ ObjectPrx ice_datagram();
+
+ /**
+ * Returns whether this proxy uses datagram invocations.
+ * @return <code>true</code> if this proxy uses datagram invocations; <code>false</code>, otherwise.
+ **/
+ boolean ice_isDatagram();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, but uses batch datagram invocations.
+ *
+ * @return A new proxy that uses batch datagram invocations.
+ **/
+ ObjectPrx ice_batchDatagram();
+
+ /**
+ * Returns whether this proxy uses batch datagram invocations.
+ * @return <code>true</code> if this proxy uses batch datagram invocations; <code>false</code>, otherwise.
+ **/
+ boolean ice_isBatchDatagram();
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for compression.
+ *
+ * @param co <code>true</code> enables compression for the new proxy; <code>false</code> disables compression.
+ * @return A new proxy with the specified compression setting.
+ **/
+ ObjectPrx ice_compress(boolean co);
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for its timeout setting.
+ *
+ * @param t The timeout for the new proxy in milliseconds.
+ * @return A new proxy with the specified timeout.
+ **/
+ ObjectPrx ice_timeout(int t);
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for its connection ID.
+ *
+ * @param connectionId The connection ID for the new proxy. An empty string removes the
+ * connection ID.
+ *
+ * @return A new proxy with the specified connection ID.
+ **/
+ ObjectPrx ice_connectionId(String connectionId);
+
+ /**
+ * Returns the {@link Connection} for this proxy. If the proxy does not yet have an established connection,
+ * it first attempts to create a connection.
+ *
+ * @return The {@link Connection} for this proxy.
+ * @throws CollocationOptimizationException If the proxy uses collocation optimization and denotes a
+ * collocated object.
+ *
+ * @see Connection
+ **/
+ Connection ice_getConnection();
+
+ /**
+ * Asynchronously gets the connection for this proxy. The call does not block.
+ *
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_getConnection();
+
+ /**
+ * Asynchronously gets the connection for this proxy. The call does not block.
+ *
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_getConnection(Callback __cb);
+
+ /**
+ * Asynchronously gets the connection for this proxy. The call does not block.
+ *
+ * @param __cb The callback object to notify the application when the operation is complete.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_getConnection(Callback_Object_ice_getConnection __cb);
+
+ /**
+ * Asynchronously gets the connection for this proxy. The call does not block.
+ *
+ * @param __responseCb The callback object to notify the application when there is a response available.
+ * @param __exceptionCb The callback object to notify the application when an exception occurs while getting
+ * the connection.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_getConnection(IceInternal.Functional_GenericCallback1<Ice.Connection> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb);
+
+ /**
+ * Completes the asynchronous get connection.
+ *
+ * @param __result The asynchronous result.
+ **/
+ Ice.Connection end_ice_getConnection(AsyncResult __result);
+
+ /**
+ * Returns the cached {@link Connection} for this proxy. If the proxy does not yet have an established
+ * connection, it does not attempt to create a connection.
+ *
+ * @return The cached {@link Connection} for this proxy (<code>null</code> if the proxy does not have
+ * an established connection).
+ * @throws CollocationOptimizationException If the proxy uses collocation optimization and denotes a
+ * collocated object.
+ *
+ * @see Connection
+ **/
+ Connection ice_getCachedConnection();
+
+ /**
+ * Flushes any pending batched requests for this communicator. The call blocks until the flush is complete.
+ **/
+ void ice_flushBatchRequests();
+
+ /**
+ * Asynchronously flushes any pending batched requests for this communicator. The call does not block.
+ *
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_flushBatchRequests();
+
+ /**
+ * Asynchronously flushes any pending batched requests for this communicator. The call does not block.
+ *
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_flushBatchRequests(Callback __cb);
+
+ /**
+ * Asynchronously flushes any pending batched requests for this communicator. The call does not block.
+ *
+ * @param __cb The callback object to notify the application when the flush is complete.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_flushBatchRequests(Callback_Object_ice_flushBatchRequests __cb);
+
+ /**
+ * Asynchronously flushes any pending batched requests for this communicator. The call does not block.
+ *
+ * @param __responseCb The asynchronous completion callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ AsyncResult begin_ice_flushBatchRequests(IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb);
+
+ /**
+ * Completes the asynchronous flush request.
+ *
+ * @param __result The asynchronous result.
+ **/
+ void end_ice_flushBatchRequests(AsyncResult __result);
+
+ /**
+ * Returns whether this proxy equals the passed object. Two proxies are equal if they are equal in all respects,
+ * that is, if their object identity, endpoints timeout settings, and so on are all equal.
+ *
+ * @param r The object to compare this proxy with.
+ * @return <code>true</code> if this proxy is equal to <code>r</code>; <code>false</code>, otherwise.
+ **/
+ @Override
+ boolean equals(java.lang.Object r);
+
+ void __write(OutputStream os);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectPrxHelper.java b/java-compat/src/Ice/src/main/java/Ice/ObjectPrxHelper.java
new file mode 100644
index 00000000000..77c758ef68e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectPrxHelper.java
@@ -0,0 +1,157 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class for all proxy helpers.
+ **/
+public class ObjectPrxHelper extends ObjectPrxHelperBase
+{
+ /**
+ * Casts a proxy to {@link Ice.ObjectPrx}. This call contacts
+ * the server and will throw an Ice run-time exception if the target
+ * object does not exist or the server cannot be reached.
+ *
+ * @param b The proxy to cast to @{link Ice.ObjectPrx}.
+ * @return <code>b</code>.
+ **/
+ public static ObjectPrx
+ checkedCast(Ice.ObjectPrx b)
+ {
+ return b;
+ }
+
+ /**
+ * Casts a proxy to {@link Ice.ObjectPrx}. This call contacts
+ * the server and throws an Ice run-time exception if the target
+ * object does not exist or the server cannot be reached.
+ *
+ * @param b The proxy to cast to {@link Ice.ObjectPrx}.
+ * @param ctx The <code>Context</code> map for the invocation.
+ * @return <code>b</code>.
+ **/
+ public static ObjectPrx
+ checkedCast(Ice.ObjectPrx b, java.util.Map<String, String> ctx)
+ {
+ return b;
+ }
+
+ /**
+ * Creates a new proxy that is identical to the passed proxy, except
+ * for its facet. This call contacts
+ * the server and throws an Ice run-time exception if the target
+ * object does not exist, the specified facet does not exist, or the server cannot be reached.
+ *
+ * @param b The proxy to cast to {@link Ice.ObjectPrx}.
+ * @param f The facet for the new proxy.
+ * @return The new proxy with the specified facet.
+ **/
+ public static ObjectPrx
+ checkedCast(Ice.ObjectPrx b, String f)
+ {
+ ObjectPrx d = null;
+ if(b != null)
+ {
+ Ice.ObjectPrx bb = b.ice_facet(f);
+ try
+ {
+ boolean ok = bb.ice_isA("::Ice::Object");
+ assert(ok);
+ ObjectPrxHelper h = new ObjectPrxHelper();
+ h.__copyFrom(bb);
+ d = h;
+ }
+ catch(Ice.FacetNotExistException ex)
+ {
+ }
+ }
+ return d;
+ }
+
+ /**
+ * Creates a new proxy that is identical to the passed proxy, except
+ * for its facet. This call contacts
+ * the server and throws an Ice run-time exception if the target
+ * object does not exist, the specified facet does not exist, or the server cannot be reached.
+ *
+ * @param b The proxy to cast to {@link Ice.ObjectPrx}.
+ * @param f The facet for the new proxy.
+ * @param ctx The <code>Context</code> map for the invocation.
+ * @return The new proxy with the specified facet.
+ **/
+ public static ObjectPrx
+ checkedCast(Ice.ObjectPrx b, String f, java.util.Map<String, String> ctx)
+ {
+ ObjectPrx d = null;
+ if(b != null)
+ {
+ Ice.ObjectPrx bb = b.ice_facet(f);
+ try
+ {
+ boolean ok = bb.ice_isA("::Ice::Object", ctx);
+ assert(ok);
+ ObjectPrxHelper h = new ObjectPrxHelper();
+ h.__copyFrom(bb);
+ d = h;
+ }
+ catch(Ice.FacetNotExistException ex)
+ {
+ }
+ }
+ return d;
+ }
+
+ /**
+ * Casts a proxy to {@link Ice.ObjectPrx}. This call does
+ * not contact the server and always succeeds.
+ *
+ * @param b The proxy to cast to {@link Ice.ObjectPrx}.
+ * @return <code>b</code>.
+ **/
+ public static ObjectPrx
+ uncheckedCast(Ice.ObjectPrx b)
+ {
+ return b;
+ }
+
+ /**
+ * Creates a new proxy that is identical to the passed proxy, except
+ * for its facet. This call does not contact the server and always succeeds.
+ *
+ * @param b The proxy to cast to {@link Ice.ObjectPrx}.
+ * @param f The facet for the new proxy.
+ * @return The new proxy with the specified facet.
+ **/
+ public static ObjectPrx
+ uncheckedCast(Ice.ObjectPrx b, String f)
+ {
+ ObjectPrx d = null;
+ if(b != null)
+ {
+ Ice.ObjectPrx bb = b.ice_facet(f);
+ ObjectPrxHelper h = new ObjectPrxHelper();
+ h.__copyFrom(bb);
+ d = h;
+ }
+ return d;
+ }
+
+ /**
+ * Returns the Slice type id of the interface or class associated
+ * with this proxy class.
+ *
+ * @return the type id, "::Ice::Object"
+ **/
+ public static String
+ ice_staticId()
+ {
+ return Ice.ObjectImpl.ice_staticId();
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectPrxHelperBase.java b/java-compat/src/Ice/src/main/java/Ice/ObjectPrxHelperBase.java
new file mode 100644
index 00000000000..fa60f0a62f2
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectPrxHelperBase.java
@@ -0,0 +1,3000 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import Ice.Instrumentation.InvocationObserver;
+import IceInternal.RetryException;
+
+/**
+ * Base class for all proxies.
+ **/
+public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
+{
+ /**
+ * Returns a hash code for this proxy.
+ *
+ * @return The hash code.
+ **/
+ @Override
+ public final int
+ hashCode()
+ {
+ return _reference.hashCode();
+ }
+
+ /**
+ * Returns the communicator that created this proxy.
+ *
+ * @return The communicator that created this proxy.
+ **/
+ @Override
+ public final Communicator
+ ice_getCommunicator()
+ {
+ return _reference.getCommunicator();
+ }
+
+ /**
+ * Returns the stringified form of this proxy.
+ *
+ * @return The stringified proxy.
+ **/
+ @Override
+ public final String
+ toString()
+ {
+ return _reference.toString();
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @return <code>true</code> if this proxy supports the specified interface; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ ice_isA(String __id)
+ {
+ return ice_isA(__id, null, false);
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __context The <code>Context</code> map for the invocation.
+ * @return <code>true</code> if this proxy supports the specified interface; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ ice_isA(String __id, java.util.Map<String, String> __context)
+ {
+ return ice_isA(__id, __context, true);
+ }
+
+ private static final String __ice_isA_name = "ice_isA";
+
+ private boolean
+ ice_isA(String __id, java.util.Map<String, String> __context, boolean __explicitCtx)
+ {
+ __checkTwowayOnly(__ice_isA_name);
+ return end_ice_isA(begin_ice_isA(__id, __context, __explicitCtx, true, null));
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_isA(String __id)
+ {
+ return begin_ice_isA(__id, null, false, false, null);
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __context The <code>Context</code> map for the invocation.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_isA(String __id, java.util.Map<String, String> __context)
+ {
+ return begin_ice_isA(__id, __context, true, false, null);
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_isA(String __id, Callback __cb)
+ {
+ return begin_ice_isA(__id, null, false, false, __cb);
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __context The <code>Context</code> map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_isA(String __id, java.util.Map<String, String> __context, Callback __cb)
+ {
+ return begin_ice_isA(__id, __context, true, false, __cb);
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_isA(String __id, Callback_Object_ice_isA __cb)
+ {
+ return begin_ice_isA(__id, null, false, false, __cb);
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __context The <code>Context</code> map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_isA(String __id, java.util.Map<String, String> __context, Callback_Object_ice_isA __cb)
+ {
+ return begin_ice_isA(__id, __context, true, false, __cb);
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_isA(String __id,
+ IceInternal.Functional_BoolCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb)
+ {
+ return begin_ice_isA(__id, null, false, false, __responseCb, __exceptionCb, null);
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_isA(String __id,
+ IceInternal.Functional_BoolCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_ice_isA(__id, null, false, false, __responseCb, __exceptionCb, __sentCb);
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __context The <code>Context</code> map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_isA(String __id,
+ java.util.Map<String, String> __context,
+ IceInternal.Functional_BoolCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb)
+ {
+ return begin_ice_isA(__id, __context, true, false, __responseCb, __exceptionCb, null);
+ }
+
+ /**
+ * Tests whether this proxy supports a given interface.
+ *
+ * @param __id The Slice type ID of an interface.
+ * @param __context The <code>Context</code> map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_isA(String __id,
+ java.util.Map<String, String> __context,
+ IceInternal.Functional_BoolCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_ice_isA(__id, __context, true, false, __responseCb, __exceptionCb, __sentCb);
+ }
+
+ private AsyncResult
+ begin_ice_isA(String __id,
+ java.util.Map<String, String> __context,
+ boolean __explicitCtx,
+ boolean __synchronous,
+ IceInternal.Functional_BoolCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_ice_isA(__id, __context, __explicitCtx, __synchronous,
+ new IceInternal.Functional_TwowayCallbackBool(__responseCb, __exceptionCb, __sentCb)
+ {
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ ObjectPrxHelperBase.__ice_isA_completed(this, __result);
+ }
+ });
+ }
+
+ private AsyncResult
+ begin_ice_isA(String __id, java.util.Map<String, String> __context, boolean __explicitCtx,
+ boolean __synchronous, IceInternal.CallbackBase __cb)
+ {
+ __checkAsyncTwowayOnly(__ice_isA_name);
+ IceInternal.OutgoingAsync __result = getOutgoingAsync(__ice_isA_name, __cb);
+ try
+ {
+ __result.prepare(__ice_isA_name, OperationMode.Nonmutating, __context, __explicitCtx, __synchronous);
+ OutputStream __os = __result.startWriteParams(Ice.FormatType.DefaultFormat);
+ __os.writeString(__id);
+ __result.endWriteParams();
+ __result.invoke();
+ }
+ catch(Exception __ex)
+ {
+ __result.abort(__ex);
+ }
+ return __result;
+ }
+
+ /**
+ * Completes the asynchronous ice_isA request.
+ *
+ * @param __r The asynchronous result.
+ * @return <code>true</code> if this proxy supports the specified interface; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ end_ice_isA(AsyncResult __r)
+ {
+ IceInternal.OutgoingAsync __result = IceInternal.OutgoingAsync.check(__r, this, __ice_isA_name);
+ try
+ {
+ if(!__result.__wait())
+ {
+ try
+ {
+ __result.throwUserException();
+ }
+ catch(UserException __ex)
+ {
+ throw new UnknownUserException(__ex.ice_id(), __ex);
+ }
+ }
+ boolean __ret;
+ InputStream __is = __result.startReadParams();
+ __ret = __is.readBool();
+ __result.endReadParams();
+ return __ret;
+ }
+ finally
+ {
+ if(__result != null)
+ {
+ __result.cacheMessageBuffers();
+ }
+ }
+ }
+
+ static public void __ice_isA_completed(TwowayCallbackBool __cb, AsyncResult __result)
+ {
+ boolean __ret = false;
+ try
+ {
+ __ret = __result.getProxy().end_ice_isA(__result);
+ }
+ catch(LocalException __ex)
+ {
+ __cb.exception(__ex);
+ return;
+ }
+ catch(SystemException __ex)
+ {
+ __cb.exception(__ex);
+ return;
+ }
+ __cb.response(__ret);
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ **/
+ @Override
+ public final void
+ ice_ping()
+ {
+ ice_ping(null, false);
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The <code>Context</code> map for the invocation.
+ **/
+ @Override
+ public final void
+ ice_ping(java.util.Map<String, String> __context)
+ {
+ ice_ping(__context, true);
+ }
+
+ private static final String __ice_ping_name = "ice_ping";
+
+ private void
+ ice_ping(java.util.Map<String, String> __context, boolean __explicitCtx)
+ {
+ end_ice_ping(begin_ice_ping(__context, __explicitCtx, true, null));
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ping()
+ {
+ return begin_ice_ping(null, false, false, null);
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ping(java.util.Map<String, String> __context)
+ {
+ return begin_ice_ping(__context, true, false, null);
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ping(Callback __cb)
+ {
+ return begin_ice_ping(null, false, false, __cb);
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ping(java.util.Map<String, String> __context, Callback __cb)
+ {
+ return begin_ice_ping(__context, true, false, __cb);
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ping(Callback_Object_ice_ping __cb)
+ {
+ return begin_ice_ping(null, false, false, __cb);
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ping(java.util.Map<String, String> __context, Callback_Object_ice_ping __cb)
+ {
+ return begin_ice_ping(__context, true, false, __cb);
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ping(IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb)
+ {
+ return begin_ice_ping(null, false, false,
+ new IceInternal.Functional_OnewayCallback(__responseCb, __exceptionCb, null));
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ping(IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_ice_ping(null, false, false, new IceInternal.Functional_OnewayCallback(__responseCb,
+ __exceptionCb, __sentCb));
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ping(java.util.Map<String, String> __context,
+ IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb)
+ {
+ return begin_ice_ping(__context, true, false, new IceInternal.Functional_OnewayCallback(__responseCb,
+ __exceptionCb, null));
+ }
+
+ /**
+ * Tests whether the target object of this proxy can be reached.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ping(java.util.Map<String, String> __context,
+ IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_ice_ping(__context, true, false,
+ new IceInternal.Functional_OnewayCallback(__responseCb, __exceptionCb, __sentCb));
+ }
+
+ private AsyncResult begin_ice_ping(java.util.Map<String, String> __context, boolean __explicitCtx,
+ boolean __synchronous, IceInternal.CallbackBase __cb)
+ {
+ IceInternal.OutgoingAsync __result = getOutgoingAsync(__ice_ping_name, __cb);
+ try
+ {
+ __result.prepare(__ice_ping_name, OperationMode.Nonmutating, __context, __explicitCtx, __synchronous);
+ __result.writeEmptyParams();
+ __result.invoke();
+ }
+ catch(Exception __ex)
+ {
+ __result.abort(__ex);
+ }
+ return __result;
+ }
+
+ /**
+ * Completes the asynchronous ping request.
+ *
+ * @param __result The asynchronous result.
+ **/
+ @Override
+ public final void
+ end_ice_ping(AsyncResult __result)
+ {
+ __end(__result, __ice_ping_name);
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @return The Slice type IDs of the interfaces supported by the target object, in base-to-derived
+ * order. The first element of the returned array is always <code>::Ice::Object</code>.
+ **/
+ @Override
+ public final String[]
+ ice_ids()
+ {
+ return ice_ids(null, false);
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The <code>Context</code> map for the invocation.
+ * @return The Slice type IDs of the interfaces supported by the target object, in base-to-derived
+ * order. The first element of the returned array is always <code>::Ice::Object</code>.
+ **/
+ @Override
+ public final String[]
+ ice_ids(java.util.Map<String, String> __context)
+ {
+ return ice_ids(__context, true);
+ }
+
+ private static final String __ice_ids_name = "ice_ids";
+
+ private String[]
+ ice_ids(java.util.Map<String, String> __context, boolean __explicitCtx)
+ {
+ __checkTwowayOnly(__ice_id_name);
+ return end_ice_ids(begin_ice_ids(__context, __explicitCtx, true, null));
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ids()
+ {
+ return begin_ice_ids(null, false, false, null);
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ids(java.util.Map<String, String> __context)
+ {
+ return begin_ice_ids(__context, true, false, null);
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ids(Callback __cb)
+ {
+ return begin_ice_ids(null, false, false,__cb);
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ids(java.util.Map<String, String> __context, Callback __cb)
+ {
+ return begin_ice_ids(__context, true, false,__cb);
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ids(Callback_Object_ice_ids __cb)
+ {
+ return begin_ice_ids(null, false, false,__cb);
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ids(java.util.Map<String, String> __context, Callback_Object_ice_ids __cb)
+ {
+ return begin_ice_ids(__context, true, false,__cb);
+ }
+
+ private class FunctionalCallback_Object_ice_ids extends IceInternal.Functional_TwowayCallbackArg1<String[]>
+ {
+ FunctionalCallback_Object_ice_ids(IceInternal.Functional_GenericCallback1<String[]> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ super(__responseCb, __exceptionCb, __sentCb);
+ }
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ ObjectPrxHelperBase.__ice_ids_completed(this, __result);
+ }
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ids(IceInternal.Functional_GenericCallback1<String[]> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb)
+ {
+ return begin_ice_ids(null, false, false, new FunctionalCallback_Object_ice_ids(__responseCb, __exceptionCb,
+ null));
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ids(IceInternal.Functional_GenericCallback1<String[]> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_ice_ids(null, false, false, new FunctionalCallback_Object_ice_ids(__responseCb, __exceptionCb,
+ __sentCb));
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ids(java.util.Map<String, String> __context,
+ IceInternal.Functional_GenericCallback1<String[]> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb)
+ {
+ return begin_ice_ids(__context, true, false, new FunctionalCallback_Object_ice_ids(__responseCb, __exceptionCb,
+ null));
+ }
+
+ /**
+ * Returns the Slice type IDs of the interfaces supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_ids(java.util.Map<String, String> __context,
+ IceInternal.Functional_GenericCallback1<String[]> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_ice_ids(__context, true, false,
+ new FunctionalCallback_Object_ice_ids(__responseCb, __exceptionCb, __sentCb));
+ }
+
+ private AsyncResult begin_ice_ids(java.util.Map<String, String> __context, boolean __explicitCtx,
+ boolean __synchronous, IceInternal.CallbackBase __cb)
+ {
+ __checkAsyncTwowayOnly(__ice_ids_name);
+ IceInternal.OutgoingAsync __result = getOutgoingAsync(__ice_ids_name, __cb);
+ try
+ {
+ __result.prepare(__ice_ids_name, OperationMode.Nonmutating, __context, __explicitCtx, __synchronous);
+ __result.writeEmptyParams();
+ __result.invoke();
+ }
+ catch(Exception __ex)
+ {
+ __result.abort(__ex);
+ }
+ return __result;
+ }
+
+ /**
+ * Completes the asynchronous ice_ids request.
+ *
+ * @param __r The asynchronous result.
+ * @return The Slice type IDs of the interfaces supported by the target object, in base-to-derived
+ * order. The first element of the returned array is always <code>::Ice::Object</code>.
+ **/
+ @Override
+ public final String[]
+ end_ice_ids(AsyncResult __r)
+ {
+ IceInternal.OutgoingAsync __result = IceInternal.OutgoingAsync.check(__r, this, __ice_ids_name);
+ try
+ {
+ if(!__result.__wait())
+ {
+ try
+ {
+ __result.throwUserException();
+ }
+ catch(UserException __ex)
+ {
+ throw new UnknownUserException(__ex.ice_id(), __ex);
+ }
+ }
+ String[] __ret = null;
+ InputStream __is = __result.startReadParams();
+ __ret = StringSeqHelper.read(__is);
+ __result.endReadParams();
+ return __ret;
+ }
+ finally
+ {
+ if(__result != null)
+ {
+ __result.cacheMessageBuffers();
+ }
+ }
+ }
+
+ static public void __ice_ids_completed(TwowayCallbackArg1<String[]> __cb, AsyncResult __result)
+ {
+ String[] __ret = null;
+ try
+ {
+ __ret = __result.getProxy().end_ice_ids(__result);
+ }
+ catch(LocalException __ex)
+ {
+ __cb.exception(__ex);
+ return;
+ }
+ catch(SystemException __ex)
+ {
+ __cb.exception(__ex);
+ return;
+ }
+ __cb.response(__ret);
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @return The Slice type ID of the most-derived interface.
+ **/
+ @Override
+ public final String
+ ice_id()
+ {
+ return ice_id(null, false);
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The <code>Context</code> map for the invocation.
+ * @return The Slice type ID of the most-derived interface.
+ **/
+ @Override
+ public final String
+ ice_id(java.util.Map<String, String> __context)
+ {
+ return ice_id(__context, true);
+ }
+
+ private static final String __ice_id_name = "ice_id";
+
+ private String
+ ice_id(java.util.Map<String, String> __context, boolean __explicitCtx)
+ {
+ __checkTwowayOnly(__ice_id_name);
+ return end_ice_id(begin_ice_id(__context, __explicitCtx, true, null));
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_id()
+ {
+ return begin_ice_id(null, false, false, null);
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_id(java.util.Map<String, String> __context)
+ {
+ return begin_ice_id(__context, true, false, null);
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_id(Callback __cb)
+ {
+ return begin_ice_id(null, false, false, __cb);
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_id(java.util.Map<String, String> __context, Callback __cb)
+ {
+ return begin_ice_id(__context, true, false, __cb);
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_id(Callback_Object_ice_id __cb)
+ {
+ return begin_ice_id(null, false, false, __cb);
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_id(java.util.Map<String, String> __context, Callback_Object_ice_id __cb)
+ {
+ return begin_ice_id(__context, true, false, __cb);
+ }
+
+ private class FunctionalCallback_Object_ice_id extends IceInternal.Functional_TwowayCallbackArg1<String>
+ {
+ FunctionalCallback_Object_ice_id(IceInternal.Functional_GenericCallback1<String> responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ IceInternal.Functional_BoolCallback sentCb)
+ {
+ super(responseCb, exceptionCb, sentCb);
+ }
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ ObjectPrxHelperBase.__ice_id_completed(this, __result);
+ }
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_id(IceInternal.Functional_GenericCallback1<String> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb)
+ {
+ return begin_ice_id(null, false, false, new FunctionalCallback_Object_ice_id(__responseCb, __exceptionCb, null));
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_id(IceInternal.Functional_GenericCallback1<String> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_ice_id(null, false, false, new FunctionalCallback_Object_ice_id(__responseCb, __exceptionCb, __sentCb));
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_id(java.util.Map<String, String> __context,
+ IceInternal.Functional_GenericCallback1<String> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb)
+ {
+ return begin_ice_id(__context, true, false, new FunctionalCallback_Object_ice_id(__responseCb, __exceptionCb, null));
+ }
+
+ /**
+ * Returns the Slice type ID of the most-derived interface supported by the target object of this proxy.
+ *
+ * @param __context The context map for the invocation.
+ * @param __responseCb The asynchronous response callback object.
+ * @param __exceptionCb The asynchronous exception callback object.
+ * @param __sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_id(java.util.Map<String, String> __context,
+ IceInternal.Functional_GenericCallback1<String> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_ice_id(__context, true, false,
+ new FunctionalCallback_Object_ice_id(__responseCb, __exceptionCb, __sentCb));
+ }
+
+ private AsyncResult begin_ice_id(java.util.Map<String, String> __context, boolean __explicitCtx,
+ boolean __synchronous, IceInternal.CallbackBase __cb)
+ {
+ __checkAsyncTwowayOnly(__ice_id_name);
+ IceInternal.OutgoingAsync __result = getOutgoingAsync(__ice_id_name, __cb);
+ try
+ {
+ __result.prepare(__ice_id_name, OperationMode.Nonmutating, __context, __explicitCtx, __synchronous);
+ __result.writeEmptyParams();
+ __result.invoke();
+ }
+ catch(Exception __ex)
+ {
+ __result.abort(__ex);
+ }
+ return __result;
+ }
+
+ /**
+ * Completes the asynchronous ice_id request.
+ *
+ * @param __r The asynchronous result.
+ * @return The Slice type ID of the most-derived interface.
+ **/
+ @Override
+ public final String
+ end_ice_id(AsyncResult __r)
+ {
+ IceInternal.OutgoingAsync __result = IceInternal.OutgoingAsync.check(__r, this, __ice_id_name);
+ try
+ {
+ if(!__result.__wait())
+ {
+ try
+ {
+ __result.throwUserException();
+ }
+ catch(UserException __ex)
+ {
+ throw new UnknownUserException(__ex.ice_id(), __ex);
+ }
+ }
+ String __ret = null;
+ InputStream __is = __result.startReadParams();
+ __ret = __is.readString();
+ __result.endReadParams();
+ return __ret;
+ }
+ finally
+ {
+ if(__result != null)
+ {
+ __result.cacheMessageBuffers();
+ }
+ }
+ }
+
+ static public void __ice_id_completed(TwowayCallbackArg1<String> __cb, AsyncResult __result)
+ {
+ String __ret = null;
+ try
+ {
+ __ret = __result.getProxy().end_ice_id(__result);
+ }
+ catch(LocalException __ex)
+ {
+ __cb.exception(__ex);
+ return;
+ }
+ catch(SystemException __ex)
+ {
+ __cb.exception(__ex);
+ return;
+ }
+ __cb.response(__ret);
+ }
+
+ /**
+ * Invoke an operation dynamically.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * @param outParams The encoded out-paramaters and return value
+ * for the operation. The return value follows any out-parameters.
+ * @return If the operation completed successfully, the return value
+ * is <code>true</code>. If the operation raises a user exception,
+ * the return value is <code>false</code>; in this case, <code>outParams</code>
+ * contains the encoded user exception. If the operation raised an
+ * it throws it directly.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final boolean
+ ice_invoke(String operation, OperationMode mode, byte[] inParams, ByteSeqHolder outParams)
+ {
+ return ice_invoke(operation, mode, inParams, outParams, null, false);
+ }
+
+ /**
+ * Invoke an operation dynamically.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * @param outParams The encoded out-paramaters and return value
+ * for the operation. The return value follows any out-parameters.
+ * @param context The context map for the invocation.
+ * @return If the operation was invoked synchronously (because there
+ * was no need to queue the request), the return value is <code>true</code>;
+ * otherwise, if the invocation was queued, the return value is <code>false</code>.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final boolean
+ ice_invoke(String operation, OperationMode mode, byte[] inParams, ByteSeqHolder outParams,
+ java.util.Map<String, String> context)
+ {
+ return ice_invoke(operation, mode, inParams, outParams, context, true);
+ }
+
+ private boolean
+ ice_invoke(String operation, OperationMode mode, byte[] inParams, ByteSeqHolder outParams,
+ java.util.Map<String, String> context, boolean explicitCtx)
+ {
+ return end_ice_invoke(outParams, begin_ice_invoke(operation, mode, inParams, context, explicitCtx, true, null));
+ }
+
+ private static final String __ice_invoke_name = "ice_invoke";
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_invoke(String operation, OperationMode mode, byte[] inParams)
+ {
+ return begin_ice_invoke(operation, mode, inParams, null, false, false, null);
+ }
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __context The context map for the invocation.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ java.util.Map<String, String> __context)
+ {
+ return begin_ice_invoke(operation, mode, inParams, __context, true, false, null);
+ }
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_invoke(String operation, OperationMode mode, byte[] inParams, Callback __cb)
+ {
+ return begin_ice_invoke(operation, mode, inParams, null, false, false, __cb);
+ }
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_invoke(String operation, OperationMode mode, byte[] inParams, java.util.Map<String, String> __context,
+ Callback __cb)
+ {
+ return begin_ice_invoke(operation, mode, inParams, __context, true, false, __cb);
+ }
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_invoke(String operation, OperationMode mode, byte[] inParams, Callback_Object_ice_invoke __cb)
+ {
+ return begin_ice_invoke(operation, mode, inParams, null, false, false, __cb);
+ }
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param __context The context map for the invocation.
+ * @param __cb The asynchronous callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final AsyncResult
+ begin_ice_invoke(String operation, OperationMode mode, byte[] inParams, java.util.Map<String, String> __context,
+ Callback_Object_ice_invoke __cb)
+ {
+ return begin_ice_invoke(operation, mode, inParams, __context, true, false, __cb);
+ }
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param responseCb The asynchronous response callback object.
+ * @param exceptionCb The asynchronous exception callback object.
+ * @param sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ FunctionalCallback_Object_ice_invoke_Response responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ IceInternal.Functional_BoolCallback sentCb)
+ {
+ return begin_ice_invoke(operation, mode, inParams, null, false, false, responseCb, exceptionCb, sentCb);
+ }
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * for the operation. The return value follows any out-parameters.
+ * @param responseCb The asynchronous response callback object.
+ * @param exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ FunctionalCallback_Object_ice_invoke_Response responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> exceptionCb)
+ {
+ return begin_ice_invoke(operation, mode, inParams, null, false, false, responseCb, exceptionCb, null);
+ }
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * @param context The context map for the invocation.
+ * for the operation. The return value follows any out-parameters.
+ * @param responseCb The asynchronous response callback object.
+ * @param exceptionCb The asynchronous exception callback object.
+ * @param sentCb The asynchronous sent callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ java.util.Map<String, String> context,
+ FunctionalCallback_Object_ice_invoke_Response responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ IceInternal.Functional_BoolCallback sentCb)
+ {
+ return begin_ice_invoke(operation, mode, inParams, context, true, false, responseCb, exceptionCb, sentCb);
+ }
+
+ /**
+ * Invokes an operation dynamically and asynchronously.
+ *
+ * @param operation The name of the operation to invoke.
+ * @param mode The operation mode (normal or idempotent).
+ * @param inParams The encoded in-parameters for the operation.
+ * @param context The context map for the invocation.
+ * for the operation. The return value follows any out-parameters.
+ * @param responseCb The asynchronous response callback object.
+ * @param exceptionCb The asynchronous exception callback object.
+ * @return The asynchronous result object.
+ *
+ * @see Blobject
+ * @see OperationMode
+ **/
+ @Override
+ public final AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ java.util.Map<String, String> context,
+ FunctionalCallback_Object_ice_invoke_Response responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> exceptionCb)
+ {
+ return begin_ice_invoke(operation, mode, inParams, context, true, false, responseCb, exceptionCb, null);
+ }
+
+ private AsyncResult begin_ice_invoke(String operation, OperationMode mode, byte[] inParams,
+ java.util.Map<String, String> __context,
+ boolean __explicitCtx,
+ boolean __synchronous,
+ FunctionalCallback_Object_ice_invoke_Response __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ class CB extends IceInternal.Functional_TwowayCallback implements _Callback_Object_ice_invoke
+ {
+ CB(FunctionalCallback_Object_ice_invoke_Response responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ IceInternal.Functional_BoolCallback sentCb)
+ {
+ super(responseCb != null, exceptionCb, sentCb);
+ __responseCb = responseCb;
+ }
+
+ @Override
+ public void response(boolean __ret, byte[] outParams)
+ {
+ __responseCb.apply(__ret, outParams);
+ }
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ ObjectPrxHelperBase.__ice_invoke_completed(this, __result);
+ }
+
+ FunctionalCallback_Object_ice_invoke_Response __responseCb;
+ }
+ return begin_ice_invoke(operation, mode, inParams, __context, __explicitCtx, __synchronous,
+ new CB(__responseCb, __exceptionCb, __sentCb));
+ }
+
+ private AsyncResult
+ begin_ice_invoke(String operation, OperationMode mode, byte[] inParams, java.util.Map<String, String> __context,
+ boolean __explicitCtx, boolean __synchronous, IceInternal.CallbackBase __cb)
+ {
+ IceInternal.OutgoingAsync __result = getOutgoingAsync(__ice_invoke_name, __cb);
+ try
+ {
+ __result.prepare(operation, mode, __context, __explicitCtx, __synchronous);
+ __result.writeParamEncaps(inParams);
+ __result.invoke();
+ }
+ catch(Exception __ex)
+ {
+ __result.abort(__ex);
+ }
+ return __result;
+ }
+
+ /**
+ * Completes the asynchronous ice_invoke request.
+ *
+ * @param outParams The encoded out-paramaters and return value.
+ * @param __r The asynchronous result.
+ * @return If the operation completed successfully, the return value
+ * is <code>true</code>. If the operation raises a user exception,
+ * the return value is <code>false</code>; in this case, <code>outParams</code>
+ * contains the encoded user exception. If the operation raises a run-time exception,
+ * it throws it directly.
+ **/
+ @Override
+ public final boolean
+ end_ice_invoke(ByteSeqHolder outParams, AsyncResult __r)
+ {
+ IceInternal.OutgoingAsync __result = IceInternal.OutgoingAsync.check(__r, this, __ice_invoke_name);
+ try
+ {
+ boolean ok = __result.__wait();
+ if(_reference.getMode() == IceInternal.Reference.ModeTwoway)
+ {
+ if(outParams != null)
+ {
+ outParams.value = __result.readParamEncaps();
+ }
+ }
+ return ok;
+ }
+ finally
+ {
+ if(__result != null)
+ {
+ __result.cacheMessageBuffers();
+ }
+ }
+ }
+
+ public static void __ice_invoke_completed(_Callback_Object_ice_invoke __cb, AsyncResult __result)
+ {
+ ByteSeqHolder outParams = new ByteSeqHolder();
+ boolean __ret = false;
+ try
+ {
+ __ret = __result.getProxy().end_ice_invoke(outParams, __result);
+ }
+ catch(LocalException __ex)
+ {
+ __cb.exception(__ex);
+ return;
+ }
+ catch(SystemException __ex)
+ {
+ __cb.exception(__ex);
+ return;
+ }
+ __cb.response(__ret, outParams.value);
+ }
+
+ /**
+ * Returns the identity embedded in this proxy.
+ *
+ * @return The identity of the target object.
+ **/
+ @Override
+ public final Identity
+ ice_getIdentity()
+ {
+ return _reference.getIdentity().clone();
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the identity.
+ *
+ * @param newIdentity The identity for the new proxy.
+ * @return The proxy with the new identity.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_identity(Identity newIdentity)
+ {
+ if(newIdentity.name.equals(""))
+ {
+ throw new IllegalIdentityException();
+ }
+ if(newIdentity.equals(_reference.getIdentity()))
+ {
+ return this;
+ }
+ else
+ {
+ ObjectPrxHelperBase proxy = new ObjectPrxHelperBase();
+ proxy.__setup(_reference.changeIdentity(newIdentity));
+ return proxy;
+ }
+ }
+
+ /**
+ * Returns the per-proxy context for this proxy.
+ *
+ * @return The per-proxy context. If the proxy does not have a per-proxy (implicit) context, the return value
+ * is <code>null</code>.
+ **/
+ @Override
+ public final java.util.Map<String, String>
+ ice_getContext()
+ {
+ return new java.util.HashMap<String, String>(_reference.getContext());
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the per-proxy context.
+ *
+ * @param newContext The context for the new proxy.
+ * @return The proxy with the new per-proxy context.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_context(java.util.Map<String, String> newContext)
+ {
+ return newInstance(_reference.changeContext(newContext));
+ }
+
+ /**
+ * Returns the facet for this proxy.
+ *
+ * @return The facet for this proxy. If the proxy uses the default facet, the return value is the empty string.
+ **/
+ @Override
+ public final String
+ ice_getFacet()
+ {
+ return _reference.getFacet();
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the facet.
+ *
+ * @param newFacet The facet for the new proxy.
+ * @return The proxy with the new facet.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_facet(String newFacet)
+ {
+ if(newFacet == null)
+ {
+ newFacet = "";
+ }
+
+ if(newFacet.equals(_reference.getFacet()))
+ {
+ return this;
+ }
+ else
+ {
+ ObjectPrxHelperBase proxy = new ObjectPrxHelperBase();
+ proxy.__setup(_reference.changeFacet(newFacet));
+ return proxy;
+ }
+ }
+
+ /**
+ * Returns the adapter ID for this proxy.
+ *
+ * @return The adapter ID. If the proxy does not have an adapter ID, the return value is the empty string.
+ **/
+ @Override
+ public final String
+ ice_getAdapterId()
+ {
+ return _reference.getAdapterId();
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the adapter ID.
+ *
+ * @param newAdapterId The adapter ID for the new proxy.
+ * @return The proxy with the new adapter ID.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_adapterId(String newAdapterId)
+ {
+ if(newAdapterId == null)
+ {
+ newAdapterId = "";
+ }
+
+ if(newAdapterId.equals(_reference.getAdapterId()))
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeAdapterId(newAdapterId));
+ }
+ }
+
+ /**
+ * Returns the endpoints used by this proxy.
+ *
+ * @return The endpoints used by this proxy.
+ *
+ * @see Endpoint
+ **/
+ @Override
+ public final Endpoint[]
+ ice_getEndpoints()
+ {
+ return _reference.getEndpoints().clone();
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the endpoints.
+ *
+ * @param newEndpoints The endpoints for the new proxy.
+ * @return The proxy with the new endpoints.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_endpoints(Endpoint[] newEndpoints)
+ {
+ if(java.util.Arrays.equals(newEndpoints, _reference.getEndpoints()))
+ {
+ return this;
+ }
+ else
+ {
+ IceInternal.EndpointI[] edpts = new IceInternal.EndpointI[newEndpoints.length];
+ edpts = java.util.Arrays.asList(newEndpoints).toArray(edpts);
+ return newInstance(_reference.changeEndpoints(edpts));
+ }
+ }
+
+ /**
+ * Returns the locator cache timeout of this proxy.
+ *
+ * @return The locator cache timeout value (in seconds).
+ *
+ * @see Locator
+ **/
+ @Override
+ public final int
+ ice_getLocatorCacheTimeout()
+ {
+ return _reference.getLocatorCacheTimeout();
+ }
+
+ /**
+ * Returns the invocation timeout of this proxy.
+ *
+ * @return The invocation timeout value (in seconds).
+ **/
+ @Override
+ public final int
+ ice_getInvocationTimeout()
+ {
+ return _reference.getInvocationTimeout();
+ }
+
+ /**
+ * Returns the connection id of this proxy.
+ *
+ * @return The connection id.
+ *
+ **/
+ @Override
+ public final String
+ ice_getConnectionId()
+ {
+ return _reference.getConnectionId();
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the locator cache timeout.
+ *
+ * @param newTimeout The new locator cache timeout (in seconds).
+ *
+ * @see Locator
+ **/
+ @Override
+ public final ObjectPrx
+ ice_locatorCacheTimeout(int newTimeout)
+ {
+ if(newTimeout < -1)
+ {
+ throw new IllegalArgumentException("invalid value passed to ice_locatorCacheTimeout: " + newTimeout);
+ }
+ if(newTimeout == _reference.getLocatorCacheTimeout())
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeLocatorCacheTimeout(newTimeout));
+ }
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the invocation timeout.
+ *
+ * @param newTimeout The new invocation timeout (in seconds).
+ **/
+ @Override
+ public final ObjectPrx
+ ice_invocationTimeout(int newTimeout)
+ {
+ if(newTimeout < 1 && newTimeout != -1 && newTimeout != -2)
+ {
+ throw new IllegalArgumentException("invalid value passed to ice_invocationTimeout: " + newTimeout);
+ }
+ if(newTimeout == _reference.getInvocationTimeout())
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeInvocationTimeout(newTimeout));
+ }
+ }
+
+ /**
+ * Returns whether this proxy caches connections.
+ *
+ * @return <code>true</code> if this proxy caches connections; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ ice_isConnectionCached()
+ {
+ return _reference.getCacheConnection();
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for connection caching.
+ *
+ * @param newCache <code>true</code> if the new proxy should cache connections; <code>false</code>, otherwise.
+ * @return The new proxy with the specified caching policy.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_connectionCached(boolean newCache)
+ {
+ if(newCache == _reference.getCacheConnection())
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeCacheConnection(newCache));
+ }
+ }
+
+ /**
+ * Returns how this proxy selects endpoints (randomly or ordered).
+ *
+ * @return The endpoint selection policy.
+ *
+ * @see EndpointSelectionType
+ **/
+ @Override
+ public final Ice.EndpointSelectionType
+ ice_getEndpointSelection()
+ {
+ return _reference.getEndpointSelection();
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the endpoint selection policy.
+ *
+ * @param newType The new endpoint selection policy.
+ * @return The new proxy with the specified endpoint selection policy.
+ *
+ * @see EndpointSelectionType
+ **/
+ @Override
+ public final ObjectPrx
+ ice_endpointSelection(Ice.EndpointSelectionType newType)
+ {
+ if(newType == _reference.getEndpointSelection())
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeEndpointSelection(newType));
+ }
+ }
+
+ /**
+ * Returns whether this proxy uses only secure endpoints.
+ *
+ * @return <code>true</code> if all endpoints for this proxy are secure; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ ice_isSecure()
+ {
+ return _reference.getSecure();
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for its endpoints.
+ *
+ * @param b If <code>b</code> is <code>true</code>, only endpoints that use a secure transport are
+ * retained for the new proxy. If <code>b</code> is false, the returned proxy is identical to this proxy.
+ * @return The new proxy with possible different endpoints.k
+ **/
+ @Override
+ public final ObjectPrx
+ ice_secure(boolean b)
+ {
+ if(b == _reference.getSecure())
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeSecure(b));
+ }
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the encoding used to marshal
+ * parameters.
+ *
+ * @param e The encoding version to use to marshal requests parameters.
+ * @return The new proxy with the specified encoding version.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_encodingVersion(Ice.EncodingVersion e)
+ {
+ if(e.equals(_reference.getEncoding()))
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeEncoding(e));
+ }
+ }
+
+ /**
+ * Returns the encoding version used to marshal requests parameters.
+ *
+ * @return The encoding version.
+ **/
+ @Override
+ public final Ice.EncodingVersion
+ ice_getEncodingVersion()
+ {
+ return _reference.getEncoding().clone();
+ }
+
+ /**
+ * Returns whether this proxy prefers secure endpoints.
+ *
+ * @return <code>true</code> if the proxy always attempts to invoke via secure endpoints before it
+ * attempts to use insecure endpoints; <code>false</code>, otherwise;
+ **/
+ @Override
+ public final boolean
+ ice_isPreferSecure()
+ {
+ return _reference.getPreferSecure();
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for its endpoint selection policy.
+ *
+ * @param b If <code>b</code> is <code>true</code>, the new proxy will use secure endpoints for invocations
+ * and only use insecure endpoints if an invocation cannot be made via secure endpoints. If <code>b</code> is
+ * <code>false</code>, the proxy prefers insecure endpoints to secure ones.
+ * @return The new proxy with the new endpoint selection policy.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_preferSecure(boolean b)
+ {
+ if(b == _reference.getPreferSecure())
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changePreferSecure(b));
+ }
+ }
+
+ /**
+ * Returns the router for this proxy.
+ *
+ * @return The router for the proxy. If no router is configured for the proxy, the return value
+ * is <code>null</code>.
+ **/
+ @Override
+ public final Ice.RouterPrx
+ ice_getRouter()
+ {
+ IceInternal.RouterInfo ri = _reference.getRouterInfo();
+ return ri != null ? ri.getRouter() : null;
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the router.
+ *
+ * @param router The router for the new proxy.
+ * @return The new proxy with the specified router.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_router(Ice.RouterPrx router)
+ {
+ IceInternal.Reference ref = _reference.changeRouter(router);
+ if(ref.equals(_reference))
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(ref);
+ }
+ }
+
+ /**
+ * Returns the locator for this proxy.
+ *
+ * @return The locator for this proxy. If no locator is configured, the return value is <code>null</code>.
+ **/
+ @Override
+ public final Ice.LocatorPrx
+ ice_getLocator()
+ {
+ IceInternal.LocatorInfo ri = _reference.getLocatorInfo();
+ return ri != null ? ri.getLocator() : null;
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for the locator.
+ *
+ * @param locator The locator for the new proxy.
+ * @return The new proxy with the specified locator.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_locator(Ice.LocatorPrx locator)
+ {
+ IceInternal.Reference ref = _reference.changeLocator(locator);
+ if(ref.equals(_reference))
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(ref);
+ }
+ }
+
+ /**
+ * Returns whether this proxy uses collocation optimization.
+ *
+ * @return <code>true</code> if the proxy uses collocation optimization; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ ice_isCollocationOptimized()
+ {
+ return _reference.getCollocationOptimized();
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for collocation optimization.
+ *
+ * @param b <code>true</code> if the new proxy enables collocation optimization; <code>false</code>, otherwise.
+ * @return The new proxy the specified collocation optimization.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_collocationOptimized(boolean b)
+ {
+ if(b == _reference.getCollocationOptimized())
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeCollocationOptimized(b));
+ }
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, but uses twoway invocations.
+ *
+ * @return A new proxy that uses twoway invocations.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_twoway()
+ {
+ if(_reference.getMode() == IceInternal.Reference.ModeTwoway)
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeMode(IceInternal.Reference.ModeTwoway));
+ }
+ }
+
+ /**
+ * Returns whether this proxy uses twoway invocations.
+ * @return <code>true</code> if this proxy uses twoway invocations; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ ice_isTwoway()
+ {
+ return _reference.getMode() == IceInternal.Reference.ModeTwoway;
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, but uses oneway invocations.
+ *
+ * @return A new proxy that uses oneway invocations.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_oneway()
+ {
+ if(_reference.getMode() == IceInternal.Reference.ModeOneway)
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeMode(IceInternal.Reference.ModeOneway));
+ }
+ }
+
+ /**
+ * Returns whether this proxy uses oneway invocations.
+ * @return <code>true</code> if this proxy uses oneway invocations; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ ice_isOneway()
+ {
+ return _reference.getMode() == IceInternal.Reference.ModeOneway;
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, but uses batch oneway invocations.
+ *
+ * @return A new proxy that uses batch oneway invocations.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_batchOneway()
+ {
+ if(_reference.getMode() == IceInternal.Reference.ModeBatchOneway)
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeMode(IceInternal.Reference.ModeBatchOneway));
+ }
+ }
+
+ /**
+ * Returns whether this proxy uses batch oneway invocations.
+ * @return <code>true</code> if this proxy uses batch oneway invocations; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ ice_isBatchOneway()
+ {
+ return _reference.getMode() == IceInternal.Reference.ModeBatchOneway;
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, but uses datagram invocations.
+ *
+ * @return A new proxy that uses datagram invocations.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_datagram()
+ {
+ if(_reference.getMode() == IceInternal.Reference.ModeDatagram)
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeMode(IceInternal.Reference.ModeDatagram));
+ }
+ }
+
+ /**
+ * Returns whether this proxy uses datagram invocations.
+ * @return <code>true</code> if this proxy uses datagram invocations; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ ice_isDatagram()
+ {
+ return _reference.getMode() == IceInternal.Reference.ModeDatagram;
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, but uses batch datagram invocations.
+ *
+ * @return A new proxy that uses batch datagram invocations.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_batchDatagram()
+ {
+ if(_reference.getMode() == IceInternal.Reference.ModeBatchDatagram)
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(_reference.changeMode(IceInternal.Reference.ModeBatchDatagram));
+ }
+ }
+
+ /**
+ * Returns whether this proxy uses batch datagram invocations.
+ * @return <code>true</code> if this proxy uses batch datagram invocations; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ ice_isBatchDatagram()
+ {
+ return _reference.getMode() == IceInternal.Reference.ModeBatchDatagram;
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for compression.
+ *
+ * @param co <code>true</code> enables compression for the new proxy; <code>false</code>disables compression.
+ * @return A new proxy with the specified compression setting.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_compress(boolean co)
+ {
+ IceInternal.Reference ref = _reference.changeCompress(co);
+ if(ref.equals(_reference))
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(ref);
+ }
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for its timeout setting.
+ *
+ * @param t The timeout for the new proxy in milliseconds.
+ * @return A new proxy with the specified timeout.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_timeout(int t)
+ {
+ if(t < 1 && t != -1)
+ {
+ throw new IllegalArgumentException("invalid value passed to ice_timeout: " + t);
+ }
+ IceInternal.Reference ref = _reference.changeTimeout(t);
+ if(ref.equals(_reference))
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(ref);
+ }
+ }
+
+ /**
+ * Creates a new proxy that is identical to this proxy, except for its connection ID.
+ *
+ * @param id The connection ID for the new proxy. An empty string removes the
+ * connection ID.
+ *
+ * @return A new proxy with the specified connection ID.
+ **/
+ @Override
+ public final ObjectPrx
+ ice_connectionId(String id)
+ {
+ IceInternal.Reference ref = _reference.changeConnectionId(id);
+ if(ref.equals(_reference))
+ {
+ return this;
+ }
+ else
+ {
+ return newInstance(ref);
+ }
+ }
+
+ /**
+ * Returns the {@link Connection} for this proxy. If the proxy does not yet have an established connection,
+ * it first attempts to create a connection.
+ *
+ * @return The {@link Connection} for this proxy.
+ * @throws CollocationOptimizationException If the proxy uses collocation optimization and denotes a
+ * collocated object.
+ *
+ * @see Connection
+ **/
+ @Override
+ public final Connection
+ ice_getConnection()
+ {
+ return end_ice_getConnection(begin_ice_getConnection());
+ }
+
+ /**
+ * Asynchronously gets the connection for this proxy. The call does not block.
+ *
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public AsyncResult
+ begin_ice_getConnection()
+ {
+ return begin_ice_getConnectionInternal(null);
+ }
+
+ /**
+ * Asynchronously gets the connection for this proxy. The call does not block.
+ *
+ * @param __cb The callback object to notify the application when the flush is complete.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public AsyncResult
+ begin_ice_getConnection(Callback __cb)
+ {
+ return begin_ice_getConnectionInternal(__cb);
+ }
+
+ /**
+ * Asynchronously gets the connection for this proxy. The call does not block.
+ *
+ * @param __cb The callback object to notify the application when the flush is complete.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public AsyncResult
+ begin_ice_getConnection(Callback_Object_ice_getConnection __cb)
+ {
+ return begin_ice_getConnectionInternal(__cb);
+ }
+
+ private class FunctionalCallback_Object_ice_getConnection
+ extends IceInternal.Functional_TwowayCallbackArg1<Ice.Connection>
+ {
+ FunctionalCallback_Object_ice_getConnection(
+ IceInternal.Functional_GenericCallback1<Ice.Connection> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb)
+ {
+ super(__responseCb, __exceptionCb, null);
+ }
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ ObjectPrxHelperBase.__ice_getConnection_completed(this, __result);
+ }
+ }
+
+ /**
+ * Asynchronously gets the connection for this proxy. The call does not block.
+ *
+ * @param __responseCb The callback object to notify the application when the there is a response available.
+ * @param __exceptionCb The callback object to notify the application when the there is an exception getting
+ * connection.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public AsyncResult
+ begin_ice_getConnection(IceInternal.Functional_GenericCallback1<Ice.Connection> __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb)
+ {
+ return begin_ice_getConnectionInternal(
+ new FunctionalCallback_Object_ice_getConnection(__responseCb, __exceptionCb));
+ }
+
+ private static final String __ice_getConnection_name = "ice_getConnection";
+
+ private AsyncResult
+ begin_ice_getConnectionInternal(IceInternal.CallbackBase cb)
+ {
+ IceInternal.ProxyGetConnection result = new IceInternal.ProxyGetConnection(this, __ice_getConnection_name, cb);
+ try
+ {
+ result.invoke();
+ }
+ catch(Exception ex)
+ {
+ result.abort(ex);
+ }
+ return result;
+ }
+
+ @Override
+ public Ice.Connection
+ end_ice_getConnection(AsyncResult r)
+ {
+ IceInternal.ProxyGetConnection result = IceInternal.ProxyGetConnection.check(r, this, __ice_getConnection_name);
+ result.__wait();
+ return result.getConnection();
+ }
+
+ static public void __ice_getConnection_completed(TwowayCallbackArg1<Ice.Connection> cb, AsyncResult result)
+ {
+ Ice.Connection ret = null;
+ try
+ {
+ ret = result.getProxy().end_ice_getConnection(result);
+ }
+ catch(LocalException ex)
+ {
+ cb.exception(ex);
+ return;
+ }
+ catch(SystemException ex)
+ {
+ cb.exception(ex);
+ return;
+ }
+ cb.response(ret);
+ }
+
+ /**
+ * Returns the cached {@link Connection} for this proxy. If the proxy does not yet have an established
+ * connection, it does not attempt to create a connection.
+ *
+ * @return The cached {@link Connection} for this proxy (<code>null</code> if the proxy does not have
+ * an established connection).
+ * @throws CollocationOptimizationException If the proxy uses collocation optimization and denotes a
+ * collocated object.
+ *
+ * @see Connection
+ **/
+ @Override
+ public final Connection
+ ice_getCachedConnection()
+ {
+ IceInternal.RequestHandler handler = null;
+ synchronized(this)
+ {
+ handler = _requestHandler;
+ }
+
+ if(handler != null)
+ {
+ try
+ {
+ return handler.getConnection();
+ }
+ catch(LocalException ex)
+ {
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Flushes any pending batched requests for this communicator. The call blocks until the flush is complete.
+ **/
+ @Override
+ public void
+ ice_flushBatchRequests()
+ {
+ end_ice_flushBatchRequests(begin_ice_flushBatchRequests());
+ }
+
+ /**
+ * Asynchronously flushes any pending batched requests for this communicator. The call does not block.
+ *
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public AsyncResult
+ begin_ice_flushBatchRequests()
+ {
+ return begin_ice_flushBatchRequestsInternal(null);
+ }
+
+ /**
+ * Asynchronously flushes any pending batched requests for this communicator. The call does not block.
+ *
+ * @param __cb The callback object to notify the application when the flush is complete.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public AsyncResult
+ begin_ice_flushBatchRequests(Callback __cb)
+ {
+ return begin_ice_flushBatchRequestsInternal(__cb);
+ }
+
+ /**
+ * Asynchronously flushes any pending batched requests for this communicator. The call does not block.
+ *
+ * @param __cb The callback object to notify the application when the flush is complete.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public AsyncResult
+ begin_ice_flushBatchRequests(Callback_Object_ice_flushBatchRequests __cb)
+ {
+ return begin_ice_flushBatchRequestsInternal(__cb);
+ }
+
+ /**
+ * Asynchronously flushes any pending batched requests for this communicator. The call does not block.
+ *
+ * @param __exceptionCb The callback object to notify the application when the there is an exception flushing
+ * the requests.
+ * @param __sentCb The callback object to notify the application when the flush is complete.
+ * @return The asynchronous result object.
+ **/
+ @Override
+ public AsyncResult
+ begin_ice_flushBatchRequests(IceInternal.Functional_VoidCallback __responseCb,
+ IceInternal.Functional_GenericCallback1<Ice.Exception> __exceptionCb,
+ IceInternal.Functional_BoolCallback __sentCb)
+ {
+ return begin_ice_flushBatchRequestsInternal(
+ new IceInternal.Functional_OnewayCallback(__responseCb, __exceptionCb, __sentCb));
+ }
+
+ private static final String __ice_flushBatchRequests_name = "ice_flushBatchRequests";
+
+ private AsyncResult
+ begin_ice_flushBatchRequestsInternal(IceInternal.CallbackBase cb)
+ {
+ IceInternal.ProxyFlushBatch result = new IceInternal.ProxyFlushBatch(this, __ice_flushBatchRequests_name, cb);
+ try
+ {
+ result.invoke();
+ }
+ catch(Exception ex)
+ {
+ result.abort(ex);
+ }
+ return result;
+ }
+
+ @Override
+ public void
+ end_ice_flushBatchRequests(AsyncResult r)
+ {
+ IceInternal.ProxyFlushBatch result = IceInternal.ProxyFlushBatch.check(r, this, __ice_flushBatchRequests_name);
+ result.__wait();
+ }
+
+ /**
+ * Returns whether this proxy equals the passed object. Two proxies are equal if they are equal in all respects,
+ * that is, if their object identity, endpoints timeout settings, and so on are all equal.
+ *
+ * @param r The object to compare this proxy with.
+ * @return <code>true</code> if this proxy is equal to <code>r</code>; <code>false</code>, otherwise.
+ **/
+ @Override
+ public final boolean
+ equals(java.lang.Object r)
+ {
+ if(this == r)
+ {
+ return true;
+ }
+
+ if(r instanceof ObjectPrxHelperBase)
+ {
+ return _reference.equals(((ObjectPrxHelperBase)r)._reference);
+ }
+
+ return false;
+ }
+
+ public void __write(OutputStream os)
+ {
+ _reference.getIdentity().__write(os);
+ _reference.streamWrite(os);
+ }
+
+ public final IceInternal.Reference
+ __reference()
+ {
+ return _reference;
+ }
+
+ public final void
+ __copyFrom(ObjectPrx from)
+ {
+ synchronized(from)
+ {
+ ObjectPrxHelperBase h = (ObjectPrxHelperBase)from;
+ _reference = h._reference;
+ _requestHandler = h._requestHandler;
+ }
+ }
+
+ public final int
+ __handleException(Exception ex, IceInternal.RequestHandler handler, OperationMode mode, boolean sent,
+ Holder<Integer> interval, int cnt)
+ {
+ __updateRequestHandler(handler, null); // Clear the request handler
+
+ //
+ // We only retry local exception, system exceptions aren't retried.
+ //
+ // 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 the request didn't get sent or if it's non-mutating or idempotent it can
+ // also always be retried if the retry count isn't reached.
+ //
+ if(ex instanceof LocalException && (!sent ||
+ mode == OperationMode.Nonmutating || mode == OperationMode.Idempotent ||
+ ex instanceof CloseConnectionException ||
+ ex instanceof ObjectNotExistException))
+ {
+ try
+ {
+ return _reference.getInstance().proxyFactory().checkRetryAfterException((LocalException)ex,
+ _reference,
+ interval,
+ cnt);
+ }
+ catch(CommunicatorDestroyedException exc)
+ {
+ //
+ // The communicator is already destroyed, so we cannot retry.
+ //
+ throw ex;
+ }
+ }
+ else
+ {
+ throw ex; // Retry could break at-most-once semantics, don't retry.
+ }
+ }
+
+ public final void
+ __checkTwowayOnly(String name)
+ {
+ //
+ // No mutex lock necessary, there is nothing mutable in this
+ // operation.
+ //
+
+ if(!ice_isTwoway())
+ {
+ TwowayOnlyException ex = new TwowayOnlyException();
+ ex.operation = name;
+ throw ex;
+ }
+ }
+
+ public final void
+ __checkAsyncTwowayOnly(String name)
+ {
+ //
+ // No mutex lock necessary, there is nothing mutable in this
+ // operation.
+ //
+
+ if(!ice_isTwoway())
+ {
+ throw new java.lang.IllegalArgumentException("`" + name + "' can only be called with a twoway proxy");
+ }
+ }
+
+ public final void
+ __end(AsyncResult r, String operation)
+ {
+ IceInternal.ProxyOutgoingAsyncBase result = IceInternal.ProxyOutgoingAsyncBase.check(r, this, operation);
+ try
+ {
+ boolean ok = result.__wait();
+ if(_reference.getMode() == IceInternal.Reference.ModeTwoway)
+ {
+ IceInternal.OutgoingAsync outAsync = (IceInternal.OutgoingAsync)result;
+ if(!ok)
+ {
+ try
+ {
+ outAsync.throwUserException();
+ }
+ catch(UserException ex)
+ {
+ throw new UnknownUserException(ex.ice_id(), ex);
+ }
+ }
+ outAsync.readEmptyParams();
+ }
+ }
+ finally
+ {
+ if(result != null)
+ {
+ result.cacheMessageBuffers();
+ }
+ }
+ }
+
+ public final IceInternal.RequestHandler
+ __getRequestHandler()
+ {
+ if(_reference.getCacheConnection())
+ {
+ synchronized(this)
+ {
+ if(_requestHandler != null)
+ {
+ return _requestHandler;
+ }
+ }
+ }
+ return _reference.getRequestHandler(this);
+ }
+
+ synchronized public final IceInternal.BatchRequestQueue
+ __getBatchRequestQueue()
+ {
+ if(_batchRequestQueue == null)
+ {
+ _batchRequestQueue = _reference.getBatchRequestQueue();
+ }
+ return _batchRequestQueue;
+ }
+
+ public IceInternal.RequestHandler
+ __setRequestHandler(IceInternal.RequestHandler handler)
+ {
+ if(_reference.getCacheConnection())
+ {
+ synchronized(this)
+ {
+ if(_requestHandler == null)
+ {
+ _requestHandler = handler;
+ }
+ return _requestHandler;
+ }
+ }
+ return handler;
+ }
+
+ public void
+ __updateRequestHandler(IceInternal.RequestHandler previous, IceInternal.RequestHandler handler)
+ {
+ if(_reference.getCacheConnection() && previous != null)
+ {
+ synchronized(this)
+ {
+ if(_requestHandler != null && _requestHandler != handler)
+ {
+ //
+ // Update the request handler only if "previous" is the same
+ // as the current request handler. This is called after
+ // connection binding by the connect request handler. We only
+ // replace the request handler if the current handler is the
+ // connect request handler.
+ //
+ _requestHandler = _requestHandler.update(previous, handler);
+ }
+ }
+ }
+ }
+
+ public void
+ cacheMessageBuffers(InputStream is, OutputStream os)
+ {
+ synchronized(this)
+ {
+ if(_streamCache == null)
+ {
+ _streamCache = new LinkedList<StreamCacheEntry>();
+ }
+ _streamCache.add(new StreamCacheEntry(is, os));
+ }
+ }
+
+ //
+ // Only for use by IceInternal.ProxyFactory
+ //
+ public final void
+ __setup(IceInternal.Reference ref)
+ {
+ //
+ // No need to synchronize, as this operation is only called
+ // upon initial initialization.
+ //
+
+ assert(_reference == null);
+ assert(_requestHandler == null);
+
+ _reference = ref;
+ }
+
+ protected static <T> T checkedCastImpl(Ice.ObjectPrx obj, String id, Class<T> proxyCls, Class<?> helperCls)
+ {
+ return checkedCastImpl(obj, null, false, null, false, id, proxyCls, helperCls);
+ }
+
+ protected static <T> T checkedCastImpl(Ice.ObjectPrx obj, java.util.Map<String, String> ctx, String id,
+ Class<T> proxyCls, Class<?> helperCls)
+ {
+ return checkedCastImpl(obj, ctx, true, null, false, id, proxyCls, helperCls);
+ }
+
+ protected static <T> T checkedCastImpl(Ice.ObjectPrx obj, String facet, String id, Class<T> proxyCls,
+ Class<?> helperCls)
+ {
+ return checkedCastImpl(obj, null, false, facet, true, id, proxyCls, helperCls);
+ }
+
+ protected static <T> T checkedCastImpl(Ice.ObjectPrx obj, String facet, java.util.Map<String, String> ctx,
+ String id, Class<T> proxyCls, Class<?> helperCls)
+ {
+ return checkedCastImpl(obj, ctx, true, facet, true, id, proxyCls, helperCls);
+ }
+
+ protected static <T> T checkedCastImpl(Ice.ObjectPrx obj, java.util.Map<String, String> ctx, boolean explicitCtx,
+ String facet, boolean explicitFacet, String id, Class<T> proxyCls,
+ Class<?> helperCls)
+ {
+ T d = null;
+ if(obj != null)
+ {
+ if(explicitFacet)
+ {
+ obj = obj.ice_facet(facet);
+ }
+ if(proxyCls.isInstance(obj))
+ {
+ d = proxyCls.cast(obj);
+ }
+ else
+ {
+ try
+ {
+ final boolean b = explicitCtx ? obj.ice_isA(id, ctx) : obj.ice_isA(id);
+ if(b)
+ {
+ ObjectPrxHelperBase h = null;
+ try
+ {
+ h = ObjectPrxHelperBase.class.cast(helperCls.newInstance());
+ }
+ catch(InstantiationException ex)
+ {
+ throw new SyscallException(ex);
+ }
+ catch(IllegalAccessException ex)
+ {
+ throw new SyscallException(ex);
+ }
+ h.__copyFrom(obj);
+ d = proxyCls.cast(h);
+ }
+ }
+ catch(FacetNotExistException ex)
+ {
+ }
+ }
+ }
+ return d;
+ }
+
+ protected static <T> T uncheckedCastImpl(Ice.ObjectPrx obj, Class<T> proxyCls, Class<?> helperCls)
+ {
+ return uncheckedCastImpl(obj, null, false, proxyCls, helperCls);
+ }
+
+ protected static <T> T uncheckedCastImpl(Ice.ObjectPrx obj, String facet, Class<T> proxyCls, Class<?> helperCls)
+ {
+ return uncheckedCastImpl(obj, facet, true, proxyCls, helperCls);
+ }
+
+ protected static <T> T uncheckedCastImpl(Ice.ObjectPrx obj, String facet, boolean explicitFacet, Class<T> proxyCls,
+ Class<?> helperCls)
+ {
+ T d = null;
+ if(obj != null)
+ {
+ try
+ {
+ if(explicitFacet)
+ {
+ ObjectPrxHelperBase h = ObjectPrxHelperBase.class.cast(helperCls.newInstance());
+ h.__copyFrom(obj.ice_facet(facet));
+ d = proxyCls.cast(h);
+ }
+ else
+ {
+ if(proxyCls.isInstance(obj))
+ {
+ d = proxyCls.cast(obj);
+ }
+ else
+ {
+ ObjectPrxHelperBase h = ObjectPrxHelperBase.class.cast(helperCls.newInstance());
+ h.__copyFrom(obj);
+ d = proxyCls.cast(h);
+ }
+ }
+ }
+ catch(InstantiationException ex)
+ {
+ throw new SyscallException(ex);
+ }
+ catch(IllegalAccessException ex)
+ {
+ throw new SyscallException(ex);
+ }
+ }
+ return d;
+ }
+
+ protected IceInternal.OutgoingAsync
+ getOutgoingAsync(String operation, IceInternal.CallbackBase cb)
+ {
+ StreamCacheEntry cacheEntry = null;
+ if(_reference.getInstance().cacheMessageBuffers() > 0)
+ {
+ synchronized(this)
+ {
+ if(_streamCache != null && !_streamCache.isEmpty())
+ {
+ cacheEntry = _streamCache.remove(0);
+ }
+ }
+ }
+ if(cacheEntry == null)
+ {
+ return new IceInternal.OutgoingAsync(this, operation, cb);
+ }
+ else
+ {
+ return new IceInternal.OutgoingAsync(this, operation, cb, cacheEntry.is, cacheEntry.os);
+ }
+ }
+
+ private ObjectPrxHelperBase
+ newInstance(IceInternal.Reference ref)
+ {
+ try
+ {
+ ObjectPrxHelperBase proxy = getClass().newInstance();
+ proxy.__setup(ref);
+ return proxy;
+ }
+ catch(InstantiationException e)
+ {
+ //
+ // Impossible
+ //
+ assert false;
+ return null;
+ }
+ catch(IllegalAccessException e)
+ {
+ //
+ // Impossible
+ //
+ assert false;
+ return null;
+ }
+ }
+
+ private void
+ writeObject(java.io.ObjectOutputStream out)
+ throws java.io.IOException
+ {
+ out.writeUTF(toString());
+ }
+
+ private void
+ readObject(java.io.ObjectInputStream in)
+ throws java.io.IOException, ClassNotFoundException
+ {
+ String s = in.readUTF();
+ try
+ {
+ Communicator communicator = ((Ice.ObjectInputStream)in).getCommunicator();
+ if(communicator == null)
+ {
+ throw new java.io.IOException("Cannot deserialize proxy: no communicator provided");
+ }
+ ObjectPrxHelperBase proxy = (ObjectPrxHelperBase)communicator.stringToProxy(s);
+ _reference = proxy._reference;
+ assert(proxy._requestHandler == null);
+ }
+ catch(ClassCastException ex)
+ {
+ java.io.IOException e =
+ new java.io.IOException("Cannot deserialize proxy: Ice.ObjectInputStream not found");
+ e.initCause(ex);
+ throw e;
+ }
+ catch(LocalException ex)
+ {
+ java.io.IOException e = new java.io.IOException("Failure occurred while deserializing proxy");
+ e.initCause(ex);
+ throw e;
+ }
+ }
+
+ private static class StreamCacheEntry
+ {
+ StreamCacheEntry(InputStream is, OutputStream os)
+ {
+ this.is = is;
+ this.os = os;
+ }
+
+ InputStream is;
+ OutputStream os;
+ }
+
+ private transient IceInternal.Reference _reference;
+ private transient IceInternal.RequestHandler _requestHandler;
+ private transient IceInternal.BatchRequestQueue _batchRequestQueue;
+ private transient List<StreamCacheEntry> _streamCache;
+ public static final long serialVersionUID = 0L;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectPrxHolder.java b/java-compat/src/Ice/src/main/java/Ice/ObjectPrxHolder.java
new file mode 100644
index 00000000000..eb61958e123
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectPrxHolder.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for proxies that are out- or inout-parameters.
+ **/
+public final class ObjectPrxHolder extends Holder<ObjectPrx>
+{
+ /**
+ * Instantiates the class with a <code>null</code> proxy.
+ **/
+ public
+ ObjectPrxHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed proxy.
+ *
+ * @param value The proxy stored this holder.
+ **/
+ public
+ ObjectPrxHolder(ObjectPrx value)
+ {
+ super(value);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectReader.java b/java-compat/src/Ice/src/main/java/Ice/ObjectReader.java
new file mode 100644
index 00000000000..488986f98af
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectReader.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class for extracting objects from an input stream.
+ **/
+public abstract class ObjectReader extends ObjectImpl
+{
+ /**
+ * Reads the state of this Slice class from an input stream.
+ *
+ * @param in The input stream to read from.
+ **/
+ public abstract void read(InputStream in);
+
+ @Override
+ public void __write(OutputStream os)
+ {
+ assert(false);
+ }
+
+ @Override
+ public void __read(InputStream is)
+ {
+ read(is);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectWriter.java b/java-compat/src/Ice/src/main/java/Ice/ObjectWriter.java
new file mode 100644
index 00000000000..91e474477a7
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectWriter.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class for writing Slice classes to an output stream.
+ **/
+public abstract class ObjectWriter extends ObjectImpl
+{
+ /**
+ * Writes the state of this Slice class to an output stream.
+ *
+ * @param out The stream to write to.
+ **/
+ public abstract void write(OutputStream out);
+
+ @Override
+ public void __write(OutputStream os)
+ {
+ write(os);
+ }
+
+ @Override
+ public void __read(Ice.InputStream is)
+ {
+ assert(false);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/OnewayCallback.java b/java-compat/src/Ice/src/main/java/Ice/OnewayCallback.java
new file mode 100644
index 00000000000..76405d95605
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/OnewayCallback.java
@@ -0,0 +1,77 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class for generated oneway operation callback.
+ **/
+public abstract class OnewayCallback extends IceInternal.CallbackBase
+{
+ /**
+ * Called when the invocation response is received.
+ **/
+ public abstract void response();
+
+ /**
+ * Called when the invocation raises an Ice run-time exception.
+ *
+ * @param ex The Ice run-time exception raised by the operation.
+ **/
+ public abstract void exception(LocalException ex);
+
+ /**
+ * Called when the invocation raises an Ice system exception.
+ *
+ * @param ex The Ice system exception raised by the operation.
+ **/
+ public void exception(SystemException ex)
+ {
+ exception(new Ice.UnknownException(ex));
+ }
+
+ /**
+ * Called when a queued invocation is sent successfully.
+ **/
+ public void sent(boolean sentSynchronously)
+ {
+ }
+
+ @Override
+ public final void __sent(AsyncResult __result)
+ {
+ sent(__result.sentSynchronously());
+ }
+
+ @Override
+ public final boolean __hasSentCallback()
+ {
+ return true;
+ }
+
+ @Override
+ public final void __completed(AsyncResult __result)
+ {
+ try
+ {
+ ((ObjectPrxHelperBase)__result.getProxy()).__end(__result, __result.getOperation());
+ }
+ catch(LocalException __ex)
+ {
+ exception(__ex);
+ return;
+ }
+ catch(SystemException __ex)
+ {
+ exception(__ex);
+ return;
+ }
+ response();
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Optional.java b/java-compat/src/Ice/src/main/java/Ice/Optional.java
new file mode 100644
index 00000000000..b906e31def0
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Optional.java
@@ -0,0 +1,202 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Generic class for optional parameters.
+ **/
+public class Optional<T>
+{
+ /**
+ * The value defaults to unset.
+ **/
+ public Optional()
+ {
+ _isSet = false;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The initial value.
+ **/
+ public Optional(T v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * Sets the value to a shallow copy of the given optional.
+ *
+ * @param opt The source value.
+ **/
+ public Optional(Optional<T> opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Obtains the current value.
+ *
+ * @return The current value.
+ * @throws IllegalStateException If the value is not set.
+ **/
+ public T get()
+ {
+ if(!_isSet)
+ {
+ throw new IllegalStateException("no value is set");
+ }
+ return _value;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The new value.
+ **/
+ public void set(T v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * If the given argument is set, this optional is set to a shallow copy of the argument,
+ * otherwise this optional is unset.
+ *
+ * @param opt The source value.
+ **/
+ public void set(Optional<T> opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Determines whether the value is set.
+ *
+ * @return True if the value is set, false otherwise.
+ **/
+ public boolean isSet()
+ {
+ return _isSet;
+ }
+
+ /**
+ * Unsets this value.
+ **/
+ public void clear()
+ {
+ _isSet = false;
+ _value = null;
+ }
+
+ /**
+ * Helper function for creating Optional instances.
+ *
+ * @param v The initial value of the Optional.
+ *
+ * @return A new Optional instance set to the given value.
+ **/
+ public static <T> Optional<T> O(T v)
+ {
+ return new Optional<T>(v);
+ }
+
+ /**
+ * Helper function for creating BooleanOptional instances.
+ *
+ * @param v The initial value of the Optional.
+ *
+ * @return A new BooleanOptional instance set to the given value.
+ **/
+ public static BooleanOptional O(boolean v)
+ {
+ return new BooleanOptional(v);
+ }
+
+ /**
+ * Helper function for creating ByteOptional instances.
+ *
+ * @param v The initial value of the Optional.
+ *
+ * @return A new ByteOptional instance set to the given value.
+ **/
+ public static ByteOptional O(byte v)
+ {
+ return new ByteOptional(v);
+ }
+
+ /**
+ * Helper function for creating ShortOptional instances.
+ *
+ * @param v The initial value of the Optional.
+ *
+ * @return A new ShortOptional instance set to the given value.
+ **/
+ public static ShortOptional O(short v)
+ {
+ return new ShortOptional(v);
+ }
+
+ /**
+ * Helper function for creating IntOptional instances.
+ *
+ * @param v The initial value of the Optional.
+ *
+ * @return A new IntOptional instance set to the given value.
+ **/
+ public static IntOptional O(int v)
+ {
+ return new IntOptional(v);
+ }
+
+ /**
+ * Helper function for creating LongOptional instances.
+ *
+ * @param v The initial value of the Optional.
+ *
+ * @return A new LongOptional instance set to the given value.
+ **/
+ public static LongOptional O(long v)
+ {
+ return new LongOptional(v);
+ }
+
+ /**
+ * Helper function for creating FloatOptional instances.
+ *
+ * @param v The initial value of the Optional.
+ *
+ * @return A new FloatOptional instance set to the given value.
+ **/
+ public static FloatOptional O(float v)
+ {
+ return new FloatOptional(v);
+ }
+
+ /**
+ * Helper function for creating DoubleOptional instances.
+ *
+ * @param v The initial value of the Optional.
+ *
+ * @return A new DoubleOptional instance set to the given value.
+ **/
+ public static DoubleOptional O(double v)
+ {
+ return new DoubleOptional(v);
+ }
+
+ private T _value;
+ private boolean _isSet;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/OptionalFormat.java b/java-compat/src/Ice/src/main/java/Ice/OptionalFormat.java
new file mode 100644
index 00000000000..2c68b26ea4f
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/OptionalFormat.java
@@ -0,0 +1,70 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * The optional type.
+ *
+ * An optional value is encoded with a specific optional format. This optional
+ * format describes how the data is encoded and how it can be skipped by the
+ * unmarshaling code if the optional is not known to the receiver.
+ *
+ **/
+public enum OptionalFormat
+{
+ F1(0),
+ F2(1),
+ F4(2),
+ F8(3),
+ Size(4),
+ VSize(5),
+ FSize(6),
+ Class(7);
+
+ private
+ OptionalFormat(int value)
+ {
+ _value = value;
+ }
+
+ public int
+ value()
+ {
+ return _value;
+ }
+
+ public static OptionalFormat
+ valueOf(int v)
+ {
+ switch(v)
+ {
+ case 0:
+ return F1;
+ case 1:
+ return F2;
+ case 2:
+ return F4;
+ case 3:
+ return F8;
+ case 4:
+ return Size;
+ case 5:
+ return VSize;
+ case 6:
+ return FSize;
+ case 7:
+ return Class;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private int _value;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/OptionalObject.java b/java-compat/src/Ice/src/main/java/Ice/OptionalObject.java
new file mode 100644
index 00000000000..cbb1c27384c
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/OptionalObject.java
@@ -0,0 +1,70 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Handles callbacks for an optional object parameter.
+ **/
+public class OptionalObject implements ReadValueCallback
+{
+ /**
+ * Instantiates the class with the given optional.
+ *
+ * @param opt The target optional.
+ * @param cls The formal type required for the unmarshaled object.
+ * @param type The Slice type ID corresponding to the formal type.
+ **/
+ @SuppressWarnings("rawtypes")
+ public
+ OptionalObject(Optional opt, Class<?> cls, String type)
+ {
+ this.opt = opt;
+ this.cls = cls;
+ this.type = type;
+ }
+
+ /**
+ * Sets the value of the optional to the passed instance.
+ *
+ * @param v The new value for the optional.
+ **/
+ @SuppressWarnings("unchecked")
+ public void
+ valueReady(Ice.Object v)
+ {
+ if(v == null || cls.isInstance(v))
+ {
+ //
+ // The line below would normally cause an "unchecked cast" warning.
+ //
+ opt.set(v);
+ }
+ else
+ {
+ IceInternal.Ex.throwUOE(type, v);
+ }
+ }
+
+ /**
+ * The optional object.
+ **/
+ @SuppressWarnings("rawtypes")
+ public Optional opt;
+
+ /**
+ * The formal type of the target class.
+ **/
+ public Class<?> cls;
+
+ /**
+ * The Slice type ID of the target class.
+ **/
+ public String type;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/OutputStream.java b/java-compat/src/Ice/src/main/java/Ice/OutputStream.java
new file mode 100644
index 00000000000..c2a028d15a6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/OutputStream.java
@@ -0,0 +1,2426 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public class OutputStream
+{
+ /**
+ * Constructing an OutputStream without providing a communicator means the stream will
+ * use the default encoding version, the default format for class encoding, and a
+ * non-direct buffer. You can supply a communicator later by calling initialize().
+ **/
+ public OutputStream()
+ {
+ this(false);
+ }
+
+ /**
+ * Constructing an OutputStream without providing a communicator means the stream will
+ * use the default encoding version and the default format for class encoding.
+ * You can supply a communicator later by calling initialize().
+ *
+ * @param direct Indicates whether to use a direct buffer.
+ **/
+ public OutputStream(boolean direct)
+ {
+ _buf = new IceInternal.Buffer(direct);
+ _instance = null;
+ _closure = null;
+ _encoding = IceInternal.Protocol.currentEncoding;
+ _format = FormatType.CompactFormat;
+ }
+
+ /**
+ * This constructor uses the communicator's default encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ **/
+ public OutputStream(Communicator communicator)
+ {
+ assert(communicator != null);
+ final IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, instance.defaultsAndOverrides().defaultEncoding, instance.cacheMessageBuffers() > 1);
+ }
+
+ /**
+ * This constructor uses the communicator's default encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ * @param direct Indicates whether to use a direct buffer.
+ **/
+ public OutputStream(Communicator communicator, boolean direct)
+ {
+ assert(communicator != null);
+ final IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, instance.defaultsAndOverrides().defaultEncoding, direct);
+ }
+
+ /**
+ * This constructor uses the given communicator and encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ * @param encoding The desired Ice encoding version.
+ **/
+ public OutputStream(Communicator communicator, EncodingVersion encoding)
+ {
+ assert(communicator != null);
+ final IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, encoding, instance.cacheMessageBuffers() > 1);
+ }
+
+ /**
+ * This constructor uses the given communicator and encoding version.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ * @param encoding The desired Ice encoding version.
+ * @param direct Indicates whether to use a direct buffer.
+ **/
+ public OutputStream(Communicator communicator, EncodingVersion encoding, boolean direct)
+ {
+ assert(communicator != null);
+ final IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, encoding, direct);
+ }
+
+ public OutputStream(IceInternal.Instance instance, EncodingVersion encoding)
+ {
+ initialize(instance, encoding, instance.cacheMessageBuffers() > 1);
+ }
+
+ public OutputStream(IceInternal.Instance instance, EncodingVersion encoding, boolean direct)
+ {
+ initialize(instance, encoding, direct);
+ }
+
+ public OutputStream(IceInternal.Instance instance, EncodingVersion encoding, IceInternal.Buffer buf, boolean adopt)
+ {
+ initialize(instance, encoding, new IceInternal.Buffer(buf, adopt));
+ }
+
+ /**
+ * Initializes the stream to use the communicator's default encoding version and class
+ * encoding format.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ **/
+ public void initialize(Communicator communicator)
+ {
+ assert(communicator != null);
+ final IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, instance.defaultsAndOverrides().defaultEncoding, instance.cacheMessageBuffers() > 1);
+ }
+
+ /**
+ * Initializes the stream to use the given encoding version and the communicator's
+ * default class encoding format.
+ *
+ * @param communicator The communicator to use when initializing the stream.
+ * @param encoding The desired Ice encoding version.
+ **/
+ public void initialize(Communicator communicator, EncodingVersion encoding)
+ {
+ assert(communicator != null);
+ final IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ initialize(instance, encoding, instance.cacheMessageBuffers() > 1);
+ }
+
+ private void initialize(IceInternal.Instance instance, EncodingVersion encoding, boolean direct)
+ {
+ initialize(instance, encoding, new IceInternal.Buffer(direct));
+ }
+
+ private void initialize(IceInternal.Instance instance, EncodingVersion encoding, IceInternal.Buffer buf)
+ {
+ assert(instance != null);
+
+ _instance = instance;
+ _buf = buf;
+ _closure = null;
+ _encoding = encoding;
+
+ _format = _instance.defaultsAndOverrides().defaultFormat;
+
+ _encapsStack = null;
+ _encapsCache = null;
+ }
+
+ /**
+ * Resets this output stream. This method allows the stream to be reused, to avoid creating
+ * unnecessary garbage.
+ **/
+ public void reset()
+ {
+ _buf.reset();
+ clear();
+ }
+
+ /**
+ * Releases any data retained by encapsulations. The {@link #reset} method internally calls </code>clear</code>.
+ **/
+ public void clear()
+ {
+ if(_encapsStack != null)
+ {
+ assert(_encapsStack.next == null);
+ _encapsStack.next = _encapsCache;
+ _encapsCache = _encapsStack;
+ _encapsCache.reset();
+ _encapsStack = null;
+ }
+ }
+
+ public IceInternal.Instance instance()
+ {
+ return _instance;
+ }
+
+ /**
+ * Sets the encoding format for class and exception instances.
+ *
+ * @param fmt The encoding format.
+ **/
+ public void setFormat(FormatType fmt)
+ {
+ _format = fmt;
+ }
+
+ /**
+ * Retrieves the closure object associated with this stream.
+ *
+ * @return The closure object.
+ **/
+ public Object getClosure()
+ {
+ return _closure;
+ }
+
+ /**
+ * Associates a closure object with this stream.
+ *
+ * @param p The new closure object.
+ * @return The previous closure object, or null.
+ **/
+ public Object setClosure(Object p)
+ {
+ Object prev = _closure;
+ _closure = p;
+ return prev;
+ }
+
+ /**
+ * Indicates that marshaling is finished.
+ *
+ * @return The byte sequence containing the encoded data.
+ **/
+ public byte[] finished()
+ {
+ IceInternal.Buffer buf = prepareWrite();
+ byte[] result = new byte[buf.b.limit()];
+ buf.b.get(result);
+ return result;
+ }
+
+ /**
+ * Swaps the contents of one stream with another.
+ *
+ * @param other The other stream.
+ **/
+ public void swap(OutputStream other)
+ {
+ assert(_instance == other._instance);
+
+ IceInternal.Buffer tmpBuf = other._buf;
+ other._buf = _buf;
+ _buf = tmpBuf;
+
+ EncodingVersion tmpEncoding = other._encoding;
+ other._encoding = _encoding;
+ _encoding = tmpEncoding;
+
+ Object tmpClosure = other._closure;
+ other._closure = _closure;
+ _closure = tmpClosure;
+
+ //
+ // Swap is never called for streams that have encapsulations being written. However,
+ // encapsulations might still be set in case marshalling failed. We just
+ // reset the encapsulations if there are still some set.
+ //
+ resetEncapsulation();
+ other.resetEncapsulation();
+ }
+
+ private void resetEncapsulation()
+ {
+ _encapsStack = null;
+ }
+
+ /**
+ * Resizes the stream to a new size.
+ *
+ * @param sz The new size.
+ **/
+ public void resize(int sz)
+ {
+ _buf.resize(sz, false);
+ _buf.b.position(sz);
+ }
+
+ /**
+ * Prepares the internal data buffer to be written to a socket.
+ **/
+ public IceInternal.Buffer prepareWrite()
+ {
+ _buf.b.limit(_buf.size());
+ _buf.b.position(0);
+ return _buf;
+ }
+
+ /**
+ * Retrieves the internal data buffer.
+ *
+ * @return The buffer.
+ **/
+ public IceInternal.Buffer getBuffer()
+ {
+ return _buf;
+ }
+
+ /**
+ * Marks the start of a class instance.
+ *
+ * @param data Preserved slices for this instance, or null.
+ **/
+ public void startValue(SlicedData data)
+ {
+ assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.startInstance(SliceType.ValueSlice, data);
+ }
+
+ /**
+ * Marks the end of a class instance.
+ **/
+ public void endValue()
+ {
+ assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.endInstance();
+ }
+
+ /**
+ * Marks the start of a user exception.
+ *
+ * @param data Preserved slices for this exception, or null.
+ **/
+ public void startException(SlicedData data)
+ {
+ assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.startInstance(SliceType.ExceptionSlice, data);
+ }
+
+ /**
+ * Marks the end of a user exception.
+ **/
+ public void endException()
+ {
+ assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.endInstance();
+ }
+
+ /**
+ * Writes the start of an encapsulation to the stream.
+ **/
+ public void startEncapsulation()
+ {
+ //
+ // 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(_encapsStack != null)
+ {
+ startEncapsulation(_encapsStack.encoding, _encapsStack.format);
+ }
+ else
+ {
+ startEncapsulation(_encoding, FormatType.DefaultFormat);
+ }
+ }
+
+ /**
+ * Writes the start of an encapsulation to the stream.
+ *
+ * @param encoding The encoding version of the encapsulation.
+ *
+ * @param format Specify the compact or sliced format.
+ *
+ **/
+ public void startEncapsulation(EncodingVersion encoding, FormatType format)
+ {
+ IceInternal.Protocol.checkSupportedEncoding(encoding);
+
+ Encaps curr = _encapsCache;
+ if(curr != null)
+ {
+ curr.reset();
+ _encapsCache = _encapsCache.next;
+ }
+ else
+ {
+ curr = new Encaps();
+ }
+ curr.next = _encapsStack;
+ _encapsStack = curr;
+
+ _encapsStack.format = format;
+ _encapsStack.setEncoding(encoding);
+ _encapsStack.start = _buf.size();
+
+ writeInt(0); // Placeholder for the encapsulation length.
+ _encapsStack.encoding.__write(this);
+ }
+
+ /**
+ * Ends the previous encapsulation.
+ **/
+ public void endEncapsulation()
+ {
+ assert(_encapsStack != null);
+
+ // Size includes size and version.
+ int start = _encapsStack.start;
+ int sz = _buf.size() - start;
+ _buf.b.putInt(start, sz);
+
+ Encaps curr = _encapsStack;
+ _encapsStack = curr.next;
+ curr.next = _encapsCache;
+ _encapsCache = curr;
+ _encapsCache.reset();
+ }
+
+ /**
+ * Writes an empty encapsulation using the given encoding version.
+ *
+ * @param encoding The desired encoding version.
+ **/
+ public void writeEmptyEncapsulation(EncodingVersion encoding)
+ {
+ IceInternal.Protocol.checkSupportedEncoding(encoding);
+ writeInt(6); // Size
+ encoding.__write(this);
+ }
+
+ /**
+ * Writes a pre-encoded encapsulation.
+ *
+ * @param v The encapsulation data.
+ **/
+ public void writeEncapsulation(byte[] v)
+ {
+ if(v.length < 6)
+ {
+ throw new EncapsulationException();
+ }
+ expand(v.length);
+ _buf.b.put(v);
+ }
+
+ /**
+ * Determines the current encoding version.
+ *
+ * @return The encoding version.
+ **/
+ public EncodingVersion getEncoding()
+ {
+ return _encapsStack != null ? _encapsStack.encoding : _encoding;
+ }
+
+ /**
+ * Marks the start of a new slice for a class instance or user exception.
+ *
+ * @param typeId The Slice type ID corresponding to this slice.
+
+ * @param compactId The Slice compact type ID corresponding to
+ * this slice or -1 if no compact ID is defined for the
+ * type ID.
+
+ * @param last True if this is the last slice, false otherwise.
+ **/
+ public void startSlice(String typeId, int compactId, boolean last)
+ {
+ assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.startSlice(typeId, compactId, last);
+ }
+
+ /**
+ * Marks the end of a slice for a class instance or user exception.
+ **/
+ public void endSlice()
+ {
+ assert(_encapsStack != null && _encapsStack.encoder != null);
+ _encapsStack.encoder.endSlice();
+ }
+
+ /**
+ * Writes the state of Slice classes whose index was previously
+ * written with {@link #writeValue} to the stream.
+ **/
+ public void writePendingValues()
+ {
+ if(_encapsStack != null && _encapsStack.encoder != null)
+ {
+ _encapsStack.encoder.writePendingValues();
+ }
+ else if(_encapsStack != null ? _encapsStack.encoding_1_0 : _encoding.equals(Util.Encoding_1_0))
+ {
+ //
+ // If using the 1.0 encoding and no instances were written, we
+ // still write an empty sequence for pending instances if
+ // requested (i.e.: if this is called).
+ //
+ // This is required by the 1.0 encoding, even if no instances
+ // are written we do marshal an empty sequence if marshaled
+ // data types use classes.
+ //
+ writeSize(0);
+ }
+ }
+
+ /**
+ * Writes a size to the stream.
+ *
+ * @param v The size to write.
+ **/
+ public void writeSize(int v)
+ {
+ if(v > 254)
+ {
+ expand(5);
+ _buf.b.put((byte)-1);
+ _buf.b.putInt(v);
+ }
+ else
+ {
+ expand(1);
+ _buf.b.put((byte)v);
+ }
+ }
+
+ /**
+ * Returns the current position and allocates four bytes for a fixed-length (32-bit)
+ * size value.
+ *
+ * @return The current position.
+ **/
+ public int startSize()
+ {
+ int pos = _buf.b.position();
+ writeInt(0); // Placeholder for 32-bit size
+ return pos;
+ }
+
+ /**
+ * Computes the amount of data written since the previous call to startSize and
+ * writes that value at the saved position.
+ *
+ * @param pos The saved position.
+ **/
+ public void endSize(int pos)
+ {
+ assert(pos >= 0);
+ rewriteInt(_buf.b.position() - pos - 4, pos);
+ }
+
+ /**
+ * Writes a blob of bytes to the stream.
+ *
+ * @param v The byte array to be written. All of the bytes in the array are written.
+ **/
+ public void writeBlob(byte[] v)
+ {
+ if(v == null)
+ {
+ return;
+ }
+ expand(v.length);
+ _buf.b.put(v);
+ }
+
+ /**
+ * Writes a blob of bytes to the stream.
+ *
+ * @param v The byte array to be written.
+ * @param off The offset into the byte array from which to copy.
+ * @param len The number of bytes from the byte array to copy.
+ **/
+ public void writeBlob(byte[] v, int off, int len)
+ {
+ if(v == null)
+ {
+ return;
+ }
+ expand(len);
+ _buf.b.put(v, off, len);
+ }
+
+ /**
+ * Write the header information for an optional value.
+ *
+ * @param tag The numeric tag associated with the value.
+ * @param format The optional format of the value.
+ **/
+ public boolean writeOptional(int tag, OptionalFormat format)
+ {
+ assert(_encapsStack != null);
+ if(_encapsStack.encoder != null)
+ {
+ return _encapsStack.encoder.writeOptional(tag, format);
+ }
+ else
+ {
+ return writeOptionalImpl(tag, format);
+ }
+ }
+
+ /**
+ * Writes a byte to the stream.
+ *
+ * @param v The byte to write to the stream.
+ **/
+ public void writeByte(byte v)
+ {
+ expand(1);
+ _buf.b.put(v);
+ }
+
+ /**
+ * Writes an optional byte to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional byte to write to the stream.
+ **/
+ public void writeByte(int tag, ByteOptional v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeByte(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional byte to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The byte to write to the stream.
+ **/
+ public void writeByte(int tag, byte v)
+ {
+ if(writeOptional(tag, OptionalFormat.F1))
+ {
+ writeByte(v);
+ }
+ }
+
+ /**
+ * Writes a byte to the stream at the given position. The current position of the stream is not modified.
+ *
+ * @param v The byte to write to the stream.
+ * @param dest The position at which to store the byte in the buffer.
+ **/
+ public void rewriteByte(byte v, int dest)
+ {
+ _buf.b.put(dest, v);
+ }
+
+ /**
+ * Writes a byte sequence to the stream.
+ *
+ * @param v The byte sequence to write to the stream.
+ * Passing <code>null</code> causes an empty sequence to be written to the stream.
+ **/
+ public void writeByteSeq(byte[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.length);
+ expand(v.length);
+ _buf.b.put(v);
+ }
+ }
+
+ /**
+ * Writes an optional byte sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional byte sequence to write to the stream.
+ **/
+ public void writeByteSeq(int tag, Optional<byte[]> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeByteSeq(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional byte sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The byte sequence to write to the stream.
+ **/
+ public void writeByteSeq(int tag, byte[] v)
+ {
+ if(writeOptional(tag, OptionalFormat.VSize))
+ {
+ writeByteSeq(v);
+ }
+ }
+
+ /**
+ * Writes the remaining contents of the byte buffer as a byte sequence to the stream.
+ *
+ * @param v The byte buffer to write to the stream.
+ **/
+ public void writeByteBuffer(java.nio.ByteBuffer v)
+ {
+ if(v == null || v.remaining() == 0)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.remaining());
+ expand(v.remaining());
+ _buf.b.put(v);
+ }
+ }
+
+ /**
+ * Writes a serializable Java object to the stream.
+ *
+ * @param o The serializable object to write.
+ **/
+ public void writeSerializable(java.io.Serializable o)
+ {
+ if(o == null)
+ {
+ writeSize(0);
+ return;
+ }
+ try
+ {
+ IceInternal.OutputStreamWrapper w = new IceInternal.OutputStreamWrapper(this);
+ java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(w);
+ out.writeObject(o);
+ out.close();
+ w.close();
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new MarshalException("cannot serialize object: " + ex);
+ }
+ }
+
+ /**
+ * Writes a boolean to the stream.
+ *
+ * @param v The boolean to write to the stream.
+ **/
+ public void writeBool(boolean v)
+ {
+ expand(1);
+ _buf.b.put(v ? (byte)1 : (byte)0);
+ }
+
+ /**
+ * Writes an optional boolean to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional boolean to write to the stream.
+ **/
+ public void writeBool(int tag, BooleanOptional v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeBool(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional boolean to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The boolean to write to the stream.
+ **/
+ public void writeBool(int tag, boolean v)
+ {
+ if(writeOptional(tag, OptionalFormat.F1))
+ {
+ writeBool(v);
+ }
+ }
+
+ /**
+ * Writes a boolean to the stream at the given position. The current position of the stream is not modified.
+ *
+ * @param v The boolean to write to the stream.
+ * @param dest The position at which to store the boolean in the buffer.
+ **/
+ public void rewriteBool(boolean v, int dest)
+ {
+ _buf.b.put(dest, v ? (byte)1 : (byte)0);
+ }
+
+ /**
+ * Writes a boolean sequence to the stream.
+ *
+ * @param v The boolean sequence to write to the stream.
+ * Passing <code>null</code> causes an empty sequence to be written to the stream.
+ **/
+ public void writeBoolSeq(boolean[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.length);
+ expand(v.length);
+ for(boolean b : v)
+ {
+ _buf.b.put(b ? (byte)1 : (byte)0);
+ }
+ }
+ }
+
+ /**
+ * Writes an optional boolean sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional boolean sequence to write to the stream.
+ **/
+ public void writeBoolSeq(int tag, Optional<boolean[]> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeBoolSeq(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional boolean sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The boolean sequence to write to the stream.
+ **/
+ public void writeBoolSeq(int tag, boolean[] v)
+ {
+ if(writeOptional(tag, OptionalFormat.VSize))
+ {
+ writeBoolSeq(v);
+ }
+ }
+
+ /**
+ * Writes a short to the stream.
+ *
+ * @param v The short to write to the stream.
+ **/
+ public void writeShort(short v)
+ {
+ expand(2);
+ _buf.b.putShort(v);
+ }
+
+ /**
+ * Writes an optional short to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional short to write to the stream.
+ **/
+ public void writeShort(int tag, ShortOptional v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeShort(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional short to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The short to write to the stream.
+ **/
+ public void writeShort(int tag, short v)
+ {
+ if(writeOptional(tag, OptionalFormat.F2))
+ {
+ writeShort(v);
+ }
+ }
+
+ /**
+ * Writes a short sequence to the stream.
+ *
+ * @param v The short sequence to write to the stream.
+ * Passing <code>null</code> causes an empty sequence to be written to the stream.
+ **/
+ public void writeShortSeq(short[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.length);
+ expand(v.length * 2);
+ java.nio.ShortBuffer shortBuf = _buf.b.asShortBuffer();
+ shortBuf.put(v);
+ _buf.b.position(_buf.b.position() + v.length * 2);
+ }
+ }
+
+ /**
+ * Writes an optional short sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional short sequence to write to the stream.
+ **/
+ public void writeShortSeq(int tag, Optional<short[]> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeShortSeq(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional short sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The short sequence to write to the stream.
+ **/
+ public void writeShortSeq(int tag, short[] v)
+ {
+ if(writeOptional(tag, OptionalFormat.VSize))
+ {
+ writeSize(v == null || v.length == 0 ? 1 : v.length * 2 + (v.length > 254 ? 5 : 1));
+ writeShortSeq(v);
+ }
+ }
+
+ /**
+ * Writes the remaining contents of the short buffer as a short sequence to the stream.
+ *
+ * @param v The short buffer to write to the stream.
+ **/
+ public void writeShortBuffer(java.nio.ShortBuffer v)
+ {
+ if(v == null || v.remaining() == 0)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ int sz = v.remaining();
+ writeSize(sz);
+ expand(sz * 2);
+
+ java.nio.ShortBuffer shortBuf = _buf.b.asShortBuffer();
+ shortBuf.put(v);
+ _buf.b.position(_buf.b.position() + sz * 2);
+ }
+ }
+
+ /**
+ * Writes an int to the stream.
+ *
+ * @param v The int to write to the stream.
+ **/
+ public void writeInt(int v)
+ {
+ expand(4);
+ _buf.b.putInt(v);
+ }
+
+ /**
+ * Writes an optional int to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional int to write to the stream.
+ **/
+ public void writeInt(int tag, IntOptional v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeInt(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional int to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The int to write to the stream.
+ **/
+ public void writeInt(int tag, int v)
+ {
+ if(writeOptional(tag, OptionalFormat.F4))
+ {
+ writeInt(v);
+ }
+ }
+
+ /**
+ * Writes an int to the stream at the given position. The current position of the stream is not modified.
+ *
+ * @param v The int to write to the stream.
+ * @param dest The position at which to store the int in the buffer.
+ **/
+ public void rewriteInt(int v, int dest)
+ {
+ _buf.b.putInt(dest, v);
+ }
+
+ /**
+ * Writes an int sequence to the stream.
+ *
+ * @param v The int sequence to write to the stream.
+ * Passing <code>null</code> causes an empty sequence to be written to the stream.
+ **/
+ public void writeIntSeq(int[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.length);
+ expand(v.length * 4);
+ java.nio.IntBuffer intBuf = _buf.b.asIntBuffer();
+ intBuf.put(v);
+ _buf.b.position(_buf.b.position() + v.length * 4);
+ }
+ }
+
+ /**
+ * Writes an optional int sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional int sequence to write to the stream.
+ **/
+ public void writeIntSeq(int tag, Optional<int[]> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeIntSeq(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional int sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The int sequence to write to the stream.
+ **/
+ public void writeIntSeq(int tag, int[] v)
+ {
+ if(writeOptional(tag, OptionalFormat.VSize))
+ {
+ writeSize(v == null || v.length == 0 ? 1 : v.length * 4 + (v.length > 254 ? 5 : 1));
+ writeIntSeq(v);
+ }
+ }
+
+ /**
+ * Writes the remaining contents of the int buffer as an int sequence to the stream.
+ *
+ * @param v The int buffer to write to the stream.
+ **/
+ public void writeIntBuffer(java.nio.IntBuffer v)
+ {
+ if(v == null || v.remaining() == 0)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ int sz = v.remaining();
+ writeSize(sz);
+ expand(sz * 4);
+
+ java.nio.IntBuffer intBuf = _buf.b.asIntBuffer();
+ intBuf.put(v);
+ _buf.b.position(_buf.b.position() + sz * 4);
+ }
+ }
+
+ /**
+ * Writes a long to the stream.
+ *
+ * @param v The long to write to the stream.
+ **/
+ public void writeLong(long v)
+ {
+ expand(8);
+ _buf.b.putLong(v);
+ }
+
+ /**
+ * Writes an optional long to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional long to write to the stream.
+ **/
+ public void writeLong(int tag, LongOptional v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeLong(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional long to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The long to write to the stream.
+ **/
+ public void writeLong(int tag, long v)
+ {
+ if(writeOptional(tag, OptionalFormat.F8))
+ {
+ writeLong(v);
+ }
+ }
+
+ /**
+ * Writes a long sequence to the stream.
+ *
+ * @param v The long sequence to write to the stream.
+ * Passing <code>null</code> causes an empty sequence to be written to the stream.
+ **/
+ public void writeLongSeq(long[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.length);
+ expand(v.length * 8);
+ java.nio.LongBuffer longBuf = _buf.b.asLongBuffer();
+ longBuf.put(v);
+ _buf.b.position(_buf.b.position() + v.length * 8);
+ }
+ }
+
+ /**
+ * Writes an optional long sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional long sequence to write to the stream.
+ **/
+ public void writeLongSeq(int tag, Optional<long[]> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeLongSeq(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional long sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The long sequence to write to the stream.
+ **/
+ public void writeLongSeq(int tag, long[] v)
+ {
+ if(writeOptional(tag, OptionalFormat.VSize))
+ {
+ writeSize(v == null || v.length == 0 ? 1 : v.length * 8 + (v.length > 254 ? 5 : 1));
+ writeLongSeq(v);
+ }
+ }
+
+ /**
+ * Writes the remaining contents of the long buffer as a long sequence to the stream.
+ *
+ * @param v The long buffer to write to the stream.
+ **/
+ public void writeLongBuffer(java.nio.LongBuffer v)
+ {
+ if(v == null || v.remaining() == 0)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ int sz = v.remaining();
+ writeSize(sz);
+ expand(sz * 8);
+
+ java.nio.LongBuffer longBuf = _buf.b.asLongBuffer();
+ longBuf.put(v);
+ _buf.b.position(_buf.b.position() + sz * 8);
+ }
+ }
+
+ /**
+ * Writes a float to the stream.
+ *
+ * @param v The float to write to the stream.
+ **/
+ public void writeFloat(float v)
+ {
+ expand(4);
+ _buf.b.putFloat(v);
+ }
+
+ /**
+ * Writes an optional float to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional float to write to the stream.
+ **/
+ public void writeFloat(int tag, FloatOptional v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeFloat(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional float to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The float to write to the stream.
+ **/
+ public void writeFloat(int tag, float v)
+ {
+ if(writeOptional(tag, OptionalFormat.F4))
+ {
+ writeFloat(v);
+ }
+ }
+
+ /**
+ * Writes a float sequence to the stream.
+ *
+ * @param v The float sequence to write to the stream.
+ * Passing <code>null</code> causes an empty sequence to be written to the stream.
+ **/
+ public void writeFloatSeq(float[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.length);
+ expand(v.length * 4);
+ java.nio.FloatBuffer floatBuf = _buf.b.asFloatBuffer();
+ floatBuf.put(v);
+ _buf.b.position(_buf.b.position() + v.length * 4);
+ }
+ }
+
+ /**
+ * Writes an optional float sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional float sequence to write to the stream.
+ **/
+ public void writeFloatSeq(int tag, Optional<float[]> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeFloatSeq(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional float sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The float sequence to write to the stream.
+ **/
+ public void writeFloatSeq(int tag, float[] v)
+ {
+ if(writeOptional(tag, OptionalFormat.VSize))
+ {
+ writeSize(v == null || v.length == 0 ? 1 : v.length * 4 + (v.length > 254 ? 5 : 1));
+ writeFloatSeq(v);
+ }
+ }
+
+ /**
+ * Writes the remaining contents of the float buffer as a float sequence to the stream.
+ *
+ * @param v The float buffer to write to the stream.
+ **/
+ public void writeFloatBuffer(java.nio.FloatBuffer v)
+ {
+ if(v == null || v.remaining() == 0)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ int sz = v.remaining();
+ writeSize(sz);
+ expand(sz * 4);
+
+ java.nio.FloatBuffer floatBuf = _buf.b.asFloatBuffer();
+ floatBuf.put(v);
+ _buf.b.position(_buf.b.position() + sz * 4);
+ }
+ }
+
+ /**
+ * Writes a double to the stream.
+ *
+ * @param v The double to write to the stream.
+ **/
+ public void writeDouble(double v)
+ {
+ expand(8);
+ _buf.b.putDouble(v);
+ }
+
+ /**
+ * Writes an optional double to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional double to write to the stream.
+ **/
+ public void writeDouble(int tag, DoubleOptional v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeDouble(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional double to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The double to write to the stream.
+ **/
+ public void writeDouble(int tag, double v)
+ {
+ if(writeOptional(tag, OptionalFormat.F8))
+ {
+ writeDouble(v);
+ }
+ }
+
+ /**
+ * Writes a double sequence to the stream.
+ *
+ * @param v The double sequence to write to the stream.
+ * Passing <code>null</code> causes an empty sequence to be written to the stream.
+ **/
+ public void writeDoubleSeq(double[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.length);
+ expand(v.length * 8);
+ java.nio.DoubleBuffer doubleBuf = _buf.b.asDoubleBuffer();
+ doubleBuf.put(v);
+ _buf.b.position(_buf.b.position() + v.length * 8);
+ }
+ }
+
+ /**
+ * Writes an optional double sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional double sequence to write to the stream.
+ **/
+ public void writeDoubleSeq(int tag, Optional<double[]> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeDoubleSeq(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional double sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The double sequence to write to the stream.
+ **/
+ public void writeDoubleSeq(int tag, double[] v)
+ {
+ if(writeOptional(tag, OptionalFormat.VSize))
+ {
+ writeSize(v == null || v.length == 0 ? 1 : v.length * 8 + (v.length > 254 ? 5 : 1));
+ writeDoubleSeq(v);
+ }
+ }
+
+ /**
+ * Writes the remaining contents of the double buffer as a double sequence to the stream.
+ *
+ * @param v The double buffer to write to the stream.
+ **/
+ public void writeDoubleBuffer(java.nio.DoubleBuffer v)
+ {
+ if(v == null || v.remaining() == 0)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ int sz = v.remaining();
+ writeSize(sz);
+ expand(sz * 8);
+
+ java.nio.DoubleBuffer doubleBuf = _buf.b.asDoubleBuffer();
+ doubleBuf.put(v);
+ _buf.b.position(_buf.b.position() + sz * 8);
+ }
+ }
+
+ final static java.nio.charset.Charset _utf8 = java.nio.charset.Charset.forName("UTF8");
+ private java.nio.charset.CharsetEncoder _charEncoder = null;
+
+ /**
+ * Writes a string to the stream.
+ *
+ * @param v The string to write to the stream. Passing <code>null</code> causes
+ * an empty string to be written to the stream.
+ **/
+ public void writeString(String v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ final int len = v.length();
+ if(len > 0)
+ {
+ if(_stringBytes == null || len > _stringBytes.length)
+ {
+ _stringBytes = new byte[len];
+ }
+ if(_stringChars == null || len > _stringChars.length)
+ {
+ _stringChars = new char[len];
+ }
+ //
+ // If the string contains only 7-bit characters, it's more efficient
+ // to perform the conversion to UTF-8 manually.
+ //
+ v.getChars(0, len, _stringChars, 0);
+ for(int i = 0; i < len; ++i)
+ {
+ if(_stringChars[i] > (char)127)
+ {
+ //
+ // Found a multibyte character.
+ //
+ if(_charEncoder == null)
+ {
+ _charEncoder = _utf8.newEncoder();
+ }
+ java.nio.ByteBuffer b = null;
+ try
+ {
+ b = _charEncoder.encode(java.nio.CharBuffer.wrap(_stringChars, 0, len));
+ }
+ catch(java.nio.charset.CharacterCodingException ex)
+ {
+ throw new MarshalException(ex);
+ }
+ writeSize(b.limit());
+ expand(b.limit());
+ _buf.b.put(b);
+ return;
+ }
+ _stringBytes[i] = (byte)_stringChars[i];
+ }
+ writeSize(len);
+ expand(len);
+ _buf.b.put(_stringBytes, 0, len);
+ }
+ else
+ {
+ writeSize(0);
+ }
+ }
+ }
+
+ /**
+ * Writes an optional string to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional string to write to the stream.
+ **/
+ public void writeString(int tag, Optional<String> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeString(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional string to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The string to write to the stream.
+ **/
+ public void writeString(int tag, String v)
+ {
+ if(writeOptional(tag, OptionalFormat.VSize))
+ {
+ writeString(v);
+ }
+ }
+
+ /**
+ * Writes a string sequence to the stream.
+ *
+ * @param v The string sequence to write to the stream.
+ * Passing <code>null</code> causes an empty sequence to be written to the stream.
+ **/
+ public void writeStringSeq(String[] v)
+ {
+ if(v == null)
+ {
+ writeSize(0);
+ }
+ else
+ {
+ writeSize(v.length);
+ for(String e : v)
+ {
+ writeString(e);
+ }
+ }
+ }
+
+ /**
+ * Writes an optional string sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional string sequence to write to the stream.
+ **/
+ public void writeStringSeq(int tag, Optional<String[]> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeStringSeq(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional string sequence to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The string sequence to write to the stream.
+ **/
+ public void writeStringSeq(int tag, String[] v)
+ {
+ if(writeOptional(tag, OptionalFormat.FSize))
+ {
+ int pos = startSize();
+ writeStringSeq(v);
+ endSize(pos);
+ }
+ }
+
+ /**
+ * Writes a proxy to the stream.
+ *
+ * @param v The proxy to write.
+ **/
+ public void writeProxy(ObjectPrx v)
+ {
+ if(v != null)
+ {
+ v.__write(this);
+ }
+ else
+ {
+ Identity ident = new Identity();
+ ident.__write(this);
+ }
+ }
+
+ /**
+ * Writes an optional proxy to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional proxy to write to the stream.
+ **/
+ public void writeProxy(int tag, Optional<ObjectPrx> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeProxy(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional proxy to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The proxy to write to the stream.
+ **/
+ public void writeProxy(int tag, ObjectPrx v)
+ {
+ if(writeOptional(tag, OptionalFormat.FSize))
+ {
+ int pos = startSize();
+ writeProxy(v);
+ endSize(pos);
+ }
+ }
+
+ /**
+ * Write an enumerated value.
+ *
+ * @param v The enumerator.
+ * @param maxValue The maximum enumerator value in the definition.
+ **/
+ public void writeEnum(int v, int maxValue)
+ {
+ if(isEncoding_1_0())
+ {
+ if(maxValue < 127)
+ {
+ writeByte((byte)v);
+ }
+ else if(maxValue < 32767)
+ {
+ writeShort((short)v);
+ }
+ else
+ {
+ writeInt(v);
+ }
+ }
+ else
+ {
+ writeSize(v);
+ }
+ }
+
+ /**
+ * Writes a Slice value to the stream.
+ *
+ * @param v The value to write. This method writes the index of an instance; the state of the value is
+ * written once {@link #writePendingValues} is called.
+ **/
+ public void writeValue(Ice.Object v)
+ {
+ initEncaps();
+ _encapsStack.encoder.writeValue(v);
+ }
+
+ /**
+ * Writes an optional value to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The optional value to write to the stream.
+ **/
+ public <T extends Ice.Object> void writeValue(int tag, Optional<T> v)
+ {
+ if(v != null && v.isSet())
+ {
+ writeValue(tag, v.get());
+ }
+ }
+
+ /**
+ * Writes an optional value to the stream.
+ *
+ * @param tag The optional tag.
+ * @param v The value to write to the stream.
+ **/
+ public void writeValue(int tag, Ice.Object v)
+ {
+ if(writeOptional(tag, OptionalFormat.Class))
+ {
+ writeValue(v);
+ }
+ }
+
+ /**
+ * Writes a user exception to the stream.
+ *
+ * @param v The user exception to write.
+ **/
+ public void writeException(UserException v)
+ {
+ initEncaps();
+ _encapsStack.encoder.writeException(v);
+ }
+
+ private boolean writeOptionalImpl(int tag, OptionalFormat format)
+ {
+ if(isEncoding_1_0())
+ {
+ return false; // Optional members aren't supported with the 1.0 encoding.
+ }
+
+ int v = format.value();
+ if(tag < 30)
+ {
+ v |= tag << 3;
+ writeByte((byte)v);
+ }
+ else
+ {
+ v |= 0x0F0; // tag = 30
+ writeByte((byte)v);
+ writeSize(tag);
+ }
+ return true;
+ }
+
+ /**
+ * Determines the current position in the stream.
+ *
+ * @return The current position.
+ **/
+ public int pos()
+ {
+ return _buf.b.position();
+ }
+
+ /**
+ * Sets the current position in the stream.
+ *
+ * @param n The new position.
+ **/
+ public void pos(int n)
+ {
+ _buf.b.position(n);
+ }
+
+ /**
+ * Determines the current size of the stream.
+ *
+ * @return The current size.
+ **/
+ public int size()
+ {
+ return _buf.size();
+ }
+
+ /**
+ * Determines whether the stream is empty.
+ *
+ * @return True if no data has been written yet, false otherwise.
+ **/
+ public boolean isEmpty()
+ {
+ return _buf.empty();
+ }
+
+ /**
+ * Expand the stream to accept more data.
+ *
+ * @param n The number of bytes to accommodate in the stream.
+ **/
+ public void expand(int n)
+ {
+ _buf.expand(n);
+ }
+
+ private IceInternal.Instance _instance;
+ private IceInternal.Buffer _buf;
+ private Object _closure;
+ private FormatType _format;
+ private byte[] _stringBytes; // Reusable array for string operations.
+ private char[] _stringChars; // Reusable array for string operations.
+
+ private enum SliceType { NoSlice, ValueSlice, ExceptionSlice }
+
+ abstract private static class EncapsEncoder
+ {
+ protected EncapsEncoder(OutputStream stream, Encaps encaps)
+ {
+ _stream = stream;
+ _encaps = encaps;
+ _typeIdIndex = 0;
+ _marshaledMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
+ }
+
+ abstract void writeValue(Ice.Object v);
+ abstract void writeException(UserException v);
+
+ abstract void startInstance(SliceType type, SlicedData data);
+ abstract void endInstance();
+ abstract void startSlice(String typeId, int compactId, boolean last);
+ abstract void endSlice();
+
+ boolean writeOptional(int tag, OptionalFormat format)
+ {
+ return false;
+ }
+
+ void writePendingValues()
+ {
+ }
+
+ protected int registerTypeId(String typeId)
+ {
+ if(_typeIdMap == null) // Lazy initialization
+ {
+ _typeIdMap = new java.util.TreeMap<String, Integer>();
+ }
+
+ Integer p = _typeIdMap.get(typeId);
+ if(p != null)
+ {
+ return p;
+ }
+ else
+ {
+ _typeIdMap.put(typeId, ++_typeIdIndex);
+ return -1;
+ }
+ }
+
+ final protected OutputStream _stream;
+ final protected Encaps _encaps;
+
+ // Encapsulation attributes for instance marshaling.
+ final protected java.util.IdentityHashMap<Ice.Object, Integer> _marshaledMap;
+ private java.util.TreeMap<String, Integer> _typeIdMap;
+ private int _typeIdIndex;
+ }
+
+ private static final class EncapsEncoder10 extends EncapsEncoder
+ {
+ EncapsEncoder10(OutputStream stream, Encaps encaps)
+ {
+ super(stream, encaps);
+ _sliceType = SliceType.NoSlice;
+ _valueIdIndex = 0;
+ _toBeMarshaledMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
+ }
+
+ @Override
+ void writeValue(Ice.Object v)
+ {
+ //
+ // Object references are encoded as a negative integer in 1.0.
+ //
+ if(v != null)
+ {
+ _stream.writeInt(-registerValue(v));
+ }
+ else
+ {
+ _stream.writeInt(0);
+ }
+ }
+
+ @Override
+ void writeException(UserException v)
+ {
+ //
+ // 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 instances even if some part of
+ // the exception was sliced.
+ //
+ boolean usesClasses = v.__usesClasses();
+ _stream.writeBool(usesClasses);
+ v.__write(_stream);
+ if(usesClasses)
+ {
+ writePendingValues();
+ }
+ }
+
+ @Override
+ void startInstance(SliceType sliceType, SlicedData sliceData)
+ {
+ _sliceType = sliceType;
+ }
+
+ @Override
+ void endInstance()
+ {
+ if(_sliceType == SliceType.ValueSlice)
+ {
+ //
+ // Write the Object slice.
+ //
+ startSlice(ObjectImpl.ice_staticId(), -1, true);
+ _stream.writeSize(0); // For compatibility with the old AFM.
+ endSlice();
+ }
+ _sliceType = SliceType.NoSlice;
+ }
+
+ @Override
+ void startSlice(String typeId, int compactId, boolean last)
+ {
+ //
+ // For instance 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(_sliceType == SliceType.ValueSlice)
+ {
+ int index = registerTypeId(typeId);
+ if(index < 0)
+ {
+ _stream.writeBool(false);
+ _stream.writeString(typeId);
+ }
+ else
+ {
+ _stream.writeBool(true);
+ _stream.writeSize(index);
+ }
+ }
+ else
+ {
+ _stream.writeString(typeId);
+ }
+
+ _stream.writeInt(0); // Placeholder for the slice length.
+
+ _writeSlice = _stream.pos();
+ }
+
+ @Override
+ void endSlice()
+ {
+ //
+ // Write the slice length.
+ //
+ final int sz = _stream.pos() - _writeSlice + 4;
+ _stream.rewriteInt(sz, _writeSlice - 4);
+ }
+
+ @Override
+ void writePendingValues()
+ {
+ while(_toBeMarshaledMap.size() > 0)
+ {
+ //
+ // Consider the to be marshalled instances as marshaled now,
+ // this is necessary to avoid adding again the "to be
+ // marshaled instances" into _toBeMarshaledMap while writing
+ // instances.
+ //
+ _marshaledMap.putAll(_toBeMarshaledMap);
+
+ java.util.IdentityHashMap<Ice.Object, Integer> savedMap = _toBeMarshaledMap;
+ _toBeMarshaledMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
+ _stream.writeSize(savedMap.size());
+ for(java.util.Map.Entry<Ice.Object, Integer> p : savedMap.entrySet())
+ {
+ //
+ // Ask the instance to marshal itself. Any new class
+ // instances that are triggered by the classes marshaled
+ // are added to toBeMarshaledMap.
+ //
+ _stream.writeInt(p.getValue().intValue());
+
+ try
+ {
+ p.getKey().ice_preMarshal();
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception raised by ice_preMarshal:\n" + IceInternal.Ex.toString(ex);
+ _stream.instance().initializationData().logger.warning(s);
+ }
+
+ p.getKey().__write(_stream);
+ }
+ }
+ _stream.writeSize(0); // Zero marker indicates end of sequence of sequences of instances.
+ }
+
+ private int registerValue(Ice.Object v)
+ {
+ assert(v != null);
+
+ //
+ // Look for this instance in the to-be-marshaled map.
+ //
+ Integer p = _toBeMarshaledMap.get(v);
+ if(p != null)
+ {
+ return p.intValue();
+ }
+
+ //
+ // Didn't find it, try the marshaled map next.
+ //
+ p = _marshaledMap.get(v);
+ if(p != null)
+ {
+ return p.intValue();
+ }
+
+ //
+ // We haven't seen this instance previously, create a new
+ // index, and insert it into the to-be-marshaled map.
+ //
+ _toBeMarshaledMap.put(v, ++_valueIdIndex);
+ return _valueIdIndex;
+ }
+
+ // Instance attributes
+ private SliceType _sliceType;
+
+ // Slice attributes
+ private int _writeSlice; // Position of the slice data members
+
+ // Encapsulation attributes for instance marshaling.
+ private int _valueIdIndex;
+ private java.util.IdentityHashMap<Ice.Object, Integer> _toBeMarshaledMap;
+ }
+
+ private static final class EncapsEncoder11 extends EncapsEncoder
+ {
+ EncapsEncoder11(OutputStream stream, Encaps encaps)
+ {
+ super(stream, encaps);
+ _current = null;
+ _valueIdIndex = 1;
+ }
+
+ @Override
+ void writeValue(Ice.Object v)
+ {
+ if(v == null)
+ {
+ _stream.writeSize(0);
+ }
+ else if(_current != null && _encaps.format == FormatType.SlicedFormat)
+ {
+ if(_current.indirectionTable == null) // Lazy initialization
+ {
+ _current.indirectionTable = new java.util.ArrayList<Ice.Object>();
+ _current.indirectionMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
+ }
+
+ //
+ // If writing an instance within a slice and using the sliced
+ // format, write an index from the instance indirection
+ // table. The indirect instance table is encoded at the end of
+ // each slice and is always read (even if the Slice is
+ // unknown).
+ //
+ Integer index = _current.indirectionMap.get(v);
+ if(index == null)
+ {
+ _current.indirectionTable.add(v);
+ final int idx = _current.indirectionTable.size(); // Position + 1 (0 is reserved for nil)
+ _current.indirectionMap.put(v, idx);
+ _stream.writeSize(idx);
+ }
+ else
+ {
+ _stream.writeSize(index.intValue());
+ }
+ }
+ else
+ {
+ writeInstance(v); // Write the instance or a reference if already marshaled.
+ }
+ }
+
+ @Override
+ void writeException(UserException v)
+ {
+ v.__write(_stream);
+ }
+
+ @Override
+ void startInstance(SliceType sliceType, SlicedData data)
+ {
+ if(_current == null)
+ {
+ _current = new InstanceData(null);
+ }
+ else
+ {
+ _current = _current.next == null ? new InstanceData(_current) : _current.next;
+ }
+ _current.sliceType = sliceType;
+ _current.firstSlice = true;
+
+ if(data != null)
+ {
+ writeSlicedData(data);
+ }
+ }
+
+ @Override
+ void endInstance()
+ {
+ _current = _current.previous;
+ }
+
+ @Override
+ void startSlice(String typeId, int compactId, boolean last)
+ {
+ assert((_current.indirectionTable == null || _current.indirectionTable.isEmpty()) &&
+ (_current.indirectionMap == null || _current.indirectionMap.isEmpty()));
+
+ _current.sliceFlagsPos = _stream.pos();
+
+ _current.sliceFlags = (byte)0;
+ if(_encaps.format == FormatType.SlicedFormat)
+ {
+ // Encode the slice size if using the sliced format.
+ _current.sliceFlags |= IceInternal.Protocol.FLAG_HAS_SLICE_SIZE;
+ }
+ if(last)
+ {
+ _current.sliceFlags |= IceInternal.Protocol.FLAG_IS_LAST_SLICE; // This is the last slice.
+ }
+
+ _stream.writeByte((byte)0); // Placeholder for the slice flags
+
+ //
+ // For instance 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(_current.sliceType == SliceType.ValueSlice)
+ {
+ //
+ // Encode the type ID (only in the first slice for the compact
+ // encoding).
+ //
+ if(_encaps.format == FormatType.SlicedFormat || _current.firstSlice)
+ {
+ if(compactId >= 0)
+ {
+ _current.sliceFlags |= IceInternal.Protocol.FLAG_HAS_TYPE_ID_COMPACT;
+ _stream.writeSize(compactId);
+ }
+ else
+ {
+ int index = registerTypeId(typeId);
+ if(index < 0)
+ {
+ _current.sliceFlags |= IceInternal.Protocol.FLAG_HAS_TYPE_ID_STRING;
+ _stream.writeString(typeId);
+ }
+ else
+ {
+ _current.sliceFlags |= IceInternal.Protocol.FLAG_HAS_TYPE_ID_INDEX;
+ _stream.writeSize(index);
+ }
+ }
+ }
+ }
+ else
+ {
+ _stream.writeString(typeId);
+ }
+
+ if((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_SLICE_SIZE) != 0)
+ {
+ _stream.writeInt(0); // Placeholder for the slice length.
+ }
+
+ _current.writeSlice = _stream.pos();
+ _current.firstSlice = false;
+ }
+
+ @Override
+ void endSlice()
+ {
+ //
+ // 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((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_OPTIONAL_MEMBERS) != 0)
+ {
+ _stream.writeByte((byte)IceInternal.Protocol.OPTIONAL_END_MARKER);
+ }
+
+ //
+ // Write the slice length if necessary.
+ //
+ if((_current.sliceFlags & IceInternal.Protocol.FLAG_HAS_SLICE_SIZE) != 0)
+ {
+ final int sz = _stream.pos() - _current.writeSlice + 4;
+ _stream.rewriteInt(sz, _current.writeSlice - 4);
+ }
+
+ //
+ // Only write the indirection table if it contains entries.
+ //
+ if(_current.indirectionTable != null && !_current.indirectionTable.isEmpty())
+ {
+ assert(_encaps.format == FormatType.SlicedFormat);
+ _current.sliceFlags |= IceInternal.Protocol.FLAG_HAS_INDIRECTION_TABLE;
+
+ //
+ // Write the indirection instance table.
+ //
+ _stream.writeSize(_current.indirectionTable.size());
+ for(Ice.Object v : _current.indirectionTable)
+ {
+ writeInstance(v);
+ }
+ _current.indirectionTable.clear();
+ _current.indirectionMap.clear();
+ }
+
+ //
+ // Finally, update the slice flags.
+ //
+ _stream.rewriteByte(_current.sliceFlags, _current.sliceFlagsPos);
+ }
+
+ @Override
+ boolean writeOptional(int tag, OptionalFormat format)
+ {
+ if(_current == null)
+ {
+ return _stream.writeOptionalImpl(tag, format);
+ }
+ else
+ {
+ if(_stream.writeOptionalImpl(tag, format))
+ {
+ _current.sliceFlags |= IceInternal.Protocol.FLAG_HAS_OPTIONAL_MEMBERS;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ private void writeSlicedData(SlicedData slicedData)
+ {
+ assert(slicedData != null);
+
+ //
+ // We only remarshal preserved slices if we are using the sliced
+ // format. Otherwise, we ignore the preserved slices, which
+ // essentially "slices" the instance into the most-derived type
+ // known by the sender.
+ //
+ if(_encaps.format != FormatType.SlicedFormat)
+ {
+ return;
+ }
+
+ for(SliceInfo info : slicedData.slices)
+ {
+ startSlice(info.typeId, info.compactId, info.isLastSlice);
+
+ //
+ // Write the bytes associated with this slice.
+ //
+ _stream.writeBlob(info.bytes);
+
+ if(info.hasOptionalMembers)
+ {
+ _current.sliceFlags |= IceInternal.Protocol.FLAG_HAS_OPTIONAL_MEMBERS;
+ }
+
+ //
+ // Make sure to also re-write the instance indirection table.
+ //
+ if(info.instances != null && info.instances.length > 0)
+ {
+ if(_current.indirectionTable == null) // Lazy initialization
+ {
+ _current.indirectionTable = new java.util.ArrayList<Ice.Object>();
+ _current.indirectionMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
+ }
+ for(Ice.Object o : info.instances)
+ {
+ _current.indirectionTable.add(o);
+ }
+ }
+
+ endSlice();
+ }
+ }
+
+ private void writeInstance(Ice.Object v)
+ {
+ assert(v != null);
+
+ //
+ // If the instance was already marshaled, just write it's ID.
+ //
+ Integer p = _marshaledMap.get(v);
+ if(p != null)
+ {
+ _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.
+ //
+ _marshaledMap.put(v, ++_valueIdIndex);
+
+ try
+ {
+ v.ice_preMarshal();
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception raised by ice_preMarshal:\n" + IceInternal.Ex.toString(ex);
+ _stream.instance().initializationData().logger.warning(s);
+ }
+
+ _stream.writeSize(1); // Class instance marker.
+ v.__write(_stream);
+ }
+
+ private static final class InstanceData
+ {
+ InstanceData(InstanceData previous)
+ {
+ if(previous != null)
+ {
+ previous.next = this;
+ }
+ this.previous = previous;
+ this.next = null;
+ }
+
+ // Instance attributes
+ SliceType sliceType;
+ boolean firstSlice;
+
+ // Slice attributes
+ byte sliceFlags;
+ int writeSlice; // Position of the slice data members
+ int sliceFlagsPos; // Position of the slice flags
+ java.util.List<Ice.Object> indirectionTable;
+ java.util.IdentityHashMap<Ice.Object, Integer> indirectionMap;
+
+ final InstanceData previous;
+ InstanceData next;
+ }
+
+ private InstanceData _current;
+
+ private int _valueIdIndex; // The ID of the next instance to marhsal
+ }
+
+ private static final class Encaps
+ {
+ void reset()
+ {
+ encoder = null;
+ }
+
+ void setEncoding(EncodingVersion encoding)
+ {
+ this.encoding = encoding;
+ encoding_1_0 = encoding.equals(Util.Encoding_1_0);
+ }
+
+ int start;
+ FormatType format = FormatType.DefaultFormat;
+ EncodingVersion encoding;
+ boolean encoding_1_0;
+
+ EncapsEncoder encoder;
+
+ Encaps next;
+ }
+
+ //
+ // The encoding version to use when there's no encapsulation to
+ // read from or write to. This is for example used to read message
+ // headers or when the user is using the streaming API with no
+ // encapsulation.
+ //
+ private EncodingVersion _encoding;
+
+ private boolean isEncoding_1_0()
+ {
+ return _encapsStack != null ? _encapsStack.encoding_1_0 : _encoding.equals(Util.Encoding_1_0);
+ }
+
+ private Encaps _encapsStack;
+ private Encaps _encapsCache;
+
+ private void initEncaps()
+ {
+ if(_encapsStack == null) // Lazy initialization
+ {
+ _encapsStack = _encapsCache;
+ if(_encapsStack != null)
+ {
+ _encapsCache = _encapsCache.next;
+ }
+ else
+ {
+ _encapsStack = new Encaps();
+ }
+ _encapsStack.setEncoding(_encoding);
+ }
+
+ if(_encapsStack.format == FormatType.DefaultFormat)
+ {
+ _encapsStack.format = _format;
+ }
+
+ if(_encapsStack.encoder == null) // Lazy initialization.
+ {
+ if(_encapsStack.encoding_1_0)
+ {
+ _encapsStack.encoder = new EncapsEncoder10(this, _encapsStack);
+ }
+ else
+ {
+ _encapsStack.encoder = new EncapsEncoder11(this, _encapsStack);
+ }
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/PluginFactory.java b/java-compat/src/Ice/src/main/java/Ice/PluginFactory.java
new file mode 100644
index 00000000000..a92439a8d9e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/PluginFactory.java
@@ -0,0 +1,27 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Applications implement this interface to provide a plug-in factory
+ * to the Ice run time.
+ **/
+public interface PluginFactory
+{
+ /**
+ * Called by the Ice run time to create a new plug-in.
+ *
+ * @param communicator The communicator that is in the process of being initialized.
+ * @param name The name of the plug-in.
+ * @param args The arguments that are specified in the plug-ins configuration.
+ * @return The plug-in that was created by this method.
+ **/
+ Plugin create(Communicator communicator, String name, String[] args);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/PluginManagerI.java b/java-compat/src/Ice/src/main/java/Ice/PluginManagerI.java
new file mode 100644
index 00000000000..6b40bb0f333
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/PluginManagerI.java
@@ -0,0 +1,549 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+import java.net.URLEncoder;
+
+public final class PluginManagerI implements PluginManager
+{
+ private static String _kindOfObject = "plugin";
+
+ @Override
+ public synchronized void
+ initializePlugins()
+ {
+ if(_initialized)
+ {
+ InitializationException ex = new InitializationException();
+ ex.reason = "plug-ins already initialized";
+ throw ex;
+ }
+
+ //
+ // Invoke initialize() on the plug-ins, in the order they were loaded.
+ //
+ java.util.List<Plugin> initializedPlugins = new java.util.ArrayList<Plugin>();
+ try
+ {
+ for(PluginInfo p : _plugins)
+ {
+ try
+ {
+ p.plugin.initialize();
+ }
+ catch(Ice.PluginInitializationException ex)
+ {
+ throw ex;
+ }
+ catch(RuntimeException ex)
+ {
+ PluginInitializationException e = new PluginInitializationException();
+ e.reason = "plugin `" + p.name + "' initialization failed";
+ e.initCause(ex);
+ throw e;
+ }
+ initializedPlugins.add(p.plugin);
+ }
+ }
+ catch(RuntimeException ex)
+ {
+ //
+ // Destroy the plug-ins that have been successfully initialized, in the
+ // reverse order.
+ //
+ java.util.ListIterator<Plugin> i = initializedPlugins.listIterator(initializedPlugins.size());
+ while(i.hasPrevious())
+ {
+ Plugin p = i.previous();
+ try
+ {
+ p.destroy();
+ }
+ catch(RuntimeException e)
+ {
+ // Ignore.
+ }
+ }
+ throw ex;
+ }
+
+ _initialized = true;
+ }
+
+ @Override
+ public synchronized String[]
+ getPlugins()
+ {
+ java.util.ArrayList<String> names = new java.util.ArrayList<String>();
+ for(PluginInfo p : _plugins)
+ {
+ names.add(p.name);
+ }
+ return names.toArray(new String[0]);
+ }
+
+ @Override
+ public synchronized Plugin
+ getPlugin(String name)
+ {
+ if(_communicator == null)
+ {
+ throw new CommunicatorDestroyedException();
+ }
+
+ Plugin p = findPlugin(name);
+ if(p != null)
+ {
+ return p;
+ }
+
+ NotRegisteredException ex = new NotRegisteredException();
+ ex.id = name;
+ ex.kindOfObject = _kindOfObject;
+ throw ex;
+ }
+
+ @Override
+ public synchronized void
+ addPlugin(String name, Plugin plugin)
+ {
+ if(_communicator == null)
+ {
+ throw new CommunicatorDestroyedException();
+ }
+
+ if(findPlugin(name) != null)
+ {
+ AlreadyRegisteredException ex = new AlreadyRegisteredException();
+ ex.id = name;
+ ex.kindOfObject = _kindOfObject;
+ throw ex;
+ }
+
+ PluginInfo info = new PluginInfo();
+ info.name = name;
+ info.plugin = plugin;
+ _plugins.add(info);
+ }
+
+ @Override
+ public synchronized void
+ destroy()
+ {
+ if(_communicator != null)
+ {
+ if(_initialized)
+ {
+ java.util.ListIterator<PluginInfo> i = _plugins.listIterator(_plugins.size());
+ while(i.hasPrevious())
+ {
+ PluginInfo p = i.previous();
+ try
+ {
+ p.plugin.destroy();
+ }
+ catch(RuntimeException ex)
+ {
+ Ice.Util.getProcessLogger().warning("unexpected exception raised by plug-in `" +
+ p.name + "' destruction:\n" + ex.toString());
+ }
+ }
+ }
+
+ _communicator = null;
+ }
+
+ _plugins.clear();
+
+ if(_classLoaders != null)
+ {
+ _classLoaders.clear();
+ }
+ }
+
+ public
+ PluginManagerI(Communicator communicator, IceInternal.Instance instance)
+ {
+ _communicator = communicator;
+ _instance = instance;
+ _initialized = false;
+ }
+
+ public void
+ loadPlugins(StringSeqHolder cmdArgs)
+ {
+ assert(_communicator != null);
+
+ //
+ // Load and initialize the plug-ins defined in the property set
+ // with the prefix "Ice.Plugin.". These properties should
+ // have the following format:
+ //
+ // Ice.Plugin.name[.<language>]=entry_point [args]
+ //
+ // If the Ice.PluginLoadOrder property is defined, load the
+ // specified plug-ins in the specified order, then load any
+ // remaining plug-ins.
+ //
+ final String prefix = "Ice.Plugin.";
+ Properties properties = _communicator.getProperties();
+ java.util.Map<String, String> plugins = properties.getPropertiesForPrefix(prefix);
+
+ final String[] loadOrder = properties.getPropertyAsList("Ice.PluginLoadOrder");
+ for(String name : loadOrder)
+ {
+ if(findPlugin(name) != null)
+ {
+ PluginInitializationException ex = new PluginInitializationException();
+ ex.reason = "plug-in `" + name + "' already loaded";
+ throw ex;
+ }
+
+ String key = "Ice.Plugin." + name + ".java";
+ boolean hasKey = plugins.containsKey(key);
+ if(hasKey)
+ {
+ plugins.remove("Ice.Plugin." + name);
+ }
+ else
+ {
+ key = "Ice.Plugin." + name;
+ hasKey = plugins.containsKey(key);
+ }
+
+ if(hasKey)
+ {
+ final String value = plugins.get(key);
+ loadPlugin(name, value, cmdArgs);
+ plugins.remove(key);
+ }
+ else
+ {
+ PluginInitializationException ex = new PluginInitializationException();
+ ex.reason = "plug-in `" + name + "' not defined";
+ throw ex;
+ }
+ }
+
+ //
+ // Load any remaining plug-ins that weren't specified in PluginLoadOrder.
+ //
+ while(!plugins.isEmpty())
+ {
+ java.util.Iterator<java.util.Map.Entry<String, String> > p = plugins.entrySet().iterator();
+ java.util.Map.Entry<String, String> entry = p.next();
+
+ String name = entry.getKey().substring(prefix.length());
+
+ int dotPos = name.lastIndexOf('.');
+ if(dotPos != -1)
+ {
+ String suffix = name.substring(dotPos + 1);
+ if(suffix.equals("cpp") || suffix.equals("clr"))
+ {
+ //
+ // Ignored
+ //
+ p.remove();
+ }
+ else if(suffix.equals("java"))
+ {
+ name = name.substring(0, dotPos);
+ loadPlugin(name, entry.getValue(), cmdArgs);
+ p.remove();
+
+ //
+ // Don't want to load this one if it's there!
+ //
+ plugins.remove("Ice.Plugin." + name);
+ }
+ else
+ {
+ //
+ // Name is just a regular name that happens to contain a dot
+ //
+ dotPos = -1;
+ }
+ }
+
+ if(dotPos == -1)
+ {
+ //
+ // Is there a .java entry?
+ //
+ String value = entry.getValue();
+ p.remove();
+
+ String javaValue = plugins.remove("Ice.Plugin." + name + ".java");
+ if(javaValue != null)
+ {
+ value = javaValue;
+ }
+
+ loadPlugin(name, value, cmdArgs);
+ }
+ }
+ }
+
+ private void
+ loadPlugin(String name, String pluginSpec, StringSeqHolder cmdArgs)
+ {
+ assert(_communicator != null);
+
+ //
+ // We support the following formats:
+ //
+ // <class-name> [args]
+ // <jar-file>:<class-name> [args]
+ // <class-dir>:<class-name> [args]
+ // "<path with spaces>":<class-name> [args]
+ // "<path with spaces>:<class-name>" [args]
+ //
+
+ String[] args;
+ try
+ {
+ args = IceUtilInternal.Options.split(pluginSpec);
+ }
+ catch(IceUtilInternal.Options.BadQuote ex)
+ {
+ throw new PluginInitializationException("invalid arguments for plug-in `" + name + "':\n" +
+ ex.getMessage());
+ }
+
+ assert(args.length > 0);
+
+ final String entryPoint = args[0];
+
+ final boolean isWindows = System.getProperty("os.name").startsWith("Windows");
+ boolean absolutePath = false;
+
+ //
+ // Find first ':' that isn't part of the file path.
+ //
+ int pos = entryPoint.indexOf(':');
+ if(isWindows)
+ {
+ final String driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if(pos == 1 && entryPoint.length() > 2 && driveLetters.indexOf(entryPoint.charAt(0)) != -1 &&
+ (entryPoint.charAt(2) == '\\' || entryPoint.charAt(2) == '/'))
+ {
+ absolutePath = true;
+ pos = entryPoint.indexOf(':', pos + 1);
+ }
+ if(!absolutePath)
+ {
+ absolutePath = entryPoint.startsWith("\\\\");
+ }
+ }
+ else
+ {
+ absolutePath = entryPoint.startsWith("/");
+ }
+
+ if((pos == -1 && absolutePath) || (pos != -1 && entryPoint.length() <= pos + 1))
+ {
+ //
+ // Class name is missing.
+ //
+ throw new PluginInitializationException("invalid entry point for plug-in `" + name + "':\n" + entryPoint);
+ }
+
+ //
+ // Extract the JAR file or subdirectory, if any.
+ //
+ String classDir = null; // Path name of JAR file or subdirectory.
+ String className;
+
+ if(pos == -1)
+ {
+ className = entryPoint;
+ }
+ else
+ {
+ classDir = entryPoint.substring(0, pos).trim();
+ className = entryPoint.substring(pos + 1).trim();
+ }
+
+ //
+ // Shift the arguments.
+ //
+ String[] tmp = new String[args.length - 1];
+ System.arraycopy(args, 1, tmp, 0, args.length - 1);
+ args = tmp;
+
+ //
+ // Convert command-line options into properties. First we
+ // convert the options from the plug-in configuration, then
+ // we convert the options from the application command-line.
+ //
+ Properties properties = _communicator.getProperties();
+ args = properties.parseCommandLineOptions(name, args);
+ cmdArgs.value = properties.parseCommandLineOptions(name, cmdArgs.value);
+
+ //
+ // Instantiate the class.
+ //
+ PluginFactory pluginFactory = null;
+ try
+ {
+ Class<?> c = null;
+
+ //
+ // Use a class loader if the user specified a JAR file or class directory.
+ //
+ if(classDir != null)
+ {
+ try
+ {
+ if(!absolutePath)
+ {
+ classDir = new java.io.File(System.getProperty("user.dir") + java.io.File.separator +
+ classDir).getCanonicalPath();
+ }
+
+ if(!classDir.endsWith(java.io.File.separator) && !classDir.toLowerCase().endsWith(".jar"))
+ {
+ classDir += java.io.File.separator;
+ }
+ classDir = URLEncoder.encode(classDir, "UTF-8");
+
+ //
+ // Reuse an existing class loader if we have already loaded a plug-in with
+ // the same value for classDir, otherwise create a new one.
+ //
+ ClassLoader cl = null;
+
+ if(_classLoaders == null)
+ {
+ _classLoaders = new java.util.HashMap<String, ClassLoader>();
+ }
+ else
+ {
+ cl = _classLoaders.get(classDir);
+ }
+
+ if(cl == null)
+ {
+ final java.net.URL[] url = new java.net.URL[] { new java.net.URL("file", null, classDir) };
+
+ //
+ // Use the custom class loader (if any) as the parent.
+ //
+ if(_instance.initializationData().classLoader != null)
+ {
+ cl = new java.net.URLClassLoader(url, _instance.initializationData().classLoader);
+ }
+ else
+ {
+ cl = new java.net.URLClassLoader(url);
+ }
+
+ _classLoaders.put(classDir, cl);
+ }
+
+ c = cl.loadClass(className);
+ }
+ catch(java.net.MalformedURLException ex)
+ {
+ throw new PluginInitializationException("invalid entry point format `" + pluginSpec + "'", ex);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new PluginInitializationException("invalid path in entry point `" + pluginSpec + "'", ex);
+ }
+ catch(java.lang.ClassNotFoundException ex)
+ {
+ // Ignored
+ }
+ }
+ else
+ {
+ c = IceInternal.Util.getInstance(_communicator).findClass(className);
+ }
+
+ if(c == null)
+ {
+ throw new PluginInitializationException("class " + className + " not found");
+ }
+
+ java.lang.Object obj = c.newInstance();
+ try
+ {
+ pluginFactory = (PluginFactory)obj;
+ }
+ catch(ClassCastException ex)
+ {
+ throw new PluginInitializationException("class " + className + " does not implement Ice.PluginFactory",
+ ex);
+ }
+ }
+ catch(IllegalAccessException ex)
+ {
+ throw new PluginInitializationException("unable to access default constructor in class " + className, ex);
+ }
+ catch(InstantiationException ex)
+ {
+ throw new PluginInitializationException("unable to instantiate class " + className, ex);
+ }
+
+ //
+ // Invoke the factory.
+ //
+ Plugin plugin = null;
+ try
+ {
+ plugin = pluginFactory.create(_communicator, name, args);
+ }
+ catch(PluginInitializationException ex)
+ {
+ throw ex;
+ }
+ catch(Throwable ex)
+ {
+ throw new PluginInitializationException("exception in factory " + className, ex);
+ }
+
+ if(plugin == null)
+ {
+ throw new PluginInitializationException("failure in factory " + className);
+ }
+
+ PluginInfo info = new PluginInfo();
+ info.name = name;
+ info.plugin = plugin;
+ _plugins.add(info);
+ }
+
+ private Plugin
+ findPlugin(String name)
+ {
+ for(PluginInfo p : _plugins)
+ {
+ if(name.equals(p.name))
+ {
+ return p.plugin;
+ }
+ }
+ return null;
+ }
+
+ static class PluginInfo
+ {
+ String name;
+ Plugin plugin;
+ }
+
+ private Communicator _communicator;
+ private IceInternal.Instance _instance;
+ private java.util.List<PluginInfo> _plugins = new java.util.ArrayList<PluginInfo>();
+ private boolean _initialized;
+ private java.util.Map<String, ClassLoader> _classLoaders;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/PropertiesAdminUpdateCallback.java b/java-compat/src/Ice/src/main/java/Ice/PropertiesAdminUpdateCallback.java
new file mode 100644
index 00000000000..d07b0dab83a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/PropertiesAdminUpdateCallback.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface PropertiesAdminUpdateCallback
+{
+ void updated(java.util.Map<String, String> changes);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/PropertiesI.java b/java-compat/src/Ice/src/main/java/Ice/PropertiesI.java
new file mode 100644
index 00000000000..81cff7c62e5
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/PropertiesI.java
@@ -0,0 +1,764 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public final class PropertiesI implements Properties
+{
+ static class PropertyValue
+ {
+ public PropertyValue(PropertyValue v)
+ {
+ value = v.value;
+ used = v.used;
+ }
+
+ public PropertyValue(String v, boolean u)
+ {
+ value = v;
+ used = u;
+ }
+
+ public String value;
+ public boolean used;
+ }
+
+ @Override
+ public synchronized String
+ getProperty(String key)
+ {
+ PropertyValue pv = _properties.get(key);
+ if(pv != null)
+ {
+ pv.used = true;
+ return pv.value;
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ @Override
+ public synchronized String
+ getPropertyWithDefault(String key, String value)
+ {
+ PropertyValue pv = _properties.get(key);
+ if(pv != null)
+ {
+ pv.used = true;
+ return pv.value;
+ }
+ else
+ {
+ return value;
+ }
+ }
+
+ @Override
+ public int
+ getPropertyAsInt(String key)
+ {
+ return getPropertyAsIntWithDefault(key, 0);
+ }
+
+ @Override
+ public synchronized int
+ getPropertyAsIntWithDefault(String key, int value)
+ {
+ PropertyValue pv = _properties.get(key);
+ if(pv != null)
+ {
+ pv.used = true;
+
+ try
+ {
+ return Integer.parseInt(pv.value);
+ }
+ catch(NumberFormatException ex)
+ {
+ Ice.Util.getProcessLogger().warning("numeric property " + key +
+ " set to non-numeric value, defaulting to " + value);
+ }
+ }
+
+ return value;
+ }
+
+ @Override
+ public String[]
+ getPropertyAsList(String key)
+ {
+ return getPropertyAsListWithDefault(key, null);
+ }
+
+ @Override
+ public synchronized String[]
+ getPropertyAsListWithDefault(String key, String[] value)
+ {
+ if(value == null)
+ {
+ value = new String[0];
+ }
+
+ PropertyValue pv = _properties.get(key);
+ if(pv != null)
+ {
+ pv.used = true;
+
+ String[] result = IceUtilInternal.StringUtil.splitString(pv.value, ", \t\r\n");
+ if(result == null)
+ {
+ Ice.Util.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;
+ }
+ }
+
+ @Override
+ public synchronized java.util.Map<String, String>
+ getPropertiesForPrefix(String prefix)
+ {
+ java.util.HashMap<String, String> result = new java.util.HashMap<String, String>();
+ for(java.util.Map.Entry<String, PropertyValue> p : _properties.entrySet())
+ {
+ String key = p.getKey();
+ if(prefix.length() == 0 || key.startsWith(prefix))
+ {
+ PropertyValue pv = p.getValue();
+ pv.used = true;
+ result.put(key, pv.value);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public void
+ setProperty(String key, String value)
+ {
+ //
+ // Trim whitespace
+ //
+ if(key != null)
+ {
+ key = key.trim();
+ }
+
+ //
+ // Check if the property is legal.
+ //
+ Logger logger = Ice.Util.getProcessLogger();
+ if(key == null || key.length() == 0)
+ {
+ throw new Ice.InitializationException("Attempt to set property with empty key");
+ }
+
+ int dotPos = key.indexOf('.');
+ if(dotPos != -1)
+ {
+ String prefix = key.substring(0, dotPos);
+ for(int i = 0; IceInternal.PropertyNames.validProps[i] != null; ++i)
+ {
+ String pattern = IceInternal.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.
+ //
+ assert(dotPos != -1);
+ String propPrefix = pattern.substring(0, dotPos - 1);
+ boolean mismatchCase = false;
+ String otherKey = "";
+ if(!propPrefix.toUpperCase().equals(prefix.toUpperCase()))
+ {
+ continue;
+ }
+
+ boolean found = false;
+ for(int j = 0; IceInternal.PropertyNames.validProps[i][j] != null && !found; ++j)
+ {
+ pattern = IceInternal.PropertyNames.validProps[i][j].pattern();
+ java.util.regex.Pattern pComp = java.util.regex.Pattern.compile(pattern);
+ java.util.regex.Matcher m = pComp.matcher(key);
+ found = m.matches();
+
+ if(found && IceInternal.PropertyNames.validProps[i][j].deprecated())
+ {
+ logger.warning("deprecated property: " + key);
+ if(IceInternal.PropertyNames.validProps[i][j].deprecatedBy() != null)
+ {
+ key = IceInternal.PropertyNames.validProps[i][j].deprecatedBy();
+ }
+ }
+
+ if(!found)
+ {
+ pComp = java.util.regex.Pattern.compile(pattern.toUpperCase());
+ m = pComp.matcher(key.toUpperCase());
+ if(m.matches())
+ {
+ found = true;
+ mismatchCase = true;
+ otherKey = pattern.replaceAll("\\\\", "");
+ break;
+ }
+ }
+ }
+ if(!found)
+ {
+ logger.warning("unknown property: " + key);
+ }
+ else if(mismatchCase)
+ {
+ logger.warning("unknown property: `" + key + "'; did you mean `" + otherKey + "'");
+ }
+ }
+ }
+
+ synchronized(this)
+ {
+ //
+ // Set or clear the property.
+ //
+ if(value != null && value.length() > 0)
+ {
+ PropertyValue pv = _properties.get(key);
+ if(pv != null)
+ {
+ pv.value = value;
+ }
+ else
+ {
+ pv = new PropertyValue(value, false);
+ }
+ _properties.put(key, pv);
+ }
+ else
+ {
+ _properties.remove(key);
+ }
+ }
+ }
+
+ @Override
+ public synchronized String[]
+ getCommandLineOptions()
+ {
+ String[] result = new String[_properties.size()];
+ int i = 0;
+ for(java.util.Map.Entry<String, PropertyValue> p : _properties.entrySet())
+ {
+ result[i++] = "--" + p.getKey() + "=" + p.getValue().value;
+ }
+ assert(i == result.length);
+ return result;
+ }
+
+ @Override
+ public String[]
+ parseCommandLineOptions(String pfx, String[] options)
+ {
+ if(pfx.length() > 0 && pfx.charAt(pfx.length() - 1) != '.')
+ {
+ pfx += '.';
+ }
+ pfx = "--" + pfx;
+
+ java.util.ArrayList<String> result = new java.util.ArrayList<String>();
+ for(String opt : options)
+ {
+ if(opt.startsWith(pfx))
+ {
+ if(opt.indexOf('=') == -1)
+ {
+ opt += "=1";
+ }
+
+ parseLine(opt.substring(2));
+ }
+ else
+ {
+ result.add(opt);
+ }
+ }
+ return result.toArray(new String[0]);
+ }
+
+ @Override
+ public String[]
+ parseIceCommandLineOptions(String[] options)
+ {
+ String[] args = options;
+ for(int i = 0; IceInternal.PropertyNames.clPropNames[i] != null; ++i)
+ {
+ args = parseCommandLineOptions(IceInternal.PropertyNames.clPropNames[i], args);
+ }
+ return args;
+ }
+
+ @Override
+ public void
+ load(String file)
+ {
+ if(System.getProperty("os.name").startsWith("Windows") && file.startsWith("HKLM\\"))
+ {
+ String regQuery = "reg query " + file;
+ try
+ {
+ java.lang.Process process = Runtime.getRuntime().exec(regQuery);
+ process.waitFor();
+ if(process.exitValue() != 0)
+ {
+ InitializationException ie = new InitializationException();
+ ie.reason = "Could not read Windows registry key `" + file + "'";
+ throw ie;
+ }
+
+ java.io.InputStream is = process.getInputStream();
+ java.io.StringWriter sw = new java.io.StringWriter();
+ int c;
+ while((c = is.read()) != -1)
+ {
+ sw.write(c);
+ }
+ String[] result = sw.toString().split("\n");
+
+ for(String line : result)
+ {
+ int pos = line.indexOf("REG_SZ");
+ if(pos != -1)
+ {
+ setProperty(line.substring(0, pos).trim(), line.substring(pos + 6, line.length()).trim());
+ continue;
+ }
+
+ pos = line.indexOf("REG_EXPAND_SZ");
+ if(pos != -1)
+ {
+ String name = line.substring(0, pos).trim();
+ line = line.substring(pos + 13, line.length()).trim();
+ while(true)
+ {
+ int start = line.indexOf("%", 0);
+ int end = line.indexOf("%", start + 1);
+
+ //
+ // If there isn't more %var% break the loop
+ //
+ if(start == -1 || end == -1)
+ {
+ break;
+ }
+
+ String envKey = line.substring(start + 1, end);
+ String envValue = System.getenv(envKey);
+ if(envValue == null)
+ {
+ envValue = "";
+ }
+
+ envKey = "%" + envKey + "%";
+ do
+ {
+ line = line.replace(envKey , envValue);
+ }
+ while(line.indexOf(envKey) != -1);
+ }
+ setProperty(name, line);
+ continue;
+ }
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ throw ex;
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new InitializationException("Could not read Windows registry key `" + file + "'", ex);
+ }
+ }
+ else
+ {
+ java.io.PushbackInputStream is = null;
+ try
+ {
+ java.io.InputStream f = IceInternal.Util.openResource(getClass().getClassLoader(), file);
+ if(f == null)
+ {
+ FileException fe = new FileException();
+ fe.path = file;
+ throw fe;
+ }
+ //
+ // Skip UTF-8 BOM if present.
+ //
+ byte[] bom = new byte[3];
+ is = new java.io.PushbackInputStream(f, bom.length);
+ int read = is.read(bom, 0, bom.length);
+ if(read < 3 || bom[0] != (byte)0xEF || bom[1] != (byte)0xBB || bom[2] != (byte)0xBF)
+ {
+ if(read > 0)
+ {
+ is.unread(bom, 0, read);
+ }
+ }
+
+ java.io.InputStreamReader isr = new java.io.InputStreamReader(is, "UTF-8");
+ java.io.BufferedReader br = new java.io.BufferedReader(isr);
+ parse(br);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new FileException(0, file, ex);
+ }
+ finally
+ {
+ if(is != null)
+ {
+ try
+ {
+ is.close();
+ }
+ catch(Throwable ex)
+ {
+ // Ignore.
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public synchronized Properties
+ _clone()
+ {
+ return new PropertiesI(this);
+ }
+
+ public synchronized java.util.List<String>
+ getUnusedProperties()
+ {
+ java.util.List<String> unused = new java.util.ArrayList<String>();
+ for(java.util.Map.Entry<String, PropertyValue> p : _properties.entrySet())
+ {
+ PropertyValue pv = p.getValue();
+ if(!pv.used)
+ {
+ unused.add(p.getKey());
+ }
+ }
+ return unused;
+ }
+
+ PropertiesI(PropertiesI props)
+ {
+ //
+ // 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 java.util.HashMap<String, PropertyValue>(props._properties);
+ for(java.util.Map.Entry<String, PropertyValue> p : props._properties.entrySet())
+ {
+ _properties.put(p.getKey(), new PropertyValue(p.getValue()));
+ }
+ }
+
+ PropertiesI()
+ {
+ }
+
+ PropertiesI(StringSeqHolder args, Properties defaults)
+ {
+ if(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 java.util.HashMap<String, PropertyValue>(((PropertiesI)defaults)._properties);
+ for(java.util.Map.Entry<String, PropertyValue> p : (((PropertiesI)defaults)._properties).entrySet())
+ {
+ _properties.put(p.getKey(), new PropertyValue(p.getValue()));
+ }
+ }
+
+ boolean loadConfigFiles = false;
+
+ for(int i = 0; i < args.value.length; i++)
+ {
+ if(args.value[i].startsWith("--Ice.Config"))
+ {
+ String line = args.value[i];
+ if(line.indexOf('=') == -1)
+ {
+ line += "=1";
+ }
+ parseLine(line.substring(2));
+ loadConfigFiles = true;
+
+ String[] arr = new String[args.value.length - 1];
+ System.arraycopy(args.value, 0, arr, 0, i);
+ if(i < args.value.length - 1)
+ {
+ System.arraycopy(args.value, i + 1, arr, i, args.value.length - i - 1);
+ }
+ args.value = arr;
+ }
+ }
+
+ if(!loadConfigFiles)
+ {
+ //
+ // If Ice.Config is not set, load from ICE_CONFIG (if set)
+ //
+ loadConfigFiles = !_properties.containsKey("Ice.Config");
+ }
+
+ if(loadConfigFiles)
+ {
+ loadConfig();
+ }
+
+ args.value = parseIceCommandLineOptions(args.value);
+ }
+
+ private void
+ parse(java.io.BufferedReader in)
+ {
+ try
+ {
+ String line;
+ while((line = in.readLine()) != null)
+ {
+ parseLine(line);
+ }
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new SyscallException(ex);
+ }
+ }
+
+ private static final int ParseStateKey = 0;
+ private static final int ParseStateValue = 1;
+
+ private void
+ parseLine(String line)
+ {
+ String key = "";
+ String value = "";
+
+ int state = ParseStateKey;
+
+ String whitespace = "";
+ String escapedspace = "";
+ boolean finished = false;
+ for(int i = 0; i < line.length(); ++i)
+ {
+ char 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 '#':
+ 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))
+ {
+ Ice.Util.getProcessLogger().warning("invalid config file entry: \"" + line + "\"");
+ return;
+ }
+ else if(key.length() == 0)
+ {
+ return;
+ }
+
+ setProperty(key, value);
+ }
+
+ private void
+ loadConfig()
+ {
+ String value = getProperty("Ice.Config");
+
+ if(value.length() == 0 || value.equals("1"))
+ {
+ try
+ {
+ value = System.getenv("ICE_CONFIG");
+ if(value == null)
+ {
+ value = "";
+ }
+ }
+ catch(java.lang.SecurityException ex)
+ {
+ value = "";
+ }
+ }
+
+ if(value.length() > 0)
+ {
+ for(String file : value.split(","))
+ {
+ load(file.trim());
+ }
+
+ _properties.put("Ice.Config", new PropertyValue(value, true));
+ }
+ }
+
+ private java.util.HashMap<String, PropertyValue> _properties = new java.util.HashMap<String, PropertyValue>();
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ProxyIdentityFacetKey.java b/java-compat/src/Ice/src/main/java/Ice/ProxyIdentityFacetKey.java
new file mode 100644
index 00000000000..21ff8089ba2
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ProxyIdentityFacetKey.java
@@ -0,0 +1,97 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * This class wraps a proxy to allow it to be used the key for a hashed collection.
+ * The <code>hashCode</code> and <code>equals</code> methods are based on the object identity and
+ * the facet of the proxy.
+ *
+ * @see Util#proxyIdentityAndFacetCompare
+ * @see Util#proxyIdentityCompare
+ * @see ProxyIdentityKey
+ *
+ **/
+public class ProxyIdentityFacetKey
+{
+ /**
+ * Initializes this class with the passed proxy.
+ *
+ * @param proxy The proxy for this instance.
+ **/
+ public
+ ProxyIdentityFacetKey(Ice.ObjectPrx proxy)
+ {
+ _proxy = proxy;
+
+ //
+ // Cache the identity and facet, and compute the hash code.
+ //
+ _identity = proxy.ice_getIdentity();
+ _facet = proxy.ice_getFacet();
+ int h = 5381;
+ h = IceInternal.HashUtil.hashAdd(h, _identity);
+ h = IceInternal.HashUtil.hashAdd(h, _facet);
+ _hashCode = h;
+ }
+
+ /**
+ * Computes a hash value based on the object identity and the facet of the proxy.
+ *
+ * @return The hash value.
+ **/
+ @Override
+ public int
+ hashCode()
+ {
+ return _hashCode;
+ }
+
+ /**
+ * Compares this proxy with the passed object for equality.
+ *
+ * @param obj The object to compare this proxy with.
+ * @return <code>true</code> if the passed object is a proxy with the same object
+ * identity and facet as this proxy; <code>false</code>, otherwise.
+ **/
+ @Override
+ public boolean
+ equals(java.lang.Object obj)
+ {
+ if(this == obj)
+ {
+ return true;
+ }
+
+ if(obj instanceof ProxyIdentityFacetKey)
+ {
+ ProxyIdentityFacetKey other = (ProxyIdentityFacetKey)obj;
+ return (_hashCode == other._hashCode) && _identity.equals(other._identity) && _facet.equals(other._facet);
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the proxy stored by this class.
+ *
+ * @return The proxy stored by this class.
+ **/
+ public Ice.ObjectPrx
+ getProxy()
+ {
+ return _proxy;
+ }
+
+ final private Ice.ObjectPrx _proxy;
+ final private Ice.Identity _identity;
+ final private String _facet;
+ final private int _hashCode;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ProxyIdentityKey.java b/java-compat/src/Ice/src/main/java/Ice/ProxyIdentityKey.java
new file mode 100644
index 00000000000..b8c85cf324b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ProxyIdentityKey.java
@@ -0,0 +1,89 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * This class wraps a proxy to allow it to be used the key for a hashed collection.
+ * The <code>hashCode</code> and <code>equals</code> methods are based on the object identity
+ * of the proxy.
+ *
+ * @see Util#proxyIdentityCompare
+ * @see Util#proxyIdentityAndFacetCompare
+ * @see ProxyIdentityFacetKey
+ *
+ **/
+public class ProxyIdentityKey
+{
+ /**
+ * Initializes this class with the passed proxy.
+ *
+ * @param proxy The proxy for this instance.
+ **/
+ public
+ ProxyIdentityKey(Ice.ObjectPrx proxy)
+ {
+ _proxy = proxy;
+
+ //
+ // Cache the identity and its hash code.
+ //
+ _identity = proxy.ice_getIdentity();
+ int h = 5381;
+ h = IceInternal.HashUtil.hashAdd(h, _identity);
+ _hashCode = h;
+ }
+
+ /**
+ * Computes a hash value based on the object identity of the proxy.
+ *
+ * @return The hash value.
+ **/
+ @Override
+ public int
+ hashCode()
+ {
+ return _hashCode;
+ }
+
+ /**
+ * Compares this proxy with the passed object for equality.
+ *
+ * @param obj The object to compare this proxy with.
+ * @return <code>true</code> if the passed object is a proxy with the same object
+ * identity; <code>false</code>, otherwise.
+ **/
+ @Override
+ public boolean
+ equals(java.lang.Object obj)
+ {
+ if(this == obj)
+ {
+ return true;
+ }
+
+ if(obj instanceof ProxyIdentityKey)
+ {
+ ProxyIdentityKey other = (ProxyIdentityKey)obj;
+ return (_hashCode == other._hashCode) && _identity.equals(other._identity);
+ }
+
+ return false;
+ }
+
+ public Ice.ObjectPrx
+ getProxy()
+ {
+ return _proxy;
+ }
+
+ final private Ice.ObjectPrx _proxy;
+ final private Ice.Identity _identity;
+ final private int _hashCode;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ReadValueCallback.java b/java-compat/src/Ice/src/main/java/Ice/ReadValueCallback.java
new file mode 100644
index 00000000000..9a3132a9822
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ReadValueCallback.java
@@ -0,0 +1,27 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Callback class to inform an application when an instance of a Slice class has been
+ * unmarshaled from an input stream.
+ *
+ * @see InputStream#readValue
+ **/
+public interface ReadValueCallback
+{
+ /**
+ * The Ice run time calls this method when it has fully unmarshaled the state
+ * of a Slice class instance.
+ *
+ * @param obj The unmarshaled Slice class instance.
+ **/
+ void valueReady(Ice.Object obj);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Request.java b/java-compat/src/Ice/src/main/java/Ice/Request.java
new file mode 100644
index 00000000000..1be2ec37fbf
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Request.java
@@ -0,0 +1,23 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Interface for incoming requests.
+ **/
+public interface Request
+{
+ /**
+ * Returns the {@link Current} object for this the request.
+ *
+ * @return The {@link Current} object for this request.
+ **/
+ Current getCurrent();
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ShortHolder.java b/java-compat/src/Ice/src/main/java/Ice/ShortHolder.java
new file mode 100644
index 00000000000..f960536349d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ShortHolder.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for shorts that are out- or inout-parameters.
+ **/
+public final class ShortHolder extends Holder<Short>
+{
+ /**
+ * Instantiates the class with the value zero.
+ **/
+ public
+ ShortHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed value.
+ *
+ * The <code>short</code> value for this holder.
+ **/
+ public
+ ShortHolder(short value)
+ {
+ super(value);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ShortOptional.java b/java-compat/src/Ice/src/main/java/Ice/ShortOptional.java
new file mode 100644
index 00000000000..60b9228f1f0
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ShortOptional.java
@@ -0,0 +1,106 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Manages an optional short parameter.
+ **/
+public class ShortOptional
+{
+ /**
+ * The value defaults to unset.
+ **/
+ public ShortOptional()
+ {
+ _isSet = false;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The initial value.
+ **/
+ public ShortOptional(short v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * Sets the value to a shallow copy of the given optional.
+ *
+ * @param opt The source value.
+ **/
+ public ShortOptional(ShortOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Obtains the current value.
+ *
+ * @return The current value.
+ * @throws IllegalStateException If the value is not set.
+ **/
+ public short get()
+ {
+ if(!_isSet)
+ {
+ throw new IllegalStateException("no value is set");
+ }
+ return _value;
+ }
+
+ /**
+ * Sets the value to the given argument.
+ *
+ * @param v The new value.
+ **/
+ public void set(short v)
+ {
+ _value = v;
+ _isSet = true;
+ }
+
+ /**
+ * If the given argument is set, this optional is set to a shallow copy of the argument,
+ * otherwise this optional is unset.
+ *
+ * @param opt The source value.
+ **/
+ public void set(ShortOptional opt)
+ {
+ _value = opt._value;
+ _isSet = opt._isSet;
+ }
+
+ /**
+ * Determines whether the value is set.
+ *
+ * @return True if the value is set, false otherwise.
+ **/
+ public boolean isSet()
+ {
+ return _isSet;
+ }
+
+ /**
+ * Unsets this value.
+ **/
+ public void clear()
+ {
+ _isSet = false;
+ _value = 0;
+ }
+
+ private short _value;
+ private boolean _isSet;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/SignalPolicy.java b/java-compat/src/Ice/src/main/java/Ice/SignalPolicy.java
new file mode 100644
index 00000000000..b1bb328d199
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/SignalPolicy.java
@@ -0,0 +1,31 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * The signal policy for Ice.Application signal handling.
+ *
+ * @see Ice.Application
+ **/
+public enum SignalPolicy
+{
+ /**
+ * If a signal is received, {@link Ice.Application} reacts to the signal
+ * by calling {@link Communicator#destroy} or {@link Communicator#shutdown},
+ * or by calling a custom shutdown hook installed by the application.
+ **/
+ HandleSignals,
+
+ /**
+ * Any signal that is received is not intercepted and takes the default
+ * action.
+ **/
+ NoSignalHandling
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/SliceInfo.java b/java-compat/src/Ice/src/main/java/Ice/SliceInfo.java
new file mode 100644
index 00000000000..8297a4d447c
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/SliceInfo.java
@@ -0,0 +1,46 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * SliceInfo encapsulates the details of a slice for an unknown class or exception type.
+ **/
+public class SliceInfo
+{
+ /**
+ * The Slice type ID for this slice.
+ **/
+ public String typeId;
+
+ /**
+ * The Slice compact type ID for this slice.
+ **/
+ public int compactId;
+
+ /**
+ * The encoded bytes for this slice, including the leading size integer.
+ **/
+ public byte[] bytes;
+
+ /**
+ * The class instances referenced by this slice.
+ **/
+ public Ice.Object[] instances;
+
+ /**
+ * Whether or not the slice contains optional members.
+ **/
+ public boolean hasOptionalMembers;
+
+ /**
+ * Whether or not this is the last slice.
+ **/
+ public boolean isLastSlice;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/SlicedData.java b/java-compat/src/Ice/src/main/java/Ice/SlicedData.java
new file mode 100644
index 00000000000..b747689687a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/SlicedData.java
@@ -0,0 +1,26 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * SlicedData holds the slices of unknown class or exception types.
+ **/
+public class SlicedData
+{
+ public SlicedData(SliceInfo[] slices)
+ {
+ this.slices = slices;
+ }
+
+ /**
+ * The details of each slice, in order of most-derived to least-derived.
+ **/
+ public SliceInfo[] slices;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/StringHolder.java b/java-compat/src/Ice/src/main/java/Ice/StringHolder.java
new file mode 100644
index 00000000000..46095138097
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/StringHolder.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Holder class for strings that are out- or inout-parameters.
+ **/
+public final class StringHolder extends Holder<String>
+{
+ /**
+ * Instantiates the class with a <code>null</code> string.
+ **/
+ public
+ StringHolder()
+ {
+ }
+
+ /**
+ * Instantiates the class with the passed value.
+ *
+ * @param value The <code>String</code> value stored by this holder.
+ **/
+ public
+ StringHolder(String value)
+ {
+ super(value);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/SysLoggerI.java b/java-compat/src/Ice/src/main/java/Ice/SysLoggerI.java
new file mode 100644
index 00000000000..2938990276a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/SysLoggerI.java
@@ -0,0 +1,244 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.io.IOException;
+
+public final class SysLoggerI implements Logger
+{
+ public
+ SysLoggerI(String prefix, String facilityString)
+ {
+ int facility;
+ if(facilityString.equals("LOG_KERN"))
+ {
+ facility = LOG_KERN;
+ }
+ else if(facilityString.equals("LOG_USER"))
+ {
+ facility = LOG_USER;
+ }
+ else if(facilityString.equals("LOG_MAIL"))
+ {
+ facility = LOG_MAIL;
+ }
+ else if(facilityString.equals("LOG_DAEMON"))
+ {
+ facility = LOG_DAEMON;
+ }
+ else if(facilityString.equals("LOG_AUTH"))
+ {
+ facility = LOG_AUTH;
+ }
+ else if(facilityString.equals("LOG_SYSLOG"))
+ {
+ facility = LOG_SYSLOG;
+ }
+ else if(facilityString.equals("LOG_LPR"))
+ {
+ facility = LOG_LPR;
+ }
+ else if(facilityString.equals("LOG_NEWS"))
+ {
+ facility = LOG_NEWS;
+ }
+ else if(facilityString.equals("LOG_UUCP"))
+ {
+ facility = LOG_UUCP;
+ }
+ else if(facilityString.equals("LOG_CRON"))
+ {
+ facility = LOG_CRON;
+ }
+ else if(facilityString.equals("LOG_AUTHPRIV"))
+ {
+ facility = LOG_AUTHPRIV;
+ }
+ else if(facilityString.equals("LOG_FTP"))
+ {
+ facility = LOG_FTP;
+ }
+ else if(facilityString.equals("LOG_LOCAL0"))
+ {
+ facility = LOG_LOCAL0;
+ }
+ else if(facilityString.equals("LOG_LOCAL1"))
+ {
+ facility = LOG_LOCAL1;
+ }
+ else if(facilityString.equals("LOG_LOCAL2"))
+ {
+ facility = LOG_LOCAL2;
+ }
+ else if(facilityString.equals("LOG_LOCAL3"))
+ {
+ facility = LOG_LOCAL3;
+ }
+ else if(facilityString.equals("LOG_LOCAL4"))
+ {
+ facility = LOG_LOCAL4;
+ }
+ else if(facilityString.equals("LOG_LOCAL5"))
+ {
+ facility = LOG_LOCAL5;
+ }
+ else if(facilityString.equals("LOG_LOCAL6"))
+ {
+ facility = LOG_LOCAL6;
+ }
+ else if(facilityString.equals("LOG_LOCAL7"))
+ {
+ facility = LOG_LOCAL7;
+ }
+ else
+ {
+ throw new Ice.InitializationException("Invalid value for Ice.SyslogFacility: " + facilityString);
+ }
+ initialize(prefix, facility);
+ }
+
+ private
+ SysLoggerI(String prefix, int facility)
+ {
+ initialize(prefix, facility);
+ }
+
+ private void
+ initialize(String prefix, int facility)
+ {
+ _prefix = prefix;
+ _facility = facility;
+
+ //
+ // Open a datagram socket to communicate with the localhost
+ // syslog daemon.
+ //
+ try
+ {
+ _host = IceInternal.Network.getLocalAddress(IceInternal.Network.EnableBoth);
+ _socket = new DatagramSocket();
+ _socket.connect(_host, _port);
+ }
+ catch(IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ @Override
+ public void
+ print(String message)
+ {
+ log(LOG_INFO, message);
+ }
+
+ @Override
+ public void
+ trace(String category, String message)
+ {
+ log(LOG_INFO, category + ": " + message);
+ }
+
+ @Override
+ public void
+ warning(String message)
+ {
+ log(LOG_WARNING, message);
+ }
+
+ @Override
+ public void
+ error(String message)
+ {
+ log(LOG_ERR, message);
+ }
+
+
+ @Override
+ public String
+ getPrefix()
+ {
+ return _prefix;
+ }
+
+ @Override
+ public Logger
+ cloneWithPrefix(String prefix)
+ {
+ return new SysLoggerI(prefix, _facility);
+ }
+
+ private void
+ log(int severity, String message)
+ {
+ try
+ {
+ //
+ // Create a syslog message as defined by the RFC 3164:
+ // <PRI>HEADER MSG. PRI is the priority and is calculated
+ // from the facility and the severity. We don't specify
+ // the HEADER. MSG contains the identifier followed by a
+ // colon character and the message.
+ //
+
+ int priority = (_facility << 3) | severity;
+
+ String msg = '<' + Integer.toString(priority) + '>' + _prefix + ": " + message;
+
+ byte buf[] = msg.getBytes();
+ DatagramPacket p = new DatagramPacket(buf, buf.length, _host, _port);
+ _socket.send(p);
+ }
+ catch(IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ private String _prefix;
+ private int _facility;
+ private DatagramSocket _socket;
+ private InetAddress _host;
+ private static int _port = 514;
+
+ //
+ // Syslog facilities (as defined in syslog.h)
+ //
+ private final static int LOG_KERN = 0;
+ private final static int LOG_USER = 1;
+ private final static int LOG_MAIL = 2;
+ private final static int LOG_DAEMON = 3;
+ private final static int LOG_AUTH = 4;
+ private final static int LOG_SYSLOG = 5;
+ private final static int LOG_LPR = 6;
+ private final static int LOG_NEWS = 7;
+ private final static int LOG_UUCP = 8;
+ private final static int LOG_CRON = 9;
+ private final static int LOG_AUTHPRIV = 10;
+ private final static int LOG_FTP = 11;
+ private final static int LOG_LOCAL0 = 16;
+ private final static int LOG_LOCAL1 = 17;
+ private final static int LOG_LOCAL2 = 18;
+ private final static int LOG_LOCAL3 = 19;
+ private final static int LOG_LOCAL4 = 20;
+ private final static int LOG_LOCAL5 = 21;
+ private final static int LOG_LOCAL6 = 22;
+ private final static int LOG_LOCAL7 = 23;
+
+ //
+ // Syslog priorities (as defined in syslog.h)
+ //
+ private final static int LOG_ERR = 3;
+ private final static int LOG_WARNING = 4;
+ private final static int LOG_INFO = 6;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/SystemException.java b/java-compat/src/Ice/src/main/java/Ice/SystemException.java
new file mode 100644
index 00000000000..c6f063adfb8
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/SystemException.java
@@ -0,0 +1,25 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class for all Ice system exceptions.
+ **/
+public abstract class SystemException extends Exception
+{
+ public SystemException()
+ {
+ }
+
+ public SystemException(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ThreadHookPlugin.java b/java-compat/src/Ice/src/main/java/Ice/ThreadHookPlugin.java
new file mode 100644
index 00000000000..8ce5943d638
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ThreadHookPlugin.java
@@ -0,0 +1,64 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Class to support thread notification hooks. Applications using thread
+ * notifications hooks instantiate a <code>ThreadHookPlugin</code> with
+ * a thread notification hook and return the instance from their
+ * {@link PluginFactory} implementation.
+ *
+ * @see PluginFactory
+ * @see Plugin
+ **/
+public class ThreadHookPlugin implements Ice.Plugin
+{
+ /**
+ * Installs a thread notification hook for a communicator.
+ *
+ * @param communicator The communicator using the thread notification hook.
+ * @param threadHook The thread notification hook for the communicator.
+ **/
+ public
+ ThreadHookPlugin(Communicator communicator, ThreadNotification threadHook)
+ {
+ if(communicator == null)
+ {
+ PluginInitializationException ex = new PluginInitializationException();
+ ex.reason = "Communicator cannot be null";
+ throw ex;
+ }
+
+ IceInternal.Instance instance = IceInternal.Util.getInstance(communicator);
+ instance.setThreadHook(threadHook);
+ }
+
+ /**
+ * Called by the Ice run time during communicator initialization. The derived class
+ * can override this method to perform any initialization that might be required
+ * by a custom thread notification hook.
+ **/
+ @Override
+ public void
+ initialize()
+ {
+ }
+
+ /**
+ * Called by the Ice run time when the communicator is destroyed. The derived class
+ * can override this method to perform any finalization that might be required
+ * by a custom thread notification hook.
+ **/
+ @Override
+ public void
+ destroy()
+ {
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ThreadNotification.java b/java-compat/src/Ice/src/main/java/Ice/ThreadNotification.java
new file mode 100644
index 00000000000..3fae6f8930e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ThreadNotification.java
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Interface for thread notification hooks. Applications can derive
+ * a class that implements the <code>start</code> and <code>stop</code>
+ * methods to intercept creation and destruction of threads created
+ * by the Ice run time.
+ *
+ * @see InitializationData
+ **/
+public interface ThreadNotification
+{
+ /**
+ * The Ice run time calls <code>start</code> for each new
+ * thread it creates. The call is made by the newly-started thread.
+ **/
+ void start();
+
+ /**
+ * The Ice run time calls <code>stop</code> before it destroys
+ * a thread. The call is made by thread that is about to be
+ * destroyed.
+ **/
+ void stop();
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TieBase.java b/java-compat/src/Ice/src/main/java/Ice/TieBase.java
new file mode 100644
index 00000000000..0cbd8ff7c4e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TieBase.java
@@ -0,0 +1,30 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Interface for servants using the tie mapping.
+ **/
+public interface TieBase
+{
+ /**
+ * Returns the delegate for this tie.
+ *
+ * @return The delegate.
+ **/
+ java.lang.Object ice_delegate();
+
+ /**
+ * Sets the delegate for this tie.
+ *
+ * @param delegate The delegate.
+ **/
+ void ice_delegate(java.lang.Object delegate);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallback.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallback.java
new file mode 100644
index 00000000000..bedbe2970c6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallback.java
@@ -0,0 +1,30 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base interface for generated twoway operation callback.
+ **/
+public interface TwowayCallback
+{
+ /**
+ * Called when the invocation raises an Ice run-time exception.
+ *
+ * @param __ex The Ice run-time exception raised by the operation.
+ **/
+ public void exception(LocalException __ex);
+
+ /**
+ * Called when the invocation raises an Ice system exception.
+ *
+ * @param __ex The Ice system exception raised by the operation.
+ **/
+ public void exception(SystemException __ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackArg1.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackArg1.java
new file mode 100644
index 00000000000..5149a2b4116
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackArg1.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackArg1<T> extends TwowayCallback
+{
+ /**
+ * Called when the invocation response is received.
+ *
+ * @param arg The operation return value.
+ **/
+ void response(T arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackArg1UE.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackArg1UE.java
new file mode 100644
index 00000000000..f1a8e57995d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackArg1UE.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackArg1UE<T> extends TwowayCallbackArg1<T>
+{
+ /**
+ * Called when the invocation raises an user exception.
+ *
+ * @param ex The user exception raised by the operation.
+ **/
+ void exception(Ice.UserException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackBool.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackBool.java
new file mode 100644
index 00000000000..bcbdb51971f
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackBool.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackBool extends TwowayCallback
+{
+ /**
+ * Called when the invocation response is received.
+ *
+ * @param arg The operation return value.
+ **/
+ void response(boolean arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackBoolUE.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackBoolUE.java
new file mode 100644
index 00000000000..5a6492e4b63
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackBoolUE.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackBoolUE extends TwowayCallbackBool
+{
+ void exception(Ice.UserException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackByte.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackByte.java
new file mode 100644
index 00000000000..2c66deb95ab
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackByte.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackByte extends TwowayCallback
+{
+ /**
+ * Called when the invocation response is received.
+ *
+ * @param arg The operation return value.
+ **/
+ void response(byte arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackByteUE.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackByteUE.java
new file mode 100644
index 00000000000..cccbd04fe42
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackByteUE.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackByteUE extends TwowayCallbackByte
+{
+ void exception(Ice.UserException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackDouble.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackDouble.java
new file mode 100644
index 00000000000..042b35e2bc1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackDouble.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackDouble extends TwowayCallback
+{
+ /**
+ * Called when the invocation response is received.
+ *
+ * @param arg The operation return value.
+ **/
+ void response(double arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackDoubleUE.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackDoubleUE.java
new file mode 100644
index 00000000000..3190a0b0d9b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackDoubleUE.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackDoubleUE extends TwowayCallbackDouble
+{
+ void exception(Ice.UserException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackFloat.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackFloat.java
new file mode 100644
index 00000000000..37818f8e8c1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackFloat.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackFloat extends TwowayCallback
+{
+ /**
+ * Called when the invocation response is received.
+ *
+ * @param arg The operation return value.
+ **/
+ void response(float arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackFloatUE.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackFloatUE.java
new file mode 100644
index 00000000000..26a14b83fe7
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackFloatUE.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackFloatUE extends TwowayCallbackFloat
+{
+ void exception(Ice.UserException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackInt.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackInt.java
new file mode 100644
index 00000000000..3319fae792e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackInt.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackInt extends TwowayCallback
+{
+ /**
+ * Called when the invocation response is received.
+ *
+ * @param arg The operation return value.
+ **/
+ void response(int arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackIntUE.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackIntUE.java
new file mode 100644
index 00000000000..7627bbb9ad6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackIntUE.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackIntUE extends TwowayCallbackInt
+{
+ void exception(Ice.UserException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackLong.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackLong.java
new file mode 100644
index 00000000000..ea49ed2a7b4
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackLong.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackLong extends TwowayCallback
+{
+ /**
+ * Called when the invocation response is received.
+ *
+ * @param arg The operation return value.
+ **/
+ void response(long arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackLongUE.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackLongUE.java
new file mode 100644
index 00000000000..47ca9c303f3
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackLongUE.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackLongUE extends TwowayCallbackLong
+{
+ void exception(Ice.UserException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackShort.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackShort.java
new file mode 100644
index 00000000000..8f613175c92
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackShort.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackShort extends TwowayCallback
+{
+ /**
+ * Called when the invocation response is received.
+ *
+ * @param arg The operation return value.
+ **/
+ void response(short arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackShortUE.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackShortUE.java
new file mode 100644
index 00000000000..142993b319a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackShortUE.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackShortUE extends TwowayCallbackShort
+{
+ void exception(Ice.UserException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackUE.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackUE.java
new file mode 100644
index 00000000000..ecd25e75edb
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackUE.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackUE extends TwowayCallback
+{
+ public void exception(UserException __ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackVoidUE.java b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackVoidUE.java
new file mode 100644
index 00000000000..24813fb7420
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/TwowayCallbackVoidUE.java
@@ -0,0 +1,25 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public interface TwowayCallbackVoidUE extends TwowayCallback
+{
+ /**
+ * Called when the invocation response is received.
+ **/
+ void response();
+
+ /**
+ * Called when the invocation raises an user exception.
+ *
+ * @param ex The user exception raised by the operation.
+ **/
+ void exception(Ice.UserException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/UnknownSlicedValue.java b/java-compat/src/Ice/src/main/java/Ice/UnknownSlicedValue.java
new file mode 100644
index 00000000000..98d3d45260c
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/UnknownSlicedValue.java
@@ -0,0 +1,54 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Unknown sliced value holds an instance of an unknown Slice class type.
+ **/
+public final class UnknownSlicedValue extends ObjectImpl
+{
+ /**
+ * Represents an instance of a Slice class type having the given Slice type.
+ *
+ * @param unknownTypeId The Slice type ID of the unknown object.
+ **/
+ public
+ UnknownSlicedValue(String unknownTypeId)
+ {
+ _unknownTypeId = unknownTypeId;
+ }
+
+ /**
+ * Determine the Slice type ID associated with this object.
+ *
+ * @return The type ID.
+ **/
+ public String getUnknownTypeId()
+ {
+ return _unknownTypeId;
+ }
+
+ @Override
+ public void __write(OutputStream __os)
+ {
+ __os.startValue(_slicedData);
+ __os.endValue();
+ }
+
+ @Override
+ public void __read(InputStream __is)
+ {
+ __is.startValue();
+ _slicedData = __is.endValue(true);
+ }
+
+ private final String _unknownTypeId;
+ private SlicedData _slicedData;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/UserException.java b/java-compat/src/Ice/src/main/java/Ice/UserException.java
new file mode 100644
index 00000000000..1d78d42c722
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/UserException.java
@@ -0,0 +1,116 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Base class for Slice user exceptions.
+ **/
+public abstract class UserException extends java.lang.Exception implements Cloneable
+{
+ public UserException()
+ {
+ }
+
+ public UserException(Throwable cause)
+ {
+ super(cause);
+ }
+
+ /**
+ * Creates a copy of this exception.
+ *
+ * @return The copy of this exception.
+ **/
+ @Override
+ public UserException clone()
+ {
+ UserException c = null;
+
+ try
+ {
+ c = (UserException)super.clone();
+ }
+ catch(CloneNotSupportedException ex)
+ {
+ assert false;
+ }
+ return c;
+ }
+
+ /**
+ * Returns the name of this exception.
+ *
+ * @return The name of this exception.
+ *
+ * @deprecated ice_name() is deprecated, use ice_id() instead.
+ **/
+ @Deprecated
+ public String
+ ice_name()
+ {
+ return ice_id().substring(2);
+ }
+
+ /**
+ * Returns the type id of this exception.
+ *
+ * @return The type id of this exception.
+ **/
+ public abstract String
+ ice_id();
+
+ /**
+ * Returns a string representation of this exception.
+ *
+ * @return A string representation of this exception.
+ **/
+ @Override
+ public String
+ toString()
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ IceUtilInternal.OutputBase out = new IceUtilInternal.OutputBase(pw);
+ out.setUseTab(false);
+ out.print(getClass().getName());
+ out.inc();
+ IceInternal.ValueWriter.write(this, out);
+ pw.flush();
+ return sw.toString();
+ }
+
+ public void
+ __write(OutputStream os)
+ {
+ os.startException(null);
+ __writeImpl(os);
+ os.endException();
+ }
+
+ public void
+ __read(InputStream is)
+ {
+ is.startException();
+ __readImpl(is);
+ is.endException(false);
+ }
+
+ public boolean
+ __usesClasses()
+ {
+ return false;
+ }
+
+ protected abstract void
+ __writeImpl(OutputStream os);
+
+ protected abstract void
+ __readImpl(InputStream is);
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/UserExceptionFactory.java b/java-compat/src/Ice/src/main/java/Ice/UserExceptionFactory.java
new file mode 100644
index 00000000000..9e899e813ec
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/UserExceptionFactory.java
@@ -0,0 +1,26 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Instantiates user exceptions.
+ *
+ * @see InputStream#throwException
+ **/
+public interface UserExceptionFactory
+{
+ /**
+ * Instantiate a user exception with the given Slice type id (such as <code>::Module::MyException</code>)
+ * and throw it. If the implementation does not throw an exception, the Ice run time will fall back
+ * to using its default behavior for instantiating the user exception.
+ **/
+ void createAndThrow(String typeId)
+ throws UserException;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/Util.java b/java-compat/src/Ice/src/main/java/Ice/Util.java
new file mode 100644
index 00000000000..565dab3588a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/Util.java
@@ -0,0 +1,715 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Utility methods for the Ice run time.
+ **/
+public final class Util
+{
+ /**
+ * Creates a new empty property set.
+ *
+ * @return A new empty property set.
+ **/
+ public static Properties
+ createProperties()
+ {
+ return new PropertiesI();
+ }
+
+ /**
+ * Creates a property set initialized from an argument vector.
+ *
+ * @param args A command-line argument vector, possibly containing
+ * options to set properties. If the command-line options include
+ * a <code>--Ice.Config</code> option, the corresponding configuration
+ * files are parsed. If the same property is set in a configuration
+ * file and in the argument vector, the argument vector takes precedence.
+ * <p>
+ * This method modifies the argument vector by removing any Ice-related options.
+ *
+ * @return A property set initialized with the property settings
+ * that were removed from <code>args</code>.
+ **/
+ public static Properties
+ createProperties(StringSeqHolder args)
+ {
+ return new PropertiesI(args, null);
+ }
+
+ /**
+ * Creates a property set initialized from an argument vector.
+ *
+ * @param args A command-line argument vector, possibly containing
+ * options to set properties. If the command-line options include
+ * a <code>--Ice.Config</code> option, the corresponding configuration
+ * files are parsed. If the same property is set in a configuration
+ * file and in the argument vector, the argument vector takes precedence.
+ * <p>
+ * This method modifies the argument vector by removing any Ice-related options.
+ * @param defaults Default values for the property set. Settings in configuration
+ * files and <code>args</code> override these defaults.
+ *
+ * @return An initalized property set.
+ **/
+ public static Properties
+ createProperties(StringSeqHolder args, Properties defaults)
+ {
+ return new PropertiesI(args, defaults);
+ }
+
+ /**
+ * Creates a property set initialized from an argument vector.
+ *
+ * @param args A command-line argument vector, possibly containing
+ * options to set properties. If the command-line options include
+ * a <code>--Ice.Config</code> option, the corresponding configuration
+ * files are parsed. If the same property is set in a configuration
+ * file and in the argument vector, the argument vector takes precedence.
+ *
+ * @return A property set initialized with the property settings
+ * in <code>args</code>.
+ **/
+ public static Properties
+ createProperties(String[] args)
+ {
+ StringSeqHolder argsH = new StringSeqHolder(args);
+ return createProperties(argsH);
+ }
+
+ /**
+ * Creates a property set initialized from an argument vector.
+ *
+ * @param args A command-line argument vector, possibly containing
+ * options to set properties. If the command-line options include
+ * a <code>--Ice.Config</code> option, the corresponding configuration
+ * files are parsed. If the same property is set in a configuration
+ * file and in the argument vector, the argument vector takes precedence.
+ * @param defaults Default values for the property set. Settings in configuration
+ * files and <code>args</code> override these defaults.
+ *
+ * @return An initalized property set.
+ **/
+ public static Properties
+ createProperties(String[] args, Properties defaults)
+ {
+ StringSeqHolder argsH = new StringSeqHolder(args);
+ return createProperties(argsH, defaults);
+ }
+
+ /**
+ * Creates a communicator.
+ *
+ * @param args A command-line argument vector. Any Ice-related options
+ * in this vector are used to intialize the communicator.
+ * This method modifies the argument vector by removing any Ice-related options.
+ *
+ * @return The initialized communicator.
+ **/
+ public static Communicator
+ initialize(StringSeqHolder args)
+ {
+ return initialize(args, null);
+ }
+
+ /**
+ * Creates a communicator.
+ *
+ * @param args A command-line argument vector. Any Ice-related options
+ * in this vector are used to intialize the communicator.
+ *
+ * @return The initialized communicator.
+ **/
+ public static Communicator
+ initialize(String[] args)
+ {
+ StringSeqHolder argsH = new StringSeqHolder(args);
+ return initialize(argsH);
+ }
+
+ /**
+ * Creates a communicator.
+ *
+ * @param args A command-line argument vector. Any Ice-related options
+ * in this vector are used to intialize the communicator.
+ * This method modifies the argument vector by removing any Ice-related options.
+ *
+ * @param initData Additional intialization data. Property settings in <code>args</code>
+ * override property settings in <code>initData</code>.
+ *
+ * @return The initialized communicator.
+ *
+ * @see InitializationData
+ **/
+ public static Communicator
+ initialize(StringSeqHolder args, InitializationData initData)
+ {
+ if(initData == null)
+ {
+ initData = new InitializationData();
+ }
+ else
+ {
+ initData = initData.clone();
+ }
+ initData.properties = createProperties(args, initData.properties);
+
+ CommunicatorI result = new CommunicatorI(initData);
+ result.finishSetup(args);
+ return result;
+ }
+
+ /**
+ * Creates a communicator.
+ *
+ * @param args A command-line argument vector. Any Ice-related options
+ * in this vector are used to intialize the communicator.
+ *
+ * @param initData Additional intialization data. Property settings in <code>args</code>
+ * override property settings in <code>initData</code>.
+ *
+ * @return The initialized communicator.
+ *
+ * @see InitializationData
+ **/
+ public static Communicator
+ initialize(String[] args, InitializationData initData)
+ {
+ StringSeqHolder argsH = new StringSeqHolder(args);
+ return initialize(argsH, initData);
+ }
+
+ /**
+ * Creates a communicator.
+ *
+ * @param initData Additional intialization data.
+ *
+ * @return The initialized communicator.
+ *
+ * @see InitializationData
+ **/
+ public static Communicator
+ initialize(InitializationData initData)
+ {
+ if(initData == null)
+ {
+ initData = new InitializationData();
+ }
+ else
+ {
+ initData = initData.clone();
+ }
+
+ CommunicatorI result = new CommunicatorI(initData);
+ result.finishSetup(new StringSeqHolder(new String[0]));
+ return result;
+ }
+
+ /**
+ * Creates a communicator using a default configuration.
+ **/
+ public static Communicator
+ initialize()
+ {
+ return initialize(new InitializationData());
+ }
+
+ /**
+ * Converts a string to an object identity.
+ *
+ * @param s The string to convert.
+ *
+ * @return The converted object identity.
+ **/
+ public static Identity
+ stringToIdentity(String s)
+ {
+ Identity ident = new Identity();
+
+ //
+ // Find unescaped separator; note that the string may contain an escaped
+ // backslash before the separator.
+ //
+ int slash = -1, pos = 0;
+ while((pos = s.indexOf('/', pos)) != -1)
+ {
+ int escapes = 0;
+ while(pos - escapes > 0 && s.charAt(pos - escapes - 1) == '\\')
+ {
+ escapes++;
+ }
+
+ //
+ // We ignore escaped escapes
+ //
+ if(escapes % 2 == 0)
+ {
+ if(slash == -1)
+ {
+ slash = pos;
+ }
+ else
+ {
+ //
+ // Extra unescaped slash found.
+ //
+ IdentityParseException ex = new IdentityParseException();
+ ex.str = "unescaped backslash in identity `" + s + "'";
+ throw ex;
+ }
+ }
+ pos++;
+ }
+
+ if(slash == -1)
+ {
+ ident.category = "";
+ try
+ {
+ ident.name = IceUtilInternal.StringUtil.unescapeString(s, 0, s.length());
+ }
+ catch(IllegalArgumentException e)
+ {
+ IdentityParseException ex = new IdentityParseException();
+ ex.str = "invalid identity name `" + s + "': " + e.getMessage();
+ throw ex;
+ }
+ }
+ else
+ {
+ try
+ {
+ ident.category = IceUtilInternal.StringUtil.unescapeString(s, 0, slash);
+ }
+ catch(IllegalArgumentException e)
+ {
+ IdentityParseException ex = new IdentityParseException();
+ ex.str = "invalid category in identity `" + s + "': " + e.getMessage();
+ throw ex;
+ }
+ if(slash + 1 < s.length())
+ {
+ try
+ {
+ ident.name = IceUtilInternal.StringUtil.unescapeString(s, slash + 1, s.length());
+ }
+ catch(IllegalArgumentException e)
+ {
+ IdentityParseException ex = new IdentityParseException();
+ ex.str = "invalid name in identity `" + s + "': " + e.getMessage();
+ 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.
+ **/
+ public static String
+ identityToString(Identity ident)
+ {
+ if(ident.category == null || ident.category.length() == 0)
+ {
+ return IceUtilInternal.StringUtil.escapeString(ident.name, "/");
+ }
+ else
+ {
+ return IceUtilInternal.StringUtil.escapeString(ident.category, "/") + '/' +
+ IceUtilInternal.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 ProxyIdentityFacetKey
+ * @see #proxyIdentityAndFacetCompare
+ **/
+ public static int
+ proxyIdentityCompare(ObjectPrx lhs, ObjectPrx rhs)
+ {
+ if(lhs == null && rhs == null)
+ {
+ return 0;
+ }
+ else if(lhs == null && rhs != null)
+ {
+ return -1;
+ }
+ else if(lhs != null && rhs == null)
+ {
+ return 1;
+ }
+ else
+ {
+ Identity lhsIdentity = lhs.ice_getIdentity();
+ Identity rhsIdentity = rhs.ice_getIdentity();
+ int n;
+ if((n = lhsIdentity.name.compareTo(rhsIdentity.name)) != 0)
+ {
+ return n;
+ }
+ return lhsIdentity.category.compareTo(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 ProxyIdentityFacetKey
+ * @see ProxyIdentityKey
+ * @see #proxyIdentityCompare
+ **/
+ public static int
+ proxyIdentityAndFacetCompare(ObjectPrx lhs, ObjectPrx rhs)
+ {
+ if(lhs == null && rhs == null)
+ {
+ return 0;
+ }
+ else if(lhs == null && rhs != null)
+ {
+ return -1;
+ }
+ else if(lhs != null && rhs == null)
+ {
+ return 1;
+ }
+ else
+ {
+ Identity lhsIdentity = lhs.ice_getIdentity();
+ Identity rhsIdentity = rhs.ice_getIdentity();
+ int n;
+ if((n = lhsIdentity.name.compareTo(rhsIdentity.name)) != 0)
+ {
+ return n;
+ }
+ if((n = lhsIdentity.category.compareTo(rhsIdentity.category)) != 0)
+ {
+ return n;
+ }
+
+ String lhsFacet = lhs.ice_getFacet();
+ String 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.compareTo(rhsFacet);
+ }
+ }
+
+ /**
+ * Returns the process-wide logger.
+ *
+ * @return The process-wide logger.
+ **/
+ public static Logger
+ getProcessLogger()
+ {
+ synchronized(_processLoggerMutex)
+ {
+ if(_processLogger == null)
+ {
+ //
+ // TODO: Would be nice to be able to use process name as prefix by default.
+ //
+ _processLogger = new LoggerI("", "");
+ }
+
+ return _processLogger;
+ }
+ }
+
+ /**
+ * Changes the process-wide logger.
+ *
+ * @param logger The new process-wide logger.
+ **/
+ public static void
+ setProcessLogger(Logger logger)
+ {
+ synchronized(_processLoggerMutex)
+ {
+ _processLogger = logger;
+ }
+ }
+
+ /**
+ * Returns the Ice version in the form <code>A.B.C</code>, where <code>A</code> indicates the
+ * major version, <code>B</code> indicates the minor version, and <code>C</code> indicates the
+ * patch level.
+ *
+ * @return The Ice version.
+ **/
+ public static String
+ stringVersion()
+ {
+ return "3.7a3"; // "A.B.C", with A=major, B=minor, C=patch
+ }
+
+ /**
+ * Returns the Ice version as an integer in the form <code>A.BB.CC</code>, where <code>A</code>
+ * indicates the major version, <code>BB</code> indicates the minor version, and <code>CC</code>
+ * indicates the patch level. For example, for Ice 3.3.1, the returned value is 30301.
+ *
+ * @return The Ice version.
+ **/
+ public static int
+ intVersion()
+ {
+ return 30753; // AABBCC, with AA=major, BB=minor, CC=patch
+ }
+
+ /**
+ * Converts a string to a protocol version.
+ *
+ * @param version The string to convert.
+ *
+ * @return The converted protocol version.
+ **/
+ static public Ice.ProtocolVersion
+ stringToProtocolVersion(String 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.
+ **/
+ static public Ice.EncodingVersion
+ stringToEncodingVersion(String 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.
+ **/
+ static public String
+ protocolVersionToString(Ice.ProtocolVersion 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.
+ **/
+ static public String
+ encodingVersionToString(Ice.EncodingVersion v)
+ {
+ return majorMinorToString(v.major, v.minor);
+ }
+
+ /**
+ * Returns the supported Ice protocol version.
+ *
+ * @return The Ice protocol version.
+ **/
+ static public Ice.ProtocolVersion
+ currentProtocol()
+ {
+ return IceInternal.Protocol.currentProtocol.clone();
+ }
+
+ /**
+ * Returns the supported Ice encoding version.
+ *
+ * @return The Ice encoding version.
+ **/
+ static public Ice.EncodingVersion
+ currentEncoding()
+ {
+ return IceInternal.Protocol.currentEncoding.clone();
+ }
+
+ /**
+ * Translates a Slice type id to a Java class name.
+ *
+ * @param id The Slice type id, such as <code>::Module::Type</code>.
+ * @return The equivalent Java class name, or null if the type id is malformed.
+ **/
+ public static String typeIdToClass(String id)
+ {
+ if(!id.startsWith("::"))
+ {
+ return null;
+ }
+
+ StringBuilder buf = new StringBuilder(id.length());
+
+ int start = 2;
+ boolean done = false;
+ while(!done)
+ {
+ int end = id.indexOf(':', start);
+ String s;
+ if(end != -1)
+ {
+ s = id.substring(start, end);
+ start = end + 2;
+ }
+ else
+ {
+ s = id.substring(start);
+ done = true;
+ }
+ if(buf.length() > 0)
+ {
+ buf.append('.');
+ }
+ buf.append(fixKwd(s));
+ }
+
+ return buf.toString();
+ }
+
+ private static String fixKwd(String name)
+ {
+ //
+ // Keyword list. *Must* be kept in alphabetical order. Note that checkedCast and uncheckedCast
+ // are not Java keywords, but are in this list to prevent illegal code being generated if
+ // someone defines Slice operations with that name.
+ //
+ final String[] keywordList =
+ {
+ "abstract", "assert", "boolean", "break", "byte", "case", "catch",
+ "char", "checkedCast", "class", "clone", "const", "continue", "default", "do",
+ "double", "else", "enum", "equals", "extends", "false", "final", "finalize",
+ "finally", "float", "for", "getClass", "goto", "hashCode", "if",
+ "implements", "import", "instanceof", "int", "interface", "long",
+ "native", "new", "notify", "notifyAll", "null", "package", "private",
+ "protected", "public", "return", "short", "static", "strictfp", "super", "switch",
+ "synchronized", "this", "throw", "throws", "toString", "transient",
+ "true", "try", "uncheckedCast", "void", "volatile", "wait", "while"
+ };
+ boolean found = java.util.Arrays.binarySearch(keywordList, name) >= 0;
+ return found ? "_" + name : name;
+ }
+
+ static private byte
+ stringToMajor(String str)
+ {
+ int pos = str.indexOf('.');
+ if(pos == -1)
+ {
+ throw new Ice.VersionParseException("malformed version value `" + str + "'");
+ }
+
+ String majStr = str.substring(0, pos);
+ int majVersion;
+ try
+ {
+ majVersion = Integer.parseInt(majStr);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.VersionParseException("invalid version value `" + str + "'");
+ }
+
+ if(majVersion < 1 || majVersion > 255)
+ {
+ throw new Ice.VersionParseException("range error in version `" + str + "'");
+ }
+
+ return (byte)majVersion;
+ }
+
+ static private byte
+ stringToMinor(String str)
+ {
+ int pos = str.indexOf('.');
+ if(pos == -1)
+ {
+ throw new Ice.VersionParseException("malformed version value `" + str + "'");
+ }
+
+ String minStr = str.substring(pos + 1, str.length());
+ int minVersion;
+ try
+ {
+ minVersion = Integer.parseInt(minStr);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.VersionParseException("invalid version value `" + str + "'");
+ }
+
+ if(minVersion < 0 || minVersion > 255)
+ {
+ throw new Ice.VersionParseException("range error in version `" + str + "'");
+ }
+
+ return (byte)minVersion;
+ }
+
+ static private String
+ majorMinorToString(byte major, byte minor)
+ {
+ StringBuilder str = new StringBuilder();
+ str.append(major < 0 ? major + 255 : (int)major);
+ str.append(".");
+ str.append(minor < 0 ? minor + 255 : (int)minor);
+ return str.toString();
+ }
+
+ public final static Ice.ProtocolVersion Protocol_1_0 = new Ice.ProtocolVersion((byte)1, (byte)0);
+
+ public final static Ice.EncodingVersion Encoding_1_0 = new Ice.EncodingVersion((byte)1, (byte)0);
+ public final static Ice.EncodingVersion Encoding_1_1 = new Ice.EncodingVersion((byte)1, (byte)1);
+
+ private static java.lang.Object _processLoggerMutex = new java.lang.Object();
+ private static Logger _processLogger = null;
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/ValueFactoryManagerI.java b/java-compat/src/Ice/src/main/java/Ice/ValueFactoryManagerI.java
new file mode 100644
index 00000000000..13e968f5cae
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/ValueFactoryManagerI.java
@@ -0,0 +1,30 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+public class ValueFactoryManagerI implements ValueFactoryManager
+{
+ public synchronized void add(ValueFactory factory, String id)
+ {
+ if(_factoryMap.containsKey(id))
+ {
+ throw new AlreadyRegisteredException("value factory", id);
+ }
+
+ _factoryMap.put(id, factory);
+ }
+
+ public synchronized ValueFactory find(String id)
+ {
+ return _factoryMap.get(id);
+ }
+
+ private java.util.HashMap<String, ValueFactory> _factoryMap = new java.util.HashMap<String, ValueFactory>();
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/_AMD_Object_ice_invoke.java b/java-compat/src/Ice/src/main/java/Ice/_AMD_Object_ice_invoke.java
new file mode 100644
index 00000000000..edc77cb14be
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/_AMD_Object_ice_invoke.java
@@ -0,0 +1,38 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+final class _AMD_Object_ice_invoke extends IceInternal.IncomingAsync implements AMD_Object_ice_invoke
+{
+ public
+ _AMD_Object_ice_invoke(IceInternal.Incoming in)
+ {
+ super(in);
+ }
+
+ @Override
+ public void
+ ice_response(boolean ok, byte[] outEncaps)
+ {
+ if(__validateResponse(ok))
+ {
+ try
+ {
+ __writeParamEncaps(outEncaps, ok);
+ }
+ catch(Ice.LocalException ex)
+ {
+ __exception(ex);
+ return;
+ }
+ __response();
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/Ice/_Callback_Object_ice_invoke.java b/java-compat/src/Ice/src/main/java/Ice/_Callback_Object_ice_invoke.java
new file mode 100644
index 00000000000..6357f50555c
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/Ice/_Callback_Object_ice_invoke.java
@@ -0,0 +1,28 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Callback object for {@link ObjectPrx#begin_ice_invoke}.
+ **/
+public interface _Callback_Object_ice_invoke extends Ice.TwowayCallback
+{
+ /**
+ * The Ice run time calls <code>response</code> when an asynchronous operation invocation
+ * completes successfully or raises a user exception.
+ *
+ * @param ret Indicates the result of the invocation. If <code>true</code>, the operation
+ * completed succesfully; if <code>false</code>, the operation raised a user exception.
+ * @param outParams Contains the encoded out-parameters of the operation (if any) if <code>ok</code>
+ * is <code>true</code>; otherwise, if <code>ok</code> is <code>false</code>, contains the
+ * encoded user exception raised by the operation.
+ **/
+ public void response(boolean ret, byte[] outParams);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ACMConfig.java b/java-compat/src/Ice/src/main/java/IceInternal/ACMConfig.java
new file mode 100644
index 00000000000..291e9d1c59f
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ACMConfig.java
@@ -0,0 +1,82 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class ACMConfig implements java.lang.Cloneable
+{
+ ACMConfig(boolean server)
+ {
+ timeout = 60 * 1000;
+ heartbeat = Ice.ACMHeartbeat.HeartbeatOnInvocation;
+ close = server ? Ice.ACMClose.CloseOnInvocation : Ice.ACMClose.CloseOnInvocationAndIdle;
+ }
+
+ public ACMConfig(Ice.Properties p, Ice.Logger l, String prefix, ACMConfig dflt)
+ {
+ assert(prefix != null);
+
+ String timeoutProperty;
+ if((prefix.equals("Ice.ACM.Client") || prefix.equals("Ice.ACM.Server")) &&
+ p.getProperty(prefix + ".Timeout").isEmpty())
+ {
+ timeoutProperty = prefix; // Deprecated property.
+ }
+ else
+ {
+ timeoutProperty = prefix + ".Timeout";
+ }
+
+ timeout = p.getPropertyAsIntWithDefault(timeoutProperty, dflt.timeout / 1000) * 1000; // To milliseconds
+
+ int hb = p.getPropertyAsIntWithDefault(prefix + ".Heartbeat", dflt.heartbeat.ordinal());
+ Ice.ACMHeartbeat[] heartbeatValues = Ice.ACMHeartbeat.values();
+ if(hb >= 0 && hb < heartbeatValues.length)
+ {
+ heartbeat = heartbeatValues[hb];
+ }
+ else
+ {
+ l.warning("invalid value for property `" + prefix + ".Heartbeat" + "', default value will be used instead");
+ heartbeat = dflt.heartbeat;
+ }
+
+ Ice.ACMClose[] closeValues = Ice.ACMClose.values();
+ int cl = p.getPropertyAsIntWithDefault(prefix + ".Close", dflt.close.ordinal());
+ if(cl >= 0 && cl < closeValues.length)
+ {
+ close = closeValues[cl];
+ }
+ else
+ {
+ l.warning("invalid value for property `" + prefix + ".Close" + "', default value will be used instead");
+ close = dflt.close;
+ }
+ }
+
+ @Override
+ public ACMConfig
+ clone()
+ {
+ ACMConfig c = null;
+ try
+ {
+ c = (ACMConfig)super.clone();
+ }
+ catch(CloneNotSupportedException ex)
+ {
+ assert false; // impossible
+ }
+ return c;
+ }
+
+ public int timeout;
+ public Ice.ACMHeartbeat heartbeat;
+ public Ice.ACMClose close;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ACMMonitor.java b/java-compat/src/Ice/src/main/java/IceInternal/ACMMonitor.java
new file mode 100644
index 00000000000..0265886b023
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ACMMonitor.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface ACMMonitor
+{
+ void add(Ice.ConnectionI con);
+ void remove(Ice.ConnectionI con);
+ void reap(Ice.ConnectionI con);
+
+ ACMMonitor acm(Ice.IntOptional timeout, Ice.Optional<Ice.ACMClose> close, Ice.Optional<Ice.ACMHeartbeat> heartbeat);
+ Ice.ACM getACM();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Acceptor.java b/java-compat/src/Ice/src/main/java/IceInternal/Acceptor.java
new file mode 100644
index 00000000000..628e147620a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Acceptor.java
@@ -0,0 +1,23 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Acceptor
+{
+ java.nio.channels.ServerSocketChannel fd();
+ void setReadyCallback(ReadyCallback callback);
+ void close();
+ EndpointI listen();
+ Transceiver accept();
+ String protocol();
+ @Override
+ String toString();
+ String toDetailedString();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/AsyncResultI.java b/java-compat/src/Ice/src/main/java/IceInternal/AsyncResultI.java
new file mode 100644
index 00000000000..41f49774a0e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/AsyncResultI.java
@@ -0,0 +1,469 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import Ice.AsyncResult;
+import Ice.Communicator;
+import Ice.CommunicatorDestroyedException;
+import Ice.Connection;
+
+public class AsyncResultI implements AsyncResult
+{
+ @Override
+ public void cancel()
+ {
+ cancel(new Ice.InvocationCanceledException());
+ }
+
+ @Override
+ public Communicator getCommunicator()
+ {
+ return _communicator;
+ }
+
+ @Override
+ public Connection getConnection()
+ {
+ return null;
+ }
+
+ @Override
+ public Ice.ObjectPrx getProxy()
+ {
+ return null;
+ }
+
+ @Override
+ public final boolean isCompleted()
+ {
+ synchronized(this)
+ {
+ return (_state & StateDone) > 0;
+ }
+ }
+
+ @Override
+ public final void waitForCompleted()
+ {
+ synchronized(this)
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ while((_state & StateDone) == 0)
+ {
+ try
+ {
+ this.wait();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+ }
+ }
+
+ @Override
+ public final boolean isSent()
+ {
+ synchronized(this)
+ {
+ return (_state & StateSent) > 0;
+ }
+ }
+
+ @Override
+ public final void waitForSent()
+ {
+ synchronized(this)
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ while((_state & StateSent) == 0 && _exception == null)
+ {
+ try
+ {
+ this.wait();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+ }
+ }
+
+ @Override
+ public final void throwLocalException()
+ {
+ synchronized(this)
+ {
+ if(_exception != null)
+ {
+ throw _exception;
+ }
+ }
+ }
+
+ @Override
+ public final boolean sentSynchronously()
+ {
+ return _sentSynchronously; // No lock needed, immutable
+ }
+
+ @Override
+ public final String getOperation()
+ {
+ return _operation;
+ }
+
+ public final void invokeSent()
+ {
+ assert(_callback != null);
+
+ if(_instance.useApplicationClassLoader())
+ {
+ Thread.currentThread().setContextClassLoader(_callback.getClass().getClassLoader());
+ }
+
+ try
+ {
+ _callback.__sent(this);
+ }
+ catch(java.lang.RuntimeException ex)
+ {
+ warning(ex);
+ }
+ catch(java.lang.Error exc)
+ {
+ error(exc);
+ if(!(exc instanceof java.lang.AssertionError || exc instanceof java.lang.OutOfMemoryError))
+ {
+ throw exc;
+ }
+ }
+ finally
+ {
+ if(_instance.useApplicationClassLoader())
+ {
+ Thread.currentThread().setContextClassLoader(null);
+ }
+ }
+
+ if(_observer != null)
+ {
+ Ice.ObjectPrx proxy = getProxy();
+ if(proxy == null || !proxy.ice_isTwoway())
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ }
+ }
+
+ public final void invokeCompleted()
+ {
+ assert(_callback != null);
+
+ if(_instance.useApplicationClassLoader())
+ {
+ Thread.currentThread().setContextClassLoader(_callback.getClass().getClassLoader());
+ }
+
+ try
+ {
+ _callback.__completed(this);
+ }
+ catch(RuntimeException ex)
+ {
+ warning(ex);
+ }
+ catch(AssertionError exc)
+ {
+ error(exc);
+ }
+ catch(OutOfMemoryError exc)
+ {
+ error(exc);
+ }
+ finally
+ {
+ if(_instance.useApplicationClassLoader())
+ {
+ Thread.currentThread().setContextClassLoader(null);
+ }
+ }
+
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ }
+
+ public final void invokeCompletedAsync()
+ {
+ //
+ // CommunicatorDestroyedCompleted is the only exception that can propagate directly
+ // from this method.
+ //
+ _instance.clientThreadPool().dispatch(new DispatchWorkItem(_cachedConnection)
+ {
+ @Override
+ public void run()
+ {
+ invokeCompleted();
+ }
+ });
+ }
+
+ synchronized public void cancelable(final CancellationHandler handler)
+ {
+ if(_cancellationException != null)
+ {
+ try
+ {
+ throw _cancellationException;
+ }
+ finally
+ {
+ _cancellationException = null;
+ }
+ }
+ _cancellationHandler = handler;
+ }
+
+ public final boolean __wait()
+ {
+ try
+ {
+ synchronized(this)
+ {
+ if((_state & StateEndCalled) > 0)
+ {
+ throw new IllegalArgumentException("end_ method called more than once");
+ }
+
+ _state |= StateEndCalled;
+ if(Thread.interrupted())
+ {
+ throw new InterruptedException();
+ }
+ while((_state & StateDone) == 0)
+ {
+ this.wait();
+ }
+
+ if(_exception != null)
+ {
+ throw (Ice.Exception)_exception.fillInStackTrace();
+ }
+
+ return (_state & StateOK) > 0;
+ }
+ }
+ catch(InterruptedException ex)
+ {
+ Ice.OperationInterruptedException exc = new Ice.OperationInterruptedException();
+ cancel(exc); // Must be called outside the synchronization
+ throw exc;
+ }
+ }
+
+ public void cacheMessageBuffers()
+ {
+ }
+
+ protected AsyncResultI(Communicator communicator, Instance instance, String op, CallbackBase del)
+ {
+ _communicator = communicator;
+ _instance = instance;
+ _operation = op;
+ _state = 0;
+ _sentSynchronously = false;
+ _exception = null;
+ _callback = del;
+ }
+
+ protected boolean sent(boolean done)
+ {
+ synchronized(this)
+ {
+ assert(_exception == null);
+
+ boolean alreadySent = (_state & StateSent) != 0;
+ _state |= StateSent;
+ if(done)
+ {
+ _state |= StateDone | StateOK;
+ _cancellationHandler = null;
+ if(_observer != null && (_callback == null || !_callback.__hasSentCallback()))
+ {
+ _observer.detach();
+ _observer = null;
+ }
+
+ //
+ // For oneway requests after the data has been sent
+ // the buffers can be reused unless this is a
+ // collocated invocation. For collocated invocations
+ // the buffer won't be reused because it has already
+ // been marked as cached in invokeCollocated.
+ //
+ cacheMessageBuffers();
+ }
+ this.notifyAll();
+ return !alreadySent && _callback != null && _callback.__hasSentCallback();
+ }
+ }
+
+ protected boolean finished(boolean ok)
+ {
+ synchronized(this)
+ {
+ _state |= StateDone;
+ if(ok)
+ {
+ _state |= StateOK;
+ }
+ _cancellationHandler = null;
+ if(_callback == null)
+ {
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ }
+ this.notifyAll();
+ return _callback != null;
+ }
+ }
+
+ protected boolean finished(Ice.Exception ex)
+ {
+ synchronized(this)
+ {
+ _state |= StateDone;
+ _exception = ex;
+ _cancellationHandler = null;
+ if(_observer != null)
+ {
+ _observer.failed(ex.ice_id());
+ }
+ if(_callback == null)
+ {
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ }
+ this.notifyAll();
+ return _callback != null;
+ }
+ }
+
+ protected final void invokeSentAsync()
+ {
+ //
+ // This is called when it's not safe to call the sent callback
+ // synchronously from this thread. Instead the exception callback
+ // is called asynchronously from the client thread pool.
+ //
+ try
+ {
+ _instance.clientThreadPool().dispatch(new DispatchWorkItem(_cachedConnection)
+ {
+ @Override
+ public void run()
+ {
+ invokeSent();
+ }
+ });
+ }
+ catch(CommunicatorDestroyedException exc)
+ {
+ }
+ }
+
+ protected void cancel(Ice.LocalException ex)
+ {
+ CancellationHandler handler;
+ synchronized(this)
+ {
+ _cancellationException = ex;
+ if(_cancellationHandler == null)
+ {
+ return;
+ }
+ handler = _cancellationHandler;
+ }
+ handler.asyncRequestCanceled((OutgoingAsyncBase)this, ex);
+ }
+
+ protected Ice.Instrumentation.InvocationObserver getObserver()
+ {
+ return _observer;
+ }
+
+ protected static void check(AsyncResult r, String operation)
+ {
+ if(r == null)
+ {
+ throw new IllegalArgumentException("AsyncResult == null");
+ }
+ else if(r.getOperation() != operation) // Do NOT use equals() here - we are comparing reference equality
+ {
+ throw new IllegalArgumentException("Incorrect operation for end_" + operation + " method: " +
+ r.getOperation());
+ }
+ }
+
+ private void warning(RuntimeException ex)
+ {
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0)
+ {
+ String s = "exception raised by AMI callback:\n" + Ex.toString(ex);
+ _instance.initializationData().logger.warning(s);
+ }
+ }
+
+ private void error(Error error)
+ {
+ String s = "error raised by AMI callback:\n" + Ex.toString(error);
+ _instance.initializationData().logger.error(s);
+ }
+
+ protected final Instance _instance;
+ protected Ice.Instrumentation.InvocationObserver _observer;
+ protected Connection _cachedConnection;
+ protected boolean _sentSynchronously;
+
+ private final Communicator _communicator;
+ private final String _operation;
+ private final CallbackBase _callback;
+
+ private Ice.Exception _exception;
+
+ private CancellationHandler _cancellationHandler;
+ private Ice.LocalException _cancellationException;
+
+ protected static final byte StateOK = 0x1;
+ protected static final byte StateDone = 0x2;
+ protected static final byte StateSent = 0x4;
+ protected static final byte StateEndCalled = 0x8;
+ protected static final byte StateCachedBuffers = 0x10;
+ protected byte _state;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/AsyncStatus.java b/java-compat/src/Ice/src/main/java/IceInternal/AsyncStatus.java
new file mode 100644
index 00000000000..19fa9f28cb0
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/AsyncStatus.java
@@ -0,0 +1,17 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class AsyncStatus
+{
+ public static final int Queued = 0;
+ public static final int Sent = 1;
+ public static final int InvokeSentCallback = 2;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/BZip2.java b/java-compat/src/Ice/src/main/java/IceInternal/BZip2.java
new file mode 100644
index 00000000000..a29b7c30c32
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/BZip2.java
@@ -0,0 +1,281 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class BZip2
+{
+ public static Buffer compress(Buffer buf, int headerSize, int compressionLevel)
+ {
+ assert(supported());
+
+ int uncompressedLen = buf.size() - headerSize;
+ int compressedLen = (int)(uncompressedLen * 1.01 + 600);
+ byte[] compressed = new byte[compressedLen];
+
+ byte[] data = null;
+ int offset = 0;
+ try
+ {
+ //
+ // If the ByteBuffer is backed by an array then we can avoid
+ // an extra copy by using the array directly.
+ //
+ data = buf.b.array();
+ offset = buf.b.arrayOffset();
+ }
+ catch(Exception ex)
+ {
+ //
+ // Otherwise, allocate an array to hold a copy of the uncompressed data.
+ //
+ data = new byte[buf.size()];
+ buf.b.position(0);
+ buf.b.get(data);
+ }
+
+ try
+ {
+ //
+ // Compress the data using the class org.apache.tools.bzip2.CBZip2OutputStream.
+ // Its constructor requires an OutputStream argument, therefore we pass the
+ // compressed buffer in an OutputStream wrapper.
+ //
+ BufferedOutputStream bos = new BufferedOutputStream(compressed);
+ //
+ // For interoperability with the bzip2 C library, we insert the magic bytes
+ // 'B', 'Z' before invoking the Java implementation.
+ //
+ bos.write('B');
+ bos.write('Z');
+ java.lang.Object[] args = new java.lang.Object[]{ bos, Integer.valueOf(compressionLevel) };
+ java.io.OutputStream os = (java.io.OutputStream)_bzOutputStreamCtor.newInstance(args);
+ os.write(data, offset + headerSize, uncompressedLen);
+ os.close();
+ compressedLen = bos.pos();
+ }
+ catch(Exception ex)
+ {
+ throw new Ice.CompressionException("bzip2 compression failure", ex);
+ }
+
+ //
+ // Don't bother if the compressed data is larger than the
+ // uncompressed data.
+ //
+ if(compressedLen >= uncompressedLen)
+ {
+ return null;
+ }
+
+ Buffer r = new Buffer(false);
+ r.resize(headerSize + 4 + compressedLen, false);
+ r.b.position(0);
+
+ //
+ // Copy the header from the uncompressed stream to the compressed one.
+ //
+ r.b.put(data, offset, headerSize);
+
+ //
+ // Add the size of the uncompressed stream before the message body.
+ //
+ r.b.putInt(buf.size());
+
+ //
+ // Add the compressed message body.
+ //
+ r.b.put(compressed, 0, compressedLen);
+
+ return r;
+ }
+
+ public static Buffer uncompress(Buffer buf, int headerSize, int messageSizeMax)
+ {
+ assert(supported());
+
+ buf.b.position(headerSize);
+ int uncompressedSize = buf.b.getInt();
+ if(uncompressedSize <= headerSize)
+ {
+ throw new Ice.IllegalMessageSizeException();
+ }
+ if(uncompressedSize > messageSizeMax)
+ {
+ IceInternal.Ex.throwMemoryLimitException(uncompressedSize, messageSizeMax);
+ }
+
+ int compressedLen = buf.size() - headerSize - 4;
+
+ byte[] compressed = null;
+ int offset = 0;
+ try
+ {
+ //
+ // If the ByteBuffer is backed by an array then we can avoid
+ // an extra copy by using the array directly.
+ //
+ compressed = buf.b.array();
+ offset = buf.b.arrayOffset();
+ }
+ catch(Exception ex)
+ {
+ //
+ // Otherwise, allocate an array to hold a copy of the compressed data.
+ //
+ compressed = new byte[buf.size()];
+ buf.b.position(0);
+ buf.b.get(compressed);
+ }
+
+ Buffer r = new Buffer(false);
+ r.resize(uncompressedSize, false);
+
+ try
+ {
+ //
+ // Uncompress the data using the class org.apache.tools.bzip2.CBZip2InputStream.
+ // Its constructor requires an InputStream argument, therefore we pass the
+ // compressed data in a ByteArrayInputStream.
+ //
+ java.io.ByteArrayInputStream bais =
+ new java.io.ByteArrayInputStream(compressed, offset + headerSize + 4, compressedLen);
+ //
+ // For interoperability with the bzip2 C library, we insert the magic bytes
+ // 'B', 'Z' during compression and therefore must extract them before we
+ // invoke the Java implementation.
+ //
+ byte magicB = (byte)bais.read();
+ byte magicZ = (byte)bais.read();
+ if(magicB != (byte)'B' || magicZ != (byte)'Z')
+ {
+ Ice.CompressionException e = new Ice.CompressionException();
+ e.reason = "bzip2 uncompression failure: invalid magic bytes";
+ throw e;
+ }
+ java.lang.Object[] args = new java.lang.Object[]{ bais };
+ java.io.InputStream is = (java.io.InputStream)_bzInputStreamCtor.newInstance(args);
+ r.b.position(headerSize);
+ byte[] arr = new byte[8 * 1024];
+ int n;
+ while((n = is.read(arr)) != -1)
+ {
+ r.b.put(arr, 0, n);
+ }
+ is.close();
+ }
+ catch(Exception ex)
+ {
+ throw new Ice.CompressionException("bzip2 uncompression failure", ex);
+ }
+
+ //
+ // Copy the header from the compressed stream to the uncompressed one.
+ //
+ r.b.position(0);
+ r.b.put(compressed, offset, headerSize);
+
+ return r;
+ }
+
+ private static boolean _checked = false;
+ private static java.lang.reflect.Constructor<?> _bzInputStreamCtor;
+ private static java.lang.reflect.Constructor<?> _bzOutputStreamCtor;
+
+ public synchronized static boolean supported()
+ {
+ //
+ // Use lazy initialization when determining whether support for bzip2 compression is available.
+ //
+ if(!_checked)
+ {
+ _checked = true;
+ try
+ {
+ Class<?> cls;
+ Class<?>[] types = new Class<?>[1];
+ cls = IceInternal.Util.findClass("org.apache.tools.bzip2.CBZip2InputStream", null);
+ if(cls != null)
+ {
+ types[0] = java.io.InputStream.class;
+ _bzInputStreamCtor = cls.getDeclaredConstructor(types);
+ }
+ cls = IceInternal.Util.findClass("org.apache.tools.bzip2.CBZip2OutputStream", null);
+ if(cls != null)
+ {
+ types = new Class[2];
+ types[0] = java.io.OutputStream.class;
+ types[1] = Integer.TYPE;
+ _bzOutputStreamCtor = cls.getDeclaredConstructor(types);
+ }
+ }
+ catch(Exception ex)
+ {
+ // Ignore - bzip2 compression not available.
+ }
+ }
+ return _bzInputStreamCtor != null && _bzOutputStreamCtor != null;
+ }
+
+ private static class BufferedOutputStream extends java.io.OutputStream
+ {
+ BufferedOutputStream(byte[] data)
+ {
+ _data = data;
+ }
+
+ @Override
+ public void close()
+ throws java.io.IOException
+ {
+ }
+
+ @Override
+ public void flush()
+ throws java.io.IOException
+ {
+ }
+
+ @Override
+ public void write(byte[] b)
+ throws java.io.IOException
+ {
+ assert(_data.length - _pos >= b.length);
+ System.arraycopy(b, 0, _data, _pos, b.length);
+ _pos += b.length;
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len)
+ throws java.io.IOException
+ {
+ assert(_data.length - _pos >= len);
+ System.arraycopy(b, off, _data, _pos, len);
+ _pos += len;
+ }
+
+ @Override
+ public void write(int b)
+ throws java.io.IOException
+ {
+ assert(_data.length - _pos >= 1);
+ _data[_pos] = (byte)b;
+ ++_pos;
+ }
+
+ int
+ pos()
+ {
+ return _pos;
+ }
+
+ private byte[] _data;
+ private int _pos;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/BatchRequestQueue.java b/java-compat/src/Ice/src/main/java/IceInternal/BatchRequestQueue.java
new file mode 100644
index 00000000000..3db2ac67177
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/BatchRequestQueue.java
@@ -0,0 +1,239 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class BatchRequestQueue
+{
+ class BatchRequestI implements Ice.BatchRequest
+ {
+ public void reset(Ice.ObjectPrx proxy, String operation, int size)
+ {
+ _proxy = proxy;
+ _operation = operation;
+ _size = size;
+ }
+
+ @Override
+ public void enqueue()
+ {
+ enqueueBatchRequest();
+ }
+
+ @Override
+ public Ice.ObjectPrx getProxy()
+ {
+ return _proxy;
+ }
+
+ @Override
+ public String getOperation()
+ {
+ return _operation;
+ }
+
+ @Override
+ public int getSize()
+ {
+ return _size;
+ }
+
+ private Ice.ObjectPrx _proxy;
+ private String _operation;
+ private int _size;
+ }
+
+ public
+ BatchRequestQueue(Instance instance, boolean datagram)
+ {
+ Ice.InitializationData initData = instance.initializationData();
+ _interceptor = initData.batchRequestInterceptor;
+ _batchStreamInUse = false;
+ _batchRequestNum = 0;
+ _batchStream = new Ice.OutputStream(instance, Protocol.currentProtocolEncoding);
+ _batchStream.writeBlob(Protocol.requestBatchHdr);
+ _batchMarker = _batchStream.size();
+ _request = new BatchRequestI();
+
+ _maxSize = instance.batchAutoFlushSize();
+ if(_maxSize > 0 && datagram)
+ {
+ int udpSndSize = initData.properties.getPropertyAsIntWithDefault("Ice.UDP.SndSize", 65535 - _udpOverhead);
+ if(udpSndSize < _maxSize)
+ {
+ _maxSize = udpSndSize;
+ }
+ }
+ }
+
+ synchronized public void
+ prepareBatchRequest(Ice.OutputStream os)
+ {
+ if(_exception != null)
+ {
+ throw (Ice.LocalException)_exception.fillInStackTrace();
+ }
+
+ waitStreamInUse(false);
+ _batchStreamInUse = true;
+ _batchStream.swap(os);
+ }
+
+ public void
+ finishBatchRequest(Ice.OutputStream os, Ice.ObjectPrx proxy, String operation)
+ {
+ //
+ // No need for synchronization, no other threads are supposed
+ // to modify the queue since we set _batchStreamInUse to true.
+ //
+ assert(_batchStreamInUse);
+ _batchStream.swap(os);
+
+ try
+ {
+ _batchStreamCanFlush = true; // Allow flush to proceed even if the stream is marked in use.
+
+ if(_maxSize > 0 && _batchStream.size() >= _maxSize)
+ {
+ proxy.begin_ice_flushBatchRequests(); // Auto flush
+ }
+
+ assert(_batchMarker < _batchStream.size());
+ if(_interceptor != null)
+ {
+ _request.reset(proxy, operation, _batchStream.size() - _batchMarker);
+ _interceptor.enqueue(_request, _batchRequestNum, _batchMarker);
+ }
+ else
+ {
+ _batchMarker = _batchStream.size();
+ ++_batchRequestNum;
+ }
+ }
+ finally
+ {
+ synchronized(this)
+ {
+ _batchStream.resize(_batchMarker);
+ _batchStreamInUse = false;
+ _batchStreamCanFlush = false;
+ notifyAll();
+ }
+ }
+ }
+
+ synchronized public void
+ abortBatchRequest(Ice.OutputStream os)
+ {
+ if(_batchStreamInUse)
+ {
+ _batchStream.swap(os);
+ _batchStream.resize(_batchMarker);
+ _batchStreamInUse = false;
+ notifyAll();
+ }
+ }
+
+ synchronized public int
+ swap(Ice.OutputStream os)
+ {
+ if(_batchRequestNum == 0)
+ {
+ return 0;
+ }
+
+ waitStreamInUse(true);
+
+ byte[] lastRequest = null;
+ if(_batchMarker < _batchStream.size())
+ {
+ lastRequest = new byte[_batchStream.size() - _batchMarker];
+ Buffer buffer = _batchStream.getBuffer();
+ buffer.b.position(_batchMarker);
+ buffer.b.get(lastRequest);
+ _batchStream.resize(_batchMarker);
+ }
+
+ int requestNum = _batchRequestNum;
+ _batchStream.swap(os);
+
+ //
+ // Reset the batch.
+ //
+ _batchRequestNum = 0;
+ _batchStream.writeBlob(Protocol.requestBatchHdr);
+ _batchMarker = _batchStream.size();
+ if(lastRequest != null)
+ {
+ _batchStream.writeBlob(lastRequest);
+ }
+ return requestNum;
+ }
+
+ synchronized public void
+ destroy(Ice.LocalException ex)
+ {
+ _exception = ex;
+ }
+
+ synchronized public boolean
+ isEmpty()
+ {
+ return _batchStream.size() == Protocol.requestBatchHdr.length;
+ }
+
+ private void
+ waitStreamInUse(boolean flush)
+ {
+ //
+ // This is similar to a mutex lock in that the stream is
+ // only "locked" while marshaling. As such we don't permit the wait
+ // to be interrupted. Instead the interrupted status is saved and
+ // restored.
+ //
+ boolean interrupted = false;
+ while(_batchStreamInUse && !(flush && _batchStreamCanFlush))
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ interrupted = true;
+ }
+ }
+ //
+ // Restore the interrupted flag if we were interrupted.
+ //
+ if(interrupted)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ private void enqueueBatchRequest()
+ {
+ assert(_batchMarker < _batchStream.size());
+ _batchMarker = _batchStream.size();
+ ++_batchRequestNum;
+ }
+
+ private Ice.BatchRequestInterceptor _interceptor;
+ private Ice.OutputStream _batchStream;
+ private boolean _batchStreamInUse;
+ private boolean _batchStreamCanFlush;
+ private int _batchRequestNum;
+ private int _batchMarker;
+ private BatchRequestI _request;
+ private Ice.LocalException _exception;
+ private int _maxSize;
+
+ final private static int _udpOverhead = 20 + 8;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/BufSizeWarnInfo.java b/java-compat/src/Ice/src/main/java/IceInternal/BufSizeWarnInfo.java
new file mode 100644
index 00000000000..67e84387319
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/BufSizeWarnInfo.java
@@ -0,0 +1,25 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+class BufSizeWarnInfo
+{
+ // Whether send size warning has been emitted
+ public boolean sndWarn;
+
+ // The send size for which the warning wwas emitted
+ public int sndSize;
+
+ // Whether receive size warning has been emitted
+ public boolean rcvWarn;
+
+ // The receive size for which the warning wwas emitted
+ public int rcvSize;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Buffer.java b/java-compat/src/Ice/src/main/java/IceInternal/Buffer.java
new file mode 100644
index 00000000000..911d8df76d4
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Buffer.java
@@ -0,0 +1,223 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+//
+// An instance of java.nio.ByteBuffer cannot grow beyond its initial capacity.
+// This class wraps a ByteBuffer and supports reallocation.
+//
+public class Buffer
+{
+ public Buffer(boolean direct)
+ {
+ this(direct, java.nio.ByteOrder.LITTLE_ENDIAN);
+ }
+
+ public Buffer(boolean direct, java.nio.ByteOrder order)
+ {
+ b = _emptyBuffer;
+ _size = 0;
+ _capacity = 0;
+ _direct = direct;
+ _order = order;
+ }
+
+ public Buffer(byte[] data)
+ {
+ this(data, java.nio.ByteOrder.LITTLE_ENDIAN);
+ }
+
+ public Buffer(byte[] data, java.nio.ByteOrder order)
+ {
+ b = java.nio.ByteBuffer.wrap(data);
+ b.order(order);
+ _size = data.length;
+ _capacity = 0;
+ _direct = false;
+ _order = order;
+ }
+
+ public Buffer(java.nio.ByteBuffer data)
+ {
+ this(data, java.nio.ByteOrder.LITTLE_ENDIAN);
+ }
+
+ public Buffer(java.nio.ByteBuffer data, java.nio.ByteOrder order)
+ {
+ b = data;
+ b.order(order);
+ _size = data.remaining();
+ _capacity = 0;
+ _direct = false;
+ _order = order;
+ }
+
+ public Buffer(Buffer buf, boolean adopt)
+ {
+ b = buf.b;
+ _size = buf._size;
+ _capacity = buf._capacity;
+ _direct = buf._direct;
+ _shrinkCounter = buf._shrinkCounter;
+ _order = buf._order;
+
+ if(adopt)
+ {
+ buf.clear();
+ }
+ }
+
+ public int size()
+ {
+ return _size;
+ }
+
+ public boolean empty()
+ {
+ return _size == 0;
+ }
+
+ public void clear()
+ {
+ b = _emptyBuffer;
+ _size = 0;
+ _capacity = 0;
+ _shrinkCounter = 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.
+ //
+ public void expand(int n)
+ {
+ final int sz = (b == _emptyBuffer) ? n : b.position() + n;
+ if(sz > _size)
+ {
+ resize(sz, false);
+ }
+ }
+
+ public void resize(int n, boolean reading)
+ {
+ assert(b == _emptyBuffer || _capacity > 0);
+
+ if(n == 0)
+ {
+ clear();
+ }
+ else if(n > _capacity)
+ {
+ reserve(n);
+ }
+ _size = n;
+
+ //
+ // When used for reading, we want to set the buffer's limit to the new size.
+ //
+ if(reading)
+ {
+ b.limit(_size);
+ }
+ }
+
+ public void reset()
+ {
+ if(_size > 0 && _size * 2 < _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(++_shrinkCounter > 2)
+ {
+ reserve(_size);
+ _shrinkCounter = 0;
+ }
+ }
+ else
+ {
+ _shrinkCounter = 0;
+ }
+ _size = 0;
+ if(b != _emptyBuffer)
+ {
+ b.limit(b.capacity());
+ b.position(0);
+ }
+ }
+
+ private void reserve(int n)
+ {
+ if(n > _capacity)
+ {
+ _capacity = java.lang.Math.max(n, 2 * _capacity);
+ _capacity = java.lang.Math.max(240, _capacity);
+ }
+ else if(n < _capacity)
+ {
+ _capacity = n;
+ }
+ else
+ {
+ return;
+ }
+
+ try
+ {
+ java.nio.ByteBuffer buf;
+
+ if(_direct)
+ {
+ buf = java.nio.ByteBuffer.allocateDirect(_capacity);
+ }
+ else
+ {
+ buf = java.nio.ByteBuffer.allocate(_capacity);
+ }
+
+ if(b == _emptyBuffer)
+ {
+ b = buf;
+ }
+ else
+ {
+ final int pos = b.position();
+ b.position(0);
+ b.limit(java.lang.Math.min(_capacity, b.capacity()));
+ buf.put(b);
+ b = buf;
+ b.limit(b.capacity());
+ b.position(pos);
+ }
+
+ b.order(_order); // Preserve the original order.
+ }
+ catch(OutOfMemoryError ex)
+ {
+ _capacity = b.capacity(); // Restore the previous capacity.
+ throw ex;
+ }
+ }
+
+ public java.nio.ByteBuffer b;
+ // Sentinel used for null buffer.
+ public java.nio.ByteBuffer _emptyBuffer = java.nio.ByteBuffer.allocate(0);
+
+ private int _size;
+ private int _capacity; // Cache capacity to avoid excessive method calls.
+ private boolean _direct; // Use direct buffers?
+ private int _shrinkCounter;
+ private java.nio.ByteOrder _order;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/CallbackBase.java b/java-compat/src/Ice/src/main/java/IceInternal/CallbackBase.java
new file mode 100644
index 00000000000..b482e9a71cd
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/CallbackBase.java
@@ -0,0 +1,25 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class CallbackBase
+{
+ public abstract void __completed(Ice.AsyncResult r);
+ public abstract void __sent(Ice.AsyncResult r);
+ public abstract boolean __hasSentCallback();
+
+ public static void check(boolean cb)
+ {
+ if(!cb)
+ {
+ throw new IllegalArgumentException("callback cannot be null");
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/CancellationHandler.java b/java-compat/src/Ice/src/main/java/IceInternal/CancellationHandler.java
new file mode 100644
index 00000000000..3085b41e3d0
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/CancellationHandler.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface CancellationHandler
+{
+ void asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/CollocatedObserverI.java b/java-compat/src/Ice/src/main/java/IceInternal/CollocatedObserverI.java
new file mode 100644
index 00000000000..a29cc2ad237
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/CollocatedObserverI.java
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class CollocatedObserverI
+ extends IceMX.ObserverWithDelegate<IceMX.CollocatedMetrics, Ice.Instrumentation.CollocatedObserver>
+ implements Ice.Instrumentation.CollocatedObserver
+{
+ @Override
+ public void
+ reply(final int size)
+ {
+ forEach(new MetricsUpdate<IceMX.CollocatedMetrics>()
+ {
+ @Override
+ public void
+ update(IceMX.CollocatedMetrics v)
+ {
+ v.replySize += size;
+ }
+ });
+ if(_delegate != null)
+ {
+ _delegate.reply(size);
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/CollocatedRequestHandler.java b/java-compat/src/Ice/src/main/java/IceInternal/CollocatedRequestHandler.java
new file mode 100644
index 00000000000..ad823f21319
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/CollocatedRequestHandler.java
@@ -0,0 +1,436 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
+{
+ private class InvokeAllAsync extends DispatchWorkItem
+ {
+ private InvokeAllAsync(OutgoingAsyncBase outAsync, Ice.OutputStream os, int requestId, int batchRequestNum)
+ {
+ _outAsync = outAsync;
+ _os = os;
+ _requestId = requestId;
+ _batchRequestNum = batchRequestNum;
+ }
+
+ @Override
+ public void run()
+ {
+ if(sentAsync(_outAsync))
+ {
+ invokeAll(_os, _requestId, _batchRequestNum);
+ }
+ }
+
+ private final OutgoingAsyncBase _outAsync;
+ private Ice.OutputStream _os;
+ private final int _requestId;
+ private final int _batchRequestNum;
+ }
+
+ public
+ CollocatedRequestHandler(Reference ref, Ice.ObjectAdapter adapter)
+ {
+ _reference = ref;
+ _dispatcher = ref.getInstance().initializationData().dispatcher != null;
+ _adapter = (Ice.ObjectAdapterI)adapter;
+ _response = _reference.getMode() == Reference.ModeTwoway;
+
+ _logger = _reference.getInstance().initializationData().logger; // Cached for better performance.
+ _traceLevels = _reference.getInstance().traceLevels(); // Cached for better performance.
+ _requestId = 0;
+ }
+
+ @Override
+ public RequestHandler
+ update(RequestHandler previousHandler, RequestHandler newHandler)
+ {
+ return previousHandler == this ? newHandler : this;
+ }
+
+ @Override
+ public int
+ sendAsyncRequest(ProxyOutgoingAsyncBase outAsync)
+ {
+ return outAsync.invokeCollocated(this);
+ }
+
+ @Override
+ synchronized public void
+ asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex)
+ {
+ Integer requestId = _sendAsyncRequests.remove(outAsync);
+ if(requestId != null)
+ {
+ if(requestId > 0)
+ {
+ _asyncRequests.remove(requestId);
+ }
+ if(outAsync.completed(ex))
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ _adapter.decDirectCount(); // invokeAll won't be called, decrease the direct count.
+ return;
+ }
+
+ if(outAsync instanceof OutgoingAsync)
+ {
+ OutgoingAsync o = (OutgoingAsync)outAsync;
+ assert(o != null);
+ for(java.util.Map.Entry<Integer, OutgoingAsyncBase> e : _asyncRequests.entrySet())
+ {
+ if(e.getValue() == o)
+ {
+ _asyncRequests.remove(e.getKey());
+ if(outAsync.completed(ex))
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void
+ sendResponse(int requestId, final Ice.OutputStream os, byte status, boolean amd)
+ {
+ OutgoingAsyncBase outAsync = null;
+ synchronized(this)
+ {
+ assert(_response);
+
+ if(_traceLevels.protocol >= 1)
+ {
+ fillInValue(os, 10, os.size());
+ }
+
+ // Adopt the OutputStream's buffer.
+ Ice.InputStream is = new Ice.InputStream(os.instance(), os.getEncoding(), os.getBuffer(), true);
+
+ is.pos(Protocol.replyHdr.length + 4);
+
+ if(_traceLevels.protocol >= 1)
+ {
+ TraceUtil.traceRecv(is, _logger, _traceLevels);
+ }
+
+ outAsync = _asyncRequests.remove(requestId);
+ if(outAsync != null && !outAsync.completed(is))
+ {
+ outAsync = null;
+ }
+ }
+
+ if(outAsync != null)
+ {
+ //
+ // If called from an AMD dispatch, invoke asynchronously
+ // the completion callback since this might be called from
+ // the user code.
+ //
+ if(amd)
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ else
+ {
+ outAsync.invokeCompleted();
+ }
+ }
+ _adapter.decDirectCount();
+ }
+
+ @Override
+ public void
+ sendNoResponse()
+ {
+ _adapter.decDirectCount();
+ }
+
+ @Override
+ public boolean
+ systemException(int requestId, Ice.SystemException ex, boolean amd)
+ {
+ handleException(requestId, ex, amd);
+ _adapter.decDirectCount();
+ return true;
+ }
+
+ @Override
+ public void
+ invokeException(int requestId, Ice.LocalException ex, int batchRequestNum, boolean amd)
+ {
+ handleException(requestId, ex, amd);
+ _adapter.decDirectCount();
+ }
+
+ @Override
+ public Reference
+ getReference()
+ {
+ return _reference;
+ }
+
+ @Override
+ public Ice.ConnectionI
+ getConnection()
+ {
+ return null;
+ }
+
+ int invokeAsyncRequest(OutgoingAsyncBase outAsync, int batchRequestNum, boolean sync)
+ {
+ //
+ // Increase the direct count to prevent the thread pool from being destroyed before
+ // invokeAll is called. This will also throw if the object adapter has been deactivated.
+ //
+ _adapter.incDirectCount();
+
+ int requestId = 0;
+ try
+ {
+ synchronized(this)
+ {
+ outAsync.cancelable(this); // This will throw if the request is canceled
+
+ if(_response)
+ {
+ requestId = ++_requestId;
+ _asyncRequests.put(requestId, outAsync);
+ }
+
+ _sendAsyncRequests.put(outAsync, requestId);
+ }
+ }
+ catch(Exception ex)
+ {
+ _adapter.decDirectCount();
+ throw ex;
+ }
+
+ outAsync.attachCollocatedObserver(_adapter, requestId);
+
+ if(!sync || !_response || _reference.getInstance().queueRequests() || _reference.getInvocationTimeout() > 0)
+ {
+ _adapter.getThreadPool().dispatch(new InvokeAllAsync(outAsync,
+ outAsync.getOs(),
+ requestId,
+ batchRequestNum));
+ }
+ else if(_dispatcher)
+ {
+ _adapter.getThreadPool().dispatchFromThisThread(new InvokeAllAsync(outAsync,
+ outAsync.getOs(),
+ requestId,
+ batchRequestNum));
+ }
+ else // Optimization: directly call invokeAll if there's no dispatcher.
+ {
+ if(sentAsync(outAsync))
+ {
+ invokeAll(outAsync.getOs(), requestId, batchRequestNum);
+ }
+ }
+ return AsyncStatus.Queued;
+ }
+
+ private boolean
+ sentAsync(final OutgoingAsyncBase outAsync)
+ {
+ synchronized(this)
+ {
+ if(_sendAsyncRequests.remove(outAsync) == null)
+ {
+ return false; // The request timed-out.
+ }
+
+ //
+ // This must be called within the synchronization to
+ // ensure completed(ex) can't be called concurrently if
+ // the request is canceled.
+ //
+ if(!outAsync.sent())
+ {
+ return true;
+ }
+ }
+
+ outAsync.invokeSent();
+ return true;
+ }
+
+ private void
+ invokeAll(Ice.OutputStream os, int requestId, int batchRequestNum)
+ {
+ if(_traceLevels.protocol >= 1)
+ {
+ fillInValue(os, 10, os.size());
+ if(requestId > 0)
+ {
+ fillInValue(os, Protocol.headerSize, requestId);
+ }
+ else if(batchRequestNum > 0)
+ {
+ fillInValue(os, Protocol.headerSize, batchRequestNum);
+ }
+ TraceUtil.traceSend(os, _logger, _traceLevels);
+ }
+
+ Ice.InputStream is = new Ice.InputStream(os.instance(), os.getEncoding(), os.getBuffer(), false);
+
+ if(batchRequestNum > 0)
+ {
+ is.pos(Protocol.requestBatchHdr.length);
+ }
+ else
+ {
+ is.pos(Protocol.requestHdr.length);
+ }
+
+ int invokeNum = batchRequestNum > 0 ? batchRequestNum : 1;
+ ServantManager servantManager = _adapter.getServantManager();
+ try
+ {
+ while(invokeNum > 0)
+ {
+ //
+ // Increase the direct count for the dispatch. We increase it again here for
+ // each dispatch. It's important for the direct count to be > 0 until the last
+ // collocated request response is sent to make sure the thread pool isn't
+ // destroyed before.
+ //
+ try
+ {
+ _adapter.incDirectCount();
+ }
+ catch(Ice.ObjectAdapterDeactivatedException ex)
+ {
+ handleException(requestId, ex, false);
+ break;
+ }
+
+ Incoming in = new Incoming(_reference.getInstance(), this, null, _adapter, _response, (byte)0,
+ requestId);
+ in.invoke(servantManager, is);
+ --invokeNum;
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ invokeException(requestId, ex, invokeNum, false); // Fatal invocation exception
+ }
+ catch(ServantError ex)
+ {
+ //
+ // ServantError is thrown when an Error has been raised by servant (or servant locator)
+ // code. We've already attempted to complete the invocation and send a response.
+ //
+ Throwable t = ex.getCause();
+ //
+ // Suppress AssertionError and OutOfMemoryError, rethrow everything else.
+ //
+ if(!(t instanceof java.lang.AssertionError || t instanceof java.lang.OutOfMemoryError))
+ {
+ throw (java.lang.Error)t;
+ }
+ }
+ catch(java.lang.Error ex)
+ {
+ //
+ // An Error was raised outside of servant code (i.e., by Ice code).
+ // Attempt to log the error and clean up. This may still fail
+ // depending on the severity of the error.
+ //
+ // Note that this does NOT send a response to the client.
+ //
+ Ice.UnknownException uex = new Ice.UnknownException(ex);
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ uex.unknown = sw.toString();
+ _logger.error(uex.unknown);
+ invokeException(requestId, uex, invokeNum, false);
+ //
+ // Suppress AssertionError and OutOfMemoryError, rethrow everything else.
+ //
+ if(!(ex instanceof java.lang.AssertionError || ex instanceof java.lang.OutOfMemoryError))
+ {
+ throw ex;
+ }
+ }
+
+ _adapter.decDirectCount();
+ }
+
+ private void
+ handleException(int requestId, Ice.Exception ex, boolean amd)
+ {
+ if(requestId == 0)
+ {
+ return; // Ignore exception for oneway messages.
+ }
+
+ OutgoingAsyncBase outAsync = null;
+ synchronized(this)
+ {
+ outAsync = _asyncRequests.remove(requestId);
+ if(outAsync != null && !outAsync.completed(ex))
+ {
+ outAsync = null;
+ }
+ }
+
+ if(outAsync != null)
+ {
+ //
+ // If called from an AMD dispatch, invoke asynchronously
+ // the completion callback since this might be called from
+ // the user code.
+ //
+ if(amd)
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ else
+ {
+ outAsync.invokeCompleted();
+ }
+ }
+ }
+
+ private void
+ fillInValue(Ice.OutputStream os, int pos, int value)
+ {
+ os.rewriteInt(value, pos);
+ }
+
+ private final Reference _reference;
+ private final boolean _dispatcher;
+ private final boolean _response;
+ private final Ice.ObjectAdapterI _adapter;
+ private final Ice.Logger _logger;
+ private final TraceLevels _traceLevels;
+
+ private int _requestId;
+
+ // A map of outstanding requests that can be canceled. A request
+ // can be canceled if it has an invocation timeout, or we support
+ // interrupts.
+ private java.util.Map<OutgoingAsyncBase, Integer> _sendAsyncRequests =
+ new java.util.HashMap<OutgoingAsyncBase, Integer>();
+
+ private java.util.Map<Integer, OutgoingAsyncBase> _asyncRequests =
+ new java.util.HashMap<Integer, OutgoingAsyncBase>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorFlushBatch.java b/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorFlushBatch.java
new file mode 100644
index 00000000000..309c9dd6a55
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorFlushBatch.java
@@ -0,0 +1,164 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.util.concurrent.Callable;
+
+public class CommunicatorFlushBatch extends IceInternal.AsyncResultI
+{
+ public static CommunicatorFlushBatch check(Ice.AsyncResult r, Ice.Communicator com, String operation)
+ {
+ check(r, operation);
+ if(!(r instanceof CommunicatorFlushBatch))
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ if(r.getCommunicator() != com)
+ {
+ throw new IllegalArgumentException("Communicator for call to end_" + operation +
+ " does not match communicator that was used to call corresponding " +
+ "begin_" + operation + " method");
+ }
+ return (CommunicatorFlushBatch)r;
+ }
+
+ public CommunicatorFlushBatch(Ice.Communicator communicator, Instance instance, String op, CallbackBase callback)
+ {
+ super(communicator, instance, op, callback);
+
+ _observer = ObserverHelper.get(instance, op);
+
+ //
+ // _useCount is initialized to 1 to prevent premature callbacks.
+ // The caller must invoke ready() after all flush requests have
+ // been initiated.
+ //
+ _useCount = 1;
+ }
+
+ public void flushConnection(final Ice.ConnectionI con)
+ {
+ class FlushBatch extends OutgoingAsyncBase
+ {
+ public FlushBatch()
+ {
+ super(CommunicatorFlushBatch.this.getCommunicator(),
+ CommunicatorFlushBatch.this._instance,
+ CommunicatorFlushBatch.this.getOperation(),
+ null);
+ }
+
+ @Override
+ public boolean sent()
+ {
+ if(_childObserver != null)
+ {
+ _childObserver.detach();
+ _childObserver = null;
+ }
+ doCheck(false);
+ return false;
+ }
+
+ // TODO: MJN: This is missing a test.
+ @Override
+ public boolean completed(Ice.Exception ex)
+ {
+ if(_childObserver != null)
+ {
+ _childObserver.failed(ex.ice_id());
+ _childObserver.detach();
+ _childObserver = null;
+ }
+ doCheck(false);
+ return false;
+ }
+
+ @Override
+ protected Ice.Instrumentation.InvocationObserver getObserver()
+ {
+ return CommunicatorFlushBatch.this._observer;
+ }
+ }
+
+ synchronized(this)
+ {
+ ++_useCount;
+ }
+
+ try
+ {
+ final FlushBatch flushBatch = new FlushBatch();
+ final int batchRequestNum = con.getBatchRequestQueue().swap(flushBatch.getOs());
+ if(batchRequestNum == 0)
+ {
+ flushBatch.sent();
+ }
+ else if(_instance.queueRequests())
+ {
+ _instance.getQueueExecutor().executeNoThrow(new Callable<Void>()
+ {
+ @Override
+ public Void call() throws RetryException
+ {
+ con.sendAsyncRequest(flushBatch, false, false, batchRequestNum);
+ return null;
+ }
+ });
+ }
+ else
+ {
+ con.sendAsyncRequest(flushBatch, false, false, batchRequestNum);
+ }
+ }
+ catch(RetryException ex)
+ {
+ doCheck(false);
+ throw ex.get();
+ }
+ catch(Ice.LocalException ex)
+ {
+ doCheck(false);
+ throw ex;
+ }
+ }
+
+ public void ready()
+ {
+ doCheck(true);
+ }
+
+ private void doCheck(boolean userThread)
+ {
+ synchronized(this)
+ {
+ assert(_useCount > 0);
+ if(--_useCount > 0)
+ {
+ return;
+ }
+ }
+
+ if(sent(true))
+ {
+ if(userThread)
+ {
+ _sentSynchronously = true;
+ invokeSent();
+ }
+ else
+ {
+ invokeSentAsync();
+ }
+ }
+ }
+
+ private int _useCount;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java b/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java
new file mode 100644
index 00000000000..095948736e3
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java
@@ -0,0 +1,840 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import IceMX.*;
+
+public class CommunicatorObserverI implements Ice.Instrumentation.CommunicatorObserver
+{
+ static void
+ addEndpointAttributes(MetricsHelper.AttributeResolver r, Class<?> cl)
+ throws Exception
+ {
+ r.add("endpoint", cl.getDeclaredMethod("getEndpoint"));
+
+ Class<?> cli = Ice.EndpointInfo.class;
+ r.add("endpointType", cl.getDeclaredMethod("getEndpointInfo"), cli.getDeclaredMethod("type"));
+ r.add("endpointIsDatagram", cl.getDeclaredMethod("getEndpointInfo"), cli.getDeclaredMethod("datagram"));
+ r.add("endpointIsSecure", cl.getDeclaredMethod("getEndpointInfo"), cli.getDeclaredMethod("secure"));
+ r.add("endpointTimeout", cl.getDeclaredMethod("getEndpointInfo"), cli.getDeclaredField("timeout"));
+ r.add("endpointCompress", cl.getDeclaredMethod("getEndpointInfo"), cli.getDeclaredField("compress"));
+
+ cli = Ice.IPEndpointInfo.class;
+ r.add("endpointHost", cl.getDeclaredMethod("getEndpointInfo"), cli.getDeclaredField("host"));
+ r.add("endpointPort", cl.getDeclaredMethod("getEndpointInfo"), cli.getDeclaredField("port"));
+ }
+
+ static void
+ addConnectionAttributes(MetricsHelper.AttributeResolver r, Class<?> cl)
+ throws Exception
+ {
+ Class<?> cli = Ice.ConnectionInfo.class;
+ r.add("incoming", cl.getDeclaredMethod("getConnectionInfo"), cli.getDeclaredField("incoming"));
+ r.add("adapterName", cl.getDeclaredMethod("getConnectionInfo"), cli.getDeclaredField("adapterName"));
+ r.add("connectionId", cl.getDeclaredMethod("getConnectionInfo"), cli.getDeclaredField("connectionId"));
+
+ cli = Ice.IPConnectionInfo.class;
+ r.add("localHost", cl.getDeclaredMethod("getConnectionInfo"), cli.getDeclaredField("localAddress"));
+ r.add("localPort", cl.getDeclaredMethod("getConnectionInfo"), cli.getDeclaredField("localPort"));
+ r.add("remoteHost", cl.getDeclaredMethod("getConnectionInfo"), cli.getDeclaredField("remoteAddress"));
+ r.add("remotePort", cl.getDeclaredMethod("getConnectionInfo"), cli.getDeclaredField("remotePort"));
+
+ cli = Ice.UDPConnectionInfo.class;
+ r.add("mcastHost", cl.getDeclaredMethod("getConnectionInfo"), cli.getDeclaredField("mcastAddress"));
+ r.add("mcastPort", cl.getDeclaredMethod("getConnectionInfo"), cli.getDeclaredField("mcastPort"));
+
+ addEndpointAttributes(r, cl);
+ }
+
+ static public class ConnectionHelper extends MetricsHelper<ConnectionMetrics>
+ {
+ static private AttributeResolver _attributes = new AttributeResolver()
+ {
+ {
+ try
+ {
+ add("parent", ConnectionHelper.class.getDeclaredMethod("getParent"));
+ add("id", ConnectionHelper.class.getDeclaredMethod("getId"));
+ add("state", ConnectionHelper.class.getDeclaredMethod("getState"));
+ addConnectionAttributes(this, ConnectionHelper.class);
+ }
+ catch(Exception ex)
+ {
+ ex.printStackTrace();
+ assert(false);
+ }
+ }
+ };
+
+ ConnectionHelper(Ice.ConnectionInfo con, Ice.Endpoint endpt, Ice.Instrumentation.ConnectionState state)
+ {
+ super(_attributes);
+ _connectionInfo = con;
+ _endpoint = endpt;
+ _state = state;
+ }
+
+ public String
+ getId()
+ {
+ if(_id == null)
+ {
+ StringBuilder os = new StringBuilder();
+ Ice.IPConnectionInfo info = getIPConnectionInfo();
+ if(info != null)
+ {
+ os.append(info.localAddress).append(':').append(info.localPort);
+ os.append(" -> ");
+ os.append(info.remoteAddress).append(':').append(info.remotePort);
+ }
+ else
+ {
+ os.append("connection-").append(_connectionInfo);
+ }
+ if(!_connectionInfo.connectionId.isEmpty())
+ {
+ os.append(" [").append(_connectionInfo.connectionId).append("]");
+ }
+ _id = os.toString();
+ }
+ return _id;
+ }
+
+ public String
+ getState()
+ {
+ switch(_state)
+ {
+ case ConnectionStateValidating:
+ return "validating";
+ case ConnectionStateHolding:
+ return "holding";
+ case ConnectionStateActive:
+ return "active";
+ case ConnectionStateClosing:
+ return "closing";
+ case ConnectionStateClosed:
+ return "closed";
+ default:
+ assert(false);
+ return "";
+ }
+ }
+
+ public String
+ getParent()
+ {
+ if(_connectionInfo.adapterName != null && !_connectionInfo.adapterName.isEmpty())
+ {
+ return _connectionInfo.adapterName;
+ }
+ else
+ {
+ return "Communicator";
+ }
+ }
+
+ public Ice.ConnectionInfo
+ getConnectionInfo()
+ {
+ return _connectionInfo;
+ }
+
+ public Ice.Endpoint
+ getEndpoint()
+ {
+ return _endpoint;
+ }
+
+ public Ice.EndpointInfo
+ getEndpointInfo()
+ {
+ if(_endpointInfo == null)
+ {
+ _endpointInfo = _endpoint.getInfo();
+ }
+ return _endpointInfo;
+ }
+
+ private Ice.IPConnectionInfo
+ getIPConnectionInfo()
+ {
+ for(Ice.ConnectionInfo p = _connectionInfo; p != null; p = p.underlying)
+ {
+ if(p instanceof Ice.IPConnectionInfo)
+ {
+ return (Ice.IPConnectionInfo)p;
+ }
+ }
+ return null;
+ }
+
+ private final Ice.ConnectionInfo _connectionInfo;
+ private final Ice.Endpoint _endpoint;
+ private final Ice.Instrumentation.ConnectionState _state;
+ private String _id;
+ private Ice.EndpointInfo _endpointInfo;
+ }
+
+ static public final class DispatchHelper extends MetricsHelper<DispatchMetrics>
+ {
+ static private final AttributeResolver _attributes = new AttributeResolver()
+ {
+ {
+ try
+ {
+ Class<?> cl = DispatchHelper.class;
+ add("parent", cl.getDeclaredMethod("getParent"));
+ add("id", cl.getDeclaredMethod("getId"));
+
+ addConnectionAttributes(this, cl);
+
+ Class<?> clc = Ice.Current.class;
+ add("operation", cl.getDeclaredMethod("getCurrent"), clc.getDeclaredField("operation"));
+ add("identity", cl.getDeclaredMethod("getIdentity"));
+ add("facet", cl.getDeclaredMethod("getCurrent"), clc.getDeclaredField("facet"));
+ add("requestId", cl.getDeclaredMethod("getCurrent"), clc.getDeclaredField("requestId"));
+ add("mode", cl.getDeclaredMethod("getMode"));
+ }
+ catch(Exception ex)
+ {
+ ex.printStackTrace();
+ assert(false);
+ }
+ }
+ };
+
+ DispatchHelper(Ice.Current current, int size)
+ {
+ super(_attributes);
+ _current = current;
+ _size = size;
+ }
+
+ @Override
+ public void
+ initMetrics(DispatchMetrics v)
+ {
+ v.size += _size;
+ }
+
+ @Override
+ protected String
+ defaultResolve(String attribute)
+ {
+ if(attribute.indexOf("context.", 0) == 0)
+ {
+ String v = _current.ctx.get(attribute.substring(8));
+ if(v != null)
+ {
+ return v;
+ }
+ }
+ throw new IllegalArgumentException(attribute);
+ }
+
+ public String
+ getMode()
+ {
+ return _current.requestId == 0 ? "oneway" : "twoway";
+ }
+
+ public String
+ getId()
+ {
+ if(_id == null)
+ {
+ StringBuilder os = new StringBuilder();
+ if(_current.id.category != null && !_current.id.category.isEmpty())
+ {
+ os.append(_current.id.category).append('/');
+ }
+ os.append(_current.id.name).append(" [").append(_current.operation).append(']');
+ _id = os.toString();
+ }
+ return _id;
+ }
+
+ public int
+ getRequestId()
+ {
+ return _current.requestId;
+ }
+
+ public String
+ getParent()
+ {
+ return _current.adapter.getName();
+ }
+
+ public Ice.ConnectionInfo
+ getConnectionInfo()
+ {
+ if(_current.con != null)
+ {
+ return _current.con.getInfo();
+ }
+ return null;
+ }
+
+ public Ice.Endpoint
+ getEndpoint()
+ {
+ if(_current.con != null)
+ {
+ return _current.con.getEndpoint();
+ }
+ return null;
+ }
+
+ public Ice.Connection
+ getConnection()
+ {
+ return _current.con;
+ }
+
+ public Ice.EndpointInfo
+ getEndpointInfo()
+ {
+ if(_current.con != null && _endpointInfo == null)
+ {
+ _endpointInfo = _current.con.getEndpoint().getInfo();
+ }
+ return _endpointInfo;
+ }
+
+ public Ice.Current
+ getCurrent()
+ {
+ return _current;
+ }
+
+ public String
+ getIdentity()
+ {
+ return Ice.Util.identityToString(_current.id);
+ }
+
+ final private Ice.Current _current;
+ final private int _size;
+ private String _id;
+ private Ice.EndpointInfo _endpointInfo;
+ }
+
+ static public final class InvocationHelper extends MetricsHelper<InvocationMetrics>
+ {
+ static private final AttributeResolver _attributes = new AttributeResolver()
+ {
+ {
+ try
+ {
+ Class<?> cl = InvocationHelper.class;
+ add("parent", cl.getDeclaredMethod("getParent"));
+ add("id", cl.getDeclaredMethod("getId"));
+
+ add("operation", cl.getDeclaredMethod("getOperation"));
+ add("identity", cl.getDeclaredMethod("getIdentity"));
+
+ Class<?> cli = Ice.ObjectPrx.class;
+ add("facet", cl.getDeclaredMethod("getProxy"), cli.getDeclaredMethod("ice_getFacet"));
+ add("encoding", cl.getDeclaredMethod("getEncodingVersion"));
+ add("mode", cl.getDeclaredMethod("getMode"));
+ add("proxy", cl.getDeclaredMethod("getProxy"));
+ }
+ catch(Exception ex)
+ {
+ ex.printStackTrace();
+ assert(false);
+ }
+ }
+ };
+
+ InvocationHelper(Ice.ObjectPrx proxy, String op, java.util.Map<String, String> ctx)
+ {
+ super(_attributes);
+ _proxy = proxy;
+ _operation = op;
+ _context = ctx;
+ }
+
+ @Override
+ protected String
+ defaultResolve(String attribute)
+ {
+ if(attribute.indexOf("context.", 0) == 0)
+ {
+ String v = _context.get(attribute.substring(8));
+ if(v != null)
+ {
+ return v;
+ }
+ }
+ throw new IllegalArgumentException(attribute);
+ }
+
+ public String
+ getMode()
+ {
+ if(_proxy == null)
+ {
+ throw new IllegalArgumentException("mode");
+ }
+
+ if(_proxy.ice_isTwoway())
+ {
+ return "twoway";
+ }
+ else if(_proxy.ice_isOneway())
+ {
+ return "oneway";
+ }
+ else if(_proxy.ice_isBatchOneway())
+ {
+ return "batch-oneway";
+ }
+ else if(_proxy.ice_isDatagram())
+ {
+ return "datagram";
+ }
+ else if(_proxy.ice_isBatchDatagram())
+ {
+ return "batch-datagram";
+ }
+ else
+ {
+ throw new IllegalArgumentException("mode");
+ }
+ }
+
+ public String
+ getId()
+ {
+ if(_id == null)
+ {
+ if(_proxy != null)
+ {
+ StringBuilder os = new StringBuilder();
+ try
+ {
+ os.append(_proxy.ice_endpoints(emptyEndpoints)).append(" [").append(_operation).append(']');
+ }
+ catch(Exception ex)
+ {
+ // Either a fixed proxy or the communicator is destroyed.
+ os.append(Ice.Util.identityToString(_proxy.ice_getIdentity()));
+ os.append(" [").append(_operation).append(']');
+ }
+ _id = os.toString();
+ }
+ else
+ {
+ _id = _operation;
+ }
+ }
+ return _id;
+ }
+
+ public String
+ getParent()
+ {
+ return "Communicator";
+ }
+
+ public Ice.ObjectPrx
+ getProxy()
+ {
+ return _proxy;
+ }
+
+ public String
+ getIdentity()
+ {
+ if(_proxy != null)
+ {
+ return Ice.Util.identityToString(_proxy.ice_getIdentity());
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ public String
+ getOperation()
+ {
+ return _operation;
+ }
+
+ public String
+ getEncodingVersion()
+ {
+ return Ice.Util.encodingVersionToString(_proxy.ice_getEncodingVersion());
+ }
+
+ final private Ice.ObjectPrx _proxy;
+ final private String _operation;
+ final private java.util.Map<String, String> _context;
+ private String _id;
+
+ static final private Ice.Endpoint[] emptyEndpoints = new Ice.Endpoint[0];
+ }
+
+ static public final class ThreadHelper extends MetricsHelper<ThreadMetrics>
+ {
+ static private final AttributeResolver _attributes = new AttributeResolver()
+ {
+ {
+ try
+ {
+ add("parent", ThreadHelper.class.getDeclaredField("_parent"));
+ add("id", ThreadHelper.class.getDeclaredField("_id"));
+ }
+ catch(Exception ex)
+ {
+ assert(false);
+ }
+ }
+ };
+
+ ThreadHelper(String parent, String id, Ice.Instrumentation.ThreadState state)
+ {
+ super(_attributes);
+ _parent = parent;
+ _id = id;
+ _state = state;
+ }
+
+ @Override
+ public void
+ initMetrics(ThreadMetrics v)
+ {
+ switch(_state)
+ {
+ case ThreadStateInUseForIO:
+ ++v.inUseForIO;
+ break;
+ case ThreadStateInUseForUser:
+ ++v.inUseForUser;
+ break;
+ case ThreadStateInUseForOther:
+ ++v.inUseForOther;
+ break;
+ default:
+ break;
+ }
+ }
+
+ final public String _parent;
+ final public String _id;
+ final private Ice.Instrumentation.ThreadState _state;
+ }
+
+ static public final class EndpointHelper extends MetricsHelper<Metrics>
+ {
+ static private final AttributeResolver _attributes = new AttributeResolver()
+ {
+ {
+ try
+ {
+ add("parent", EndpointHelper.class.getDeclaredMethod("getParent"));
+ add("id", EndpointHelper.class.getDeclaredMethod("getId"));
+ addEndpointAttributes(this, EndpointHelper.class);
+ }
+ catch(Exception ex)
+ {
+ ex.printStackTrace();
+ assert(false);
+ }
+ }
+ };
+
+ EndpointHelper(Ice.Endpoint endpt, String id)
+ {
+ super(_attributes);
+ _endpoint = endpt;
+ _id = id;
+ }
+
+ EndpointHelper(Ice.Endpoint endpt)
+ {
+ super(_attributes);
+ _endpoint = endpt;
+ }
+
+ public Ice.EndpointInfo
+ getEndpointInfo()
+ {
+ if(_endpointInfo == null)
+ {
+ _endpointInfo = _endpoint.getInfo();
+ }
+ return _endpointInfo;
+ }
+
+ public String
+ getParent()
+ {
+ return "Communicator";
+ }
+
+ public String
+ getId()
+ {
+ if(_id == null)
+ {
+ _id = _endpoint.toString();
+ }
+ return _id;
+ }
+
+ public String
+ getEndpoint()
+ {
+ return _endpoint.toString();
+ }
+
+ final private Ice.Endpoint _endpoint;
+ private String _id;
+ private Ice.EndpointInfo _endpointInfo;
+ }
+
+ public
+ CommunicatorObserverI(Ice.InitializationData initData)
+ {
+ _metrics = new MetricsAdminI(initData.properties, initData.logger);
+ _delegate = initData.observer;
+
+ _connections = new ObserverFactoryWithDelegate<ConnectionMetrics, ConnectionObserverI,
+ Ice.Instrumentation.ConnectionObserver>(_metrics, "Connection", ConnectionMetrics.class);
+ _dispatch = new ObserverFactoryWithDelegate<DispatchMetrics, DispatchObserverI,
+ Ice.Instrumentation.DispatchObserver>(_metrics, "Dispatch", DispatchMetrics.class);
+ _invocations = new ObserverFactoryWithDelegate<InvocationMetrics, InvocationObserverI,
+ Ice.Instrumentation.InvocationObserver>(_metrics, "Invocation", InvocationMetrics.class);
+ _threads = new ObserverFactoryWithDelegate<ThreadMetrics, ThreadObserverI,
+ Ice.Instrumentation.ThreadObserver>(_metrics, "Thread", ThreadMetrics.class);
+ _connects = new ObserverFactoryWithDelegate<Metrics, ObserverWithDelegateI,
+ Ice.Instrumentation.Observer>(_metrics, "ConnectionEstablishment", Metrics.class);
+ _endpointLookups = new ObserverFactoryWithDelegate<Metrics, ObserverWithDelegateI,
+ Ice.Instrumentation.Observer>(_metrics, "EndpointLookup", Metrics.class);
+
+ try
+ {
+ _invocations.registerSubMap("Remote", RemoteMetrics.class,
+ InvocationMetrics.class.getDeclaredField("remotes"));
+ _invocations.registerSubMap("Collocated", CollocatedMetrics.class,
+ InvocationMetrics.class.getDeclaredField("collocated"));
+ }
+ catch(Exception ex)
+ {
+ assert(false);
+ }
+ }
+
+ @Override
+ public Ice.Instrumentation.Observer
+ getConnectionEstablishmentObserver(Ice.Endpoint endpt, String connector)
+ {
+ if(_connects.isEnabled())
+ {
+ try
+ {
+ Ice.Instrumentation.Observer delegate = null;
+ if(_delegate != null)
+ {
+ delegate = _delegate.getConnectionEstablishmentObserver(endpt, connector);
+ }
+ return _connects.getObserver(new EndpointHelper(endpt, connector), ObserverWithDelegateI.class,
+ delegate);
+ }
+ catch(Exception ex)
+ {
+ _metrics.getLogger().error("unexpected exception trying to obtain observer:\n" + Ex.toString(ex));
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Ice.Instrumentation.Observer
+ getEndpointLookupObserver(Ice.Endpoint endpt)
+ {
+ if(_endpointLookups.isEnabled())
+ {
+ try
+ {
+ Ice.Instrumentation.Observer delegate = null;
+ if(_delegate != null)
+ {
+ delegate = _delegate.getEndpointLookupObserver(endpt);
+ }
+ return _endpointLookups.getObserver(new EndpointHelper(endpt), ObserverWithDelegateI.class, delegate);
+ }
+ catch(Exception ex)
+ {
+ _metrics.getLogger().error("unexpected exception trying to obtain observer:\n" + Ex.toString(ex));
+ }
+
+ }
+ return null;
+ }
+
+ @Override
+ public Ice.Instrumentation.ConnectionObserver
+ getConnectionObserver(Ice.ConnectionInfo c, Ice.Endpoint e, Ice.Instrumentation.ConnectionState s,
+ Ice.Instrumentation.ConnectionObserver observer)
+ {
+ if(_connections.isEnabled())
+ {
+ try
+ {
+ Ice.Instrumentation.ConnectionObserver delegate = null;
+ ConnectionObserverI o = observer instanceof ConnectionObserverI ? (ConnectionObserverI)observer : null;
+ if(_delegate != null)
+ {
+ delegate = _delegate.getConnectionObserver(c, e, s, o != null ? o.getDelegate() : observer);
+ }
+ return _connections.getObserver(new ConnectionHelper(c, e, s), o, ConnectionObserverI.class, delegate);
+ }
+ catch(Exception ex)
+ {
+ _metrics.getLogger().error("unexpected exception trying to obtain observer:\n" + Ex.toString(ex));
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Ice.Instrumentation.ThreadObserver
+ getThreadObserver(String parent, String id, Ice.Instrumentation.ThreadState s,
+ Ice.Instrumentation.ThreadObserver observer)
+ {
+ if(_threads.isEnabled())
+ {
+ try
+ {
+ Ice.Instrumentation.ThreadObserver delegate = null;
+ ThreadObserverI o = observer instanceof ThreadObserverI ? (ThreadObserverI)observer : null;
+ if(_delegate != null)
+ {
+ delegate = _delegate.getThreadObserver(parent, id, s, o != null ? o.getDelegate() : observer);
+ }
+ return _threads.getObserver(new ThreadHelper(parent, id, s), o, ThreadObserverI.class, delegate);
+ }
+ catch(Exception ex)
+ {
+ _metrics.getLogger().error("unexpected exception trying to obtain observer:\n" + Ex.toString(ex));
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Ice.Instrumentation.InvocationObserver
+ getInvocationObserver(Ice.ObjectPrx prx, String operation, java.util.Map<java.lang.String, java.lang.String> ctx)
+ {
+ if(_invocations.isEnabled())
+ {
+ try
+ {
+ Ice.Instrumentation.InvocationObserver delegate = null;
+ if(_delegate != null)
+ {
+ delegate = _delegate.getInvocationObserver(prx, operation, ctx);
+ }
+ return _invocations.getObserver(new InvocationHelper(prx, operation, ctx),
+ InvocationObserverI.class,
+ delegate);
+ }
+ catch(Exception ex)
+ {
+ _metrics.getLogger().error("unexpected exception trying to obtain observer:\n" + Ex.toString(ex));
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Ice.Instrumentation.DispatchObserver
+ getDispatchObserver(Ice.Current c, int size)
+ {
+ if(_dispatch.isEnabled())
+ {
+ try
+ {
+ Ice.Instrumentation.DispatchObserver delegate = null;
+ if(_delegate != null)
+ {
+ delegate = _delegate.getDispatchObserver(c, size);
+ }
+ return _dispatch.getObserver(new DispatchHelper(c, size), DispatchObserverI.class, delegate);
+ }
+ catch(Exception ex)
+ {
+ _metrics.getLogger().error("unexpected exception trying to obtain observer:\n" + Ex.toString(ex));
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void
+ setObserverUpdater(final Ice.Instrumentation.ObserverUpdater updater)
+ {
+ if(updater == null)
+ {
+ _connections.setUpdater(null);
+ _threads.setUpdater(null);
+ }
+ else
+ {
+ _connections.setUpdater(new Runnable() {
+ @Override
+ public void
+ run()
+ {
+ updater.updateConnectionObservers();
+ }
+ });
+ _threads.setUpdater(new Runnable() {
+ @Override
+ public void
+ run()
+ {
+ updater.updateThreadObservers();
+ }
+ });
+ }
+
+ if(_delegate != null)
+ {
+ _delegate.setObserverUpdater(updater);
+ }
+ }
+
+ public IceInternal.MetricsAdminI getFacet()
+ {
+ return _metrics;
+ }
+
+ final private IceInternal.MetricsAdminI _metrics;
+ final private Ice.Instrumentation.CommunicatorObserver _delegate;
+ final private ObserverFactoryWithDelegate<ConnectionMetrics, ConnectionObserverI,
+ Ice.Instrumentation.ConnectionObserver> _connections;
+ final private ObserverFactoryWithDelegate<DispatchMetrics, DispatchObserverI,
+ Ice.Instrumentation.DispatchObserver> _dispatch;
+ final private ObserverFactoryWithDelegate<InvocationMetrics, InvocationObserverI,
+ Ice.Instrumentation.InvocationObserver> _invocations;
+ final private ObserverFactoryWithDelegate<ThreadMetrics, ThreadObserverI,
+ Ice.Instrumentation.ThreadObserver> _threads;
+ final private ObserverFactoryWithDelegate<Metrics, ObserverWithDelegateI,
+ Ice.Instrumentation.Observer> _connects;
+ final private ObserverFactoryWithDelegate<Metrics, ObserverWithDelegateI,
+ Ice.Instrumentation.Observer> _endpointLookups;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ConnectRequestHandler.java b/java-compat/src/Ice/src/main/java/IceInternal/ConnectRequestHandler.java
new file mode 100644
index 00000000000..4f50988102a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ConnectRequestHandler.java
@@ -0,0 +1,385 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import Ice.ConnectionI;
+
+import java.util.concurrent.Callable;
+
+public class ConnectRequestHandler
+ implements RequestHandler, Reference.GetConnectionCallback, RouterInfo.AddProxyCallback
+{
+ synchronized public RequestHandler
+ connect(Ice.ObjectPrxHelperBase proxy)
+ {
+ if(!initialized())
+ {
+ _proxies.add(proxy);
+ }
+ return _requestHandler;
+ }
+
+ @Override
+ public RequestHandler
+ update(RequestHandler previousHandler, RequestHandler newHandler)
+ {
+ return previousHandler == this ? newHandler : this;
+ }
+
+ @Override
+ public int
+ sendAsyncRequest(ProxyOutgoingAsyncBase out)
+ throws RetryException
+ {
+ synchronized(this)
+ {
+ if(!_initialized)
+ {
+ out.cancelable(this); // This will throw if the request is canceled
+ }
+
+ if(!initialized())
+ {
+ _requests.add(out);
+ return AsyncStatus.Queued;
+ }
+ }
+ return out.invokeRemote(_connection, _compress, _response);
+ }
+
+ @Override
+ public void
+ asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex)
+ {
+ synchronized(this)
+ {
+ if(_exception != null)
+ {
+ return; // The request has been notified of a failure already.
+ }
+
+ if(!initialized())
+ {
+ java.util.Iterator<ProxyOutgoingAsyncBase> it = _requests.iterator();
+ while(it.hasNext())
+ {
+ OutgoingAsyncBase request = it.next();
+ if(request == outAsync)
+ {
+ it.remove();
+ if(outAsync.completed(ex))
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ return;
+ }
+ }
+ assert(false); // The request has to be queued if it timed out and we're not initialized yet.
+ }
+ }
+ _connection.asyncRequestCanceled(outAsync, ex);
+ }
+
+ @Override
+ public Reference
+ getReference()
+ {
+ return _reference;
+ }
+
+ @Override
+ synchronized public ConnectionI
+ getConnection()
+ {
+ if(_exception != null)
+ {
+ throw (Ice.LocalException)_exception.fillInStackTrace();
+ }
+ else
+ {
+ return _connection;
+ }
+ }
+
+ //
+ // Implementation of Reference.GetConnectionCallback
+ //
+
+ @Override
+ public void
+ setConnection(Ice.ConnectionI connection, boolean compress)
+ {
+ synchronized(this)
+ {
+ assert(_exception == null && _connection == null);
+ _connection = connection;
+ _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.
+ //
+ RouterInfo ri = _reference.getRouterInfo();
+ if(ri != null && !ri.addProxy(_proxy, this))
+ {
+ return; // The request handler will be initialized once addProxy returns.
+ }
+
+ //
+ // We can now send the queued requests.
+ //
+ flushRequests();
+ }
+
+ @Override
+ public synchronized void
+ setException(final Ice.LocalException ex)
+ {
+ assert(!_initialized && _exception == null);
+ _exception = ex;
+ _proxies.clear();
+ _proxy = null; // Break cyclic reference count.
+
+ //
+ // NOTE: remove the request handler *before* notifying the
+ // requests that the connection failed. It's important to ensure
+ // that future invocations will obtain a new connect request
+ // handler once invocations are notified.
+ //
+ try
+ {
+ _reference.getInstance().requestHandlerFactory().removeRequestHandler(_reference, this);
+ }
+ catch(Ice.CommunicatorDestroyedException exc)
+ {
+ // Ignore
+ }
+
+ for(OutgoingAsyncBase outAsync : _requests)
+ {
+ if(outAsync.completed(_exception))
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ }
+ _requests.clear();
+ notifyAll();
+ }
+
+ //
+ // Implementation of RouterInfo.AddProxyCallback
+ //
+ @Override
+ public void
+ addedProxy()
+ {
+ //
+ // The proxy was added to the router info, we're now ready to send the
+ // queued requests.
+ //
+ flushRequests();
+ }
+
+ public
+ ConnectRequestHandler(Reference ref, Ice.ObjectPrxHelperBase proxy)
+ {
+ _reference = ref;
+ _response = _reference.getMode() == Reference.ModeTwoway;
+ _proxy = (Ice.ObjectPrxHelperBase)proxy;
+ _initialized = false;
+ _flushing = false;
+
+ if(_reference.getInstance().queueRequests())
+ {
+ _requestHandler = new QueueRequestHandler(_reference.getInstance(), this);
+ }
+ else
+ {
+ _requestHandler = this;
+ }
+ }
+
+ private boolean
+ initialized()
+ {
+ // Must be called with the mutex locked.
+
+ if(_initialized)
+ {
+ assert(_connection != null);
+ return true;
+ }
+ else
+ {
+ //
+ // This is similar to a mutex lock in that the flag is
+ // only true for a short period of time.
+ //
+ boolean interrupted = false;
+ while(_flushing && _exception == null)
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ interrupted = true;
+ }
+ }
+ //
+ // Restore the interrupted status.
+ //
+ if(interrupted)
+ {
+ Thread.currentThread().interrupt();
+ }
+
+ if(_exception != null)
+ {
+ if(_connection != null)
+ {
+ //
+ // Only throw if the connection didn't get established. If
+ // it died after being established, we allow the caller to
+ // retry the connection establishment by not throwing here
+ // (the connection will throw RetryException).
+ //
+ return true;
+ }
+ throw (Ice.LocalException)_exception.fillInStackTrace();
+ }
+ else
+ {
+ return _initialized;
+ }
+ }
+ }
+
+ private void
+ flushRequests()
+ {
+ if(_reference.getInstance().queueRequests())
+ {
+ _reference.getInstance().getQueueExecutor().executeNoThrow(new Callable<Void>()
+ {
+ @Override
+ public Void call() throws Exception
+ {
+ flushRequestsImpl();
+ return null;
+ }
+ });
+ }
+ else
+ {
+ flushRequestsImpl();
+ }
+ }
+
+ private void
+ flushRequestsImpl()
+ {
+ synchronized(this)
+ {
+ assert(_connection != null && !_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.
+ //
+ _flushing = true;
+ }
+
+ Ice.LocalException exception = null;
+ for(ProxyOutgoingAsyncBase outAsync : _requests)
+ {
+ try
+ {
+ if((outAsync.invokeRemote(_connection, _compress, _response) & AsyncStatus.InvokeSentCallback) > 0)
+ {
+ outAsync.invokeSentAsync();
+ }
+ }
+ catch(RetryException ex)
+ {
+ exception = ex.get();
+
+ // Remove the request handler before retrying.
+ _reference.getInstance().requestHandlerFactory().removeRequestHandler(_reference, this);
+ outAsync.retryException(ex.get());
+ }
+ catch(Ice.LocalException ex)
+ {
+ exception = ex;
+ if(outAsync.completed(ex))
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ }
+ }
+ _requests.clear();
+
+ //
+ // If we aren't caching the connection, don't bother creating a
+ // connection request handler. Otherwise, update the proxies
+ // request handler to use the more efficient connection request
+ // handler.
+ //
+ if(_reference.getCacheConnection() && exception == null)
+ {
+ RequestHandler previous = _requestHandler;
+ _requestHandler = new ConnectionRequestHandler(_reference, _connection, _compress);
+ if(_reference.getInstance().queueRequests())
+ {
+ _requestHandler = new QueueRequestHandler(_reference.getInstance(), _requestHandler);
+ }
+ for(Ice.ObjectPrxHelperBase proxy : _proxies)
+ {
+ proxy.__updateRequestHandler(previous, _requestHandler);
+ }
+ }
+
+ synchronized(this)
+ {
+ assert(!_initialized);
+ _exception = exception;
+ _initialized = _exception == null;
+ _flushing = false;
+
+ //
+ // Only remove once all the requests are flushed to
+ // guarantee serialization.
+ //
+ _reference.getInstance().requestHandlerFactory().removeRequestHandler(_reference, this);
+
+ _proxies.clear();
+ _proxy = null; // Break cyclic reference count.
+ notifyAll();
+ }
+ }
+
+ private final Reference _reference;
+ private boolean _response;
+
+ private Ice.ObjectPrxHelperBase _proxy;
+ private java.util.Set<Ice.ObjectPrxHelperBase> _proxies = new java.util.HashSet<Ice.ObjectPrxHelperBase>();
+
+ private Ice.ConnectionI _connection;
+ private boolean _compress;
+ private Ice.LocalException _exception;
+ private boolean _initialized;
+ private boolean _flushing;
+
+ private java.util.List<ProxyOutgoingAsyncBase> _requests = new java.util.LinkedList<ProxyOutgoingAsyncBase>();
+ private RequestHandler _requestHandler;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ConnectionACMMonitor.java b/java-compat/src/Ice/src/main/java/IceInternal/ConnectionACMMonitor.java
new file mode 100644
index 00000000000..7e4b1427c1f
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ConnectionACMMonitor.java
@@ -0,0 +1,126 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+class ConnectionACMMonitor implements ACMMonitor
+{
+ ConnectionACMMonitor(FactoryACMMonitor parent, java.util.concurrent.ScheduledExecutorService timer,
+ ACMConfig config)
+ {
+ _parent = parent;
+ _timer = timer;
+ _config = config;
+ }
+
+ @Override
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_connection == null);
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ @Override
+ public synchronized void
+ add(Ice.ConnectionI connection)
+ {
+ assert(_connection == null);
+ _connection = connection;
+ if(_config.timeout > 0)
+ {
+ _future = _timer.scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run()
+ {
+ monitorConnection();
+ }
+ },
+ _config.timeout / 2, _config.timeout / 2, java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+ }
+
+ @Override
+ public synchronized void
+ remove(Ice.ConnectionI connection)
+ {
+ assert(_connection == connection);
+ _connection = null;
+ if(_config.timeout > 0)
+ {
+ _future.cancel(false);
+ _future = null;
+ }
+ }
+
+ @Override
+ public void
+ reap(Ice.ConnectionI connection)
+ {
+ _parent.reap(connection);
+ }
+
+ @Override
+ public ACMMonitor
+ acm(Ice.IntOptional timeout, Ice.Optional<Ice.ACMClose> close, Ice.Optional<Ice.ACMHeartbeat> heartbeat)
+ {
+ return _parent.acm(timeout, close, heartbeat);
+ }
+
+ @Override
+ public Ice.ACM
+ getACM()
+ {
+ Ice.ACM acm = new Ice.ACM();
+ acm.timeout = _config.timeout / 1000;
+ acm.close = _config.close;
+ acm.heartbeat = _config.heartbeat;
+ return acm;
+ }
+
+ private void
+ monitorConnection()
+ {
+ Ice.ConnectionI connection;
+ synchronized(this)
+ {
+ if(_connection == null)
+ {
+ return;
+ }
+ connection = _connection;
+ }
+
+ try
+ {
+ connection.monitor(Time.currentMonotonicTimeMillis(), _config);
+ }
+ catch(Exception ex)
+ {
+ _parent.handleException(ex);
+ }
+ }
+
+ final private FactoryACMMonitor _parent;
+ final private java.util.concurrent.ScheduledExecutorService _timer;
+ private java.util.concurrent.Future<?> _future;
+ final private ACMConfig _config;
+
+ private Ice.ConnectionI _connection;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ConnectionFlushBatch.java b/java-compat/src/Ice/src/main/java/IceInternal/ConnectionFlushBatch.java
new file mode 100644
index 00000000000..7824d3154c1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ConnectionFlushBatch.java
@@ -0,0 +1,102 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.util.concurrent.Callable;
+
+public class ConnectionFlushBatch extends OutgoingAsyncBase
+{
+ public static ConnectionFlushBatch check(Ice.AsyncResult r, Ice.Connection con, String operation)
+ {
+ check(r, operation);
+ if(!(r instanceof ConnectionFlushBatch))
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ if(r.getConnection() != con)
+ {
+ throw new IllegalArgumentException("Connection for call to end_" + operation +
+ " does not match connection that was used to call corresponding " +
+ "begin_" + operation + " method");
+ }
+ return (ConnectionFlushBatch)r;
+ }
+
+ public ConnectionFlushBatch(Ice.ConnectionI con, Ice.Communicator communicator, Instance instance,
+ String operation, CallbackBase callback)
+ {
+ super(communicator, instance, operation, callback);
+ _connection = con;
+ }
+
+ @Override
+ public Ice.Connection getConnection()
+ {
+ return _connection;
+ }
+
+ public void invoke()
+ {
+ try
+ {
+ final int batchRequestNum = _connection.getBatchRequestQueue().swap(_os);
+
+ int status;
+ if(batchRequestNum == 0)
+ {
+ status = IceInternal.AsyncStatus.Sent;
+ if(sent())
+ {
+ status |= IceInternal.AsyncStatus.InvokeSentCallback;
+ }
+ }
+ else if(_instance.queueRequests())
+ {
+ status = _instance.getQueueExecutor().execute(new Callable<Integer>()
+ {
+ @Override
+ public Integer call() throws RetryException
+ {
+ return _connection.sendAsyncRequest(ConnectionFlushBatch.this, false, false, batchRequestNum);
+ }
+ });
+ }
+ else
+ {
+ status = _connection.sendAsyncRequest(this, false, false, batchRequestNum);
+ }
+
+ if((status & AsyncStatus.Sent) > 0)
+ {
+ _sentSynchronously = true;
+ if((status & AsyncStatus.InvokeSentCallback) > 0)
+ {
+ invokeSent();
+ }
+ }
+ }
+ catch(RetryException ex)
+ {
+ if(completed(ex.get()))
+ {
+ invokeCompletedAsync();
+ }
+ }
+ catch(Ice.Exception ex)
+ {
+ if(completed(ex))
+ {
+ invokeCompletedAsync();
+ }
+ }
+ }
+
+ private Ice.ConnectionI _connection;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ConnectionObserverI.java b/java-compat/src/Ice/src/main/java/IceInternal/ConnectionObserverI.java
new file mode 100644
index 00000000000..ebbf963aba9
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ConnectionObserverI.java
@@ -0,0 +1,62 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ConnectionObserverI
+ extends IceMX.ObserverWithDelegate<IceMX.ConnectionMetrics, Ice.Instrumentation.ConnectionObserver>
+ implements Ice.Instrumentation.ConnectionObserver
+{
+ @Override
+ public void
+ sentBytes(final int num)
+ {
+ _sentBytes = num;
+ forEach(_sentBytesUpdate);
+ if(_delegate != null)
+ {
+ _delegate.sentBytes(num);
+ }
+ }
+
+ @Override
+ public void
+ receivedBytes(int num)
+ {
+ _receivedBytes = num;
+ forEach(_receivedBytesUpdate);
+ if(_delegate != null)
+ {
+ _delegate.receivedBytes(num);
+ }
+ }
+
+ private MetricsUpdate<IceMX.ConnectionMetrics> _sentBytesUpdate = new MetricsUpdate<IceMX.ConnectionMetrics>()
+ {
+ @Override
+ public void
+ update(IceMX.ConnectionMetrics v)
+ {
+ v.sentBytes += _sentBytes;
+ }
+ };
+
+ private MetricsUpdate<IceMX.ConnectionMetrics> _receivedBytesUpdate = new MetricsUpdate<IceMX.ConnectionMetrics>()
+ {
+ @Override
+ public void
+ update(IceMX.ConnectionMetrics v)
+ {
+ v.receivedBytes += _receivedBytes;
+ }
+ };
+
+ private int _sentBytes;
+ private int _receivedBytes;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ConnectionRequestHandler.java b/java-compat/src/Ice/src/main/java/IceInternal/ConnectionRequestHandler.java
new file mode 100644
index 00000000000..6e098e1c6a4
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ConnectionRequestHandler.java
@@ -0,0 +1,82 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ConnectionRequestHandler implements RequestHandler
+{
+ @Override
+ public RequestHandler
+ update(RequestHandler previousHandler, RequestHandler newHandler)
+ {
+ try
+ {
+ if(previousHandler == this)
+ {
+ return newHandler;
+ }
+ else if(previousHandler.getConnection() == _connection)
+ {
+ //
+ // If both request handlers point to the same connection, we also
+ // update the request handler. See bug ICE-5489 for reasons why
+ // this can be useful.
+ //
+ return newHandler;
+ }
+ }
+ catch(Ice.Exception ex)
+ {
+ // Ignore
+ }
+ return this;
+ }
+
+ @Override
+ public int sendAsyncRequest(ProxyOutgoingAsyncBase out)
+ throws RetryException
+ {
+ return out.invokeRemote(_connection, _compress, _response);
+ }
+
+ @Override
+ public void
+ asyncRequestCanceled(OutgoingAsyncBase outgoingAsync, Ice.LocalException ex)
+ {
+ _connection.asyncRequestCanceled(outgoingAsync, ex);
+ }
+
+ @Override
+ public Reference
+ getReference()
+ {
+ return _reference;
+ }
+
+ @Override
+ public Ice.ConnectionI
+ getConnection()
+ {
+ return _connection;
+ }
+
+ public ConnectionRequestHandler(Reference ref, Ice.ConnectionI connection, boolean compress)
+ {
+ _reference = ref;
+ _response = _reference.getMode() == Reference.ModeTwoway;
+ _connection = connection;
+ _compress = compress;
+ }
+
+ private final Reference _reference;
+ private final boolean _response;
+ private final Ice.ConnectionI _connection;
+ private final boolean _compress;
+
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Connector.java b/java-compat/src/Ice/src/main/java/IceInternal/Connector.java
new file mode 100644
index 00000000000..29638f0f138
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Connector.java
@@ -0,0 +1,25 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Connector
+{
+ Transceiver connect();
+
+ short type();
+ @Override
+ String toString();
+
+ //
+ // Compare connectors for sorting process.
+ //
+ @Override
+ boolean equals(java.lang.Object obj);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/DefaultsAndOverrides.java b/java-compat/src/Ice/src/main/java/IceInternal/DefaultsAndOverrides.java
new file mode 100644
index 00000000000..b1b7fc5687d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/DefaultsAndOverrides.java
@@ -0,0 +1,242 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class DefaultsAndOverrides
+{
+ DefaultsAndOverrides(Ice.Properties properties, Ice.Logger logger)
+ {
+ String value;
+ int intValue;
+
+ defaultProtocol = properties.getPropertyWithDefault("Ice.Default.Protocol", "tcp");
+
+ value = properties.getProperty("Ice.Default.Host");
+ if(!value.isEmpty())
+ {
+ defaultHost = value;
+ }
+ else
+ {
+ defaultHost = null;
+ }
+
+ value = properties.getProperty("Ice.Default.SourceAddress");
+ if(!value.isEmpty())
+ {
+ defaultSourceAddress = Network.getNumericAddress(value);
+ if(defaultSourceAddress == null)
+ {
+ throw new Ice.InitializationException("invalid IP address set for Ice.Default.SourceAddress: `" +
+ value + "'");
+ }
+ }
+ else
+ {
+ defaultSourceAddress = null;
+ }
+
+ value = properties.getProperty("Ice.Override.Timeout");
+ if(!value.isEmpty())
+ {
+ overrideTimeout = true;
+ intValue = properties.getPropertyAsInt("Ice.Override.Timeout");
+ if(intValue < 0 && intValue != -1)
+ {
+ overrideTimeoutValue = -1;
+ StringBuffer msg = new StringBuffer("invalid value for Ice.Override.Timeout `");
+ msg.append(properties.getProperty("Ice.Override.Timeout"));
+ msg.append("': defaulting to -1");
+ logger.warning(msg.toString());
+ }
+ else
+ {
+ overrideTimeoutValue = intValue;
+ }
+ }
+ else
+ {
+ overrideTimeout = false;
+ overrideTimeoutValue = -1;
+ }
+
+ value = properties.getProperty("Ice.Override.ConnectTimeout");
+ if(!value.isEmpty())
+ {
+ overrideConnectTimeout = true;
+ intValue = properties.getPropertyAsInt("Ice.Override.ConnectTimeout");
+ if(intValue < 0 && intValue != -1)
+ {
+ overrideConnectTimeoutValue = -1;
+ StringBuffer msg = new StringBuffer("invalid value for Ice.Override.ConnectTimeout `");
+ msg.append(properties.getProperty("Ice.Override.ConnectTimeout"));
+ msg.append("': defaulting to -1");
+ logger.warning(msg.toString());
+ }
+ else
+ {
+ overrideConnectTimeoutValue = intValue;
+ }
+ }
+ else
+ {
+ overrideConnectTimeout = false;
+ overrideConnectTimeoutValue = -1;
+ }
+
+ value = properties.getProperty("Ice.Override.CloseTimeout");
+ if(!value.isEmpty())
+ {
+ overrideCloseTimeout = true;
+ intValue = properties.getPropertyAsInt("Ice.Override.CloseTimeout");
+ if(intValue < 0 && intValue != -1)
+ {
+ overrideCloseTimeoutValue = -1;
+ StringBuffer msg = new StringBuffer("invalid value for Ice.Override.CloseTimeout `");
+ msg.append(properties.getProperty("Ice.Override.CloseTimeout"));
+ msg.append("': defaulting to -1");
+ logger.warning(msg.toString());
+ }
+ else
+ {
+ overrideCloseTimeoutValue = intValue;
+ }
+ }
+ else
+ {
+ overrideCloseTimeout = false;
+ overrideCloseTimeoutValue = -1;
+ }
+
+ value = properties.getProperty("Ice.Override.Compress");
+ if(!value.isEmpty())
+ {
+ overrideCompress = true;
+ boolean b = properties.getPropertyAsInt("Ice.Override.Compress") > 0;
+ if(b && !BZip2.supported())
+ {
+ System.err.println("warning: bzip2 support not available, Ice.Override.Compress ignored");
+ b = false;
+ }
+ overrideCompressValue = b;
+ }
+ else
+ {
+ overrideCompress = false;
+ overrideCompressValue = false;
+ }
+
+ value = properties.getProperty("Ice.Override.Secure");
+ if(!value.isEmpty())
+ {
+ overrideSecure = true;
+ overrideSecureValue = properties.getPropertyAsInt("Ice.Override.Secure") > 0;
+ }
+ else
+ {
+ overrideSecure = false;
+ overrideSecureValue = false;
+ }
+
+ defaultCollocationOptimization =
+ properties.getPropertyAsIntWithDefault("Ice.Default.CollocationOptimized", 1) > 0;
+
+ value = properties.getPropertyWithDefault("Ice.Default.EndpointSelection", "Random");
+ if(value.equals("Random"))
+ {
+ defaultEndpointSelection = Ice.EndpointSelectionType.Random;
+ }
+ else if(value.equals("Ordered"))
+ {
+ defaultEndpointSelection = Ice.EndpointSelectionType.Ordered;
+ }
+ else
+ {
+ Ice.EndpointSelectionTypeParseException ex = new Ice.EndpointSelectionTypeParseException();
+ ex.str = "illegal value `" + value + "'; expected `Random' or `Ordered'";
+ throw ex;
+ }
+
+ intValue = properties.getPropertyAsIntWithDefault("Ice.Default.Timeout", 60000);
+ if(intValue < 1 && intValue != -1)
+ {
+ defaultTimeout = 60000;
+ StringBuffer msg = new StringBuffer("invalid value for Ice.Default.Timeout `");
+ msg.append(properties.getProperty("Ice.Default.Timeout"));
+ msg.append("': defaulting to 60000");
+ logger.warning(msg.toString());
+ }
+ else
+ {
+ defaultTimeout = intValue;
+ }
+
+ intValue = properties.getPropertyAsIntWithDefault("Ice.Default.LocatorCacheTimeout", -1);
+ if(intValue < -1)
+ {
+ defaultLocatorCacheTimeout = -1;
+ StringBuffer msg = new StringBuffer("invalid value for Ice.Default.LocatorCacheTimeout `");
+ msg.append(properties.getProperty("Ice.Default.LocatorCacheTimeout"));
+ msg.append("': defaulting to -1");
+ logger.warning(msg.toString());
+ }
+ else
+ {
+ defaultLocatorCacheTimeout = intValue;
+ }
+
+ intValue = properties.getPropertyAsIntWithDefault("Ice.Default.InvocationTimeout", -1);
+ if(intValue < 1 && intValue != -1 && intValue != -2)
+ {
+ defaultInvocationTimeout = -1;
+ StringBuffer msg = new StringBuffer("invalid value for Ice.Default.InvocationTimeout `");
+ msg.append(properties.getProperty("Ice.Default.InvocationTimeout"));
+ msg.append("': defaulting to -1");
+ logger.warning(msg.toString());
+ }
+ else
+ {
+ defaultInvocationTimeout = intValue;
+ }
+
+ defaultPreferSecure = properties.getPropertyAsIntWithDefault("Ice.Default.PreferSecure", 0) > 0;
+
+ value = properties.getPropertyWithDefault("Ice.Default.EncodingVersion",
+ Ice.Util.encodingVersionToString(Protocol.currentEncoding));
+ defaultEncoding = Ice.Util.stringToEncodingVersion(value);
+ Protocol.checkSupportedEncoding(defaultEncoding);
+
+ boolean slicedFormat = properties.getPropertyAsIntWithDefault("Ice.Default.SlicedFormat", 0) > 0;
+ defaultFormat = slicedFormat ? Ice.FormatType.SlicedFormat : Ice.FormatType.CompactFormat;
+ }
+
+ final public String defaultHost;
+ final public java.net.InetSocketAddress defaultSourceAddress;
+ final public String defaultProtocol;
+ final public boolean defaultCollocationOptimization;
+ final public Ice.EndpointSelectionType defaultEndpointSelection;
+ final public int defaultTimeout;
+ final public int defaultLocatorCacheTimeout;
+ final public int defaultInvocationTimeout;
+ final public boolean defaultPreferSecure;
+ final public Ice.EncodingVersion defaultEncoding;
+ final public Ice.FormatType defaultFormat;
+
+ final public boolean overrideTimeout;
+ final public int overrideTimeoutValue;
+ final public boolean overrideConnectTimeout;
+ final public int overrideConnectTimeoutValue;
+ final public boolean overrideCloseTimeout;
+ final public int overrideCloseTimeoutValue;
+ final public boolean overrideCompress;
+ final public boolean overrideCompressValue;
+ final public boolean overrideSecure;
+ final public boolean overrideSecureValue;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/DictionaryPatcher.java b/java-compat/src/Ice/src/main/java/IceInternal/DictionaryPatcher.java
new file mode 100644
index 00000000000..2f426ac4fa1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/DictionaryPatcher.java
@@ -0,0 +1,41 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class DictionaryPatcher<K, V> implements Ice.ReadValueCallback
+{
+ public DictionaryPatcher(java.util.Map<K, V> dict, Class<V> cls, K key)
+ {
+ _dict = dict;
+ _cls = cls;
+ _key = key;
+ }
+
+ public void valueReady(Ice.Object v)
+ {
+ if(v != null)
+ {
+ //
+ // Raise ClassCastException if the element doesn't match the expected type.
+ //
+ if(!_cls.isInstance(v))
+ {
+ throw new ClassCastException("expected element of type " + _cls.getName() + " but received " +
+ v.getClass().getName());
+ }
+ }
+
+ _dict.put(_key, _cls.cast(v));
+ }
+
+ private java.util.Map<K, V> _dict;
+ private Class<V> _cls;
+ private K _key;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/DispatchObserverI.java b/java-compat/src/Ice/src/main/java/IceInternal/DispatchObserverI.java
new file mode 100644
index 00000000000..1d4ce8be34e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/DispatchObserverI.java
@@ -0,0 +1,55 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class DispatchObserverI
+ extends IceMX.ObserverWithDelegate<IceMX.DispatchMetrics, Ice.Instrumentation.DispatchObserver>
+ implements Ice.Instrumentation.DispatchObserver
+{
+ @Override
+ public void
+ userException()
+ {
+ forEach(_userException);
+ if(_delegate != null)
+ {
+ _delegate.userException();
+ }
+ }
+
+ @Override
+ public void
+ reply(final int size)
+ {
+ forEach(new MetricsUpdate<IceMX.DispatchMetrics>()
+ {
+ @Override
+ public void
+ update(IceMX.DispatchMetrics v)
+ {
+ v.replySize += size;
+ }
+ });
+ if(_delegate != null)
+ {
+ _delegate.reply(size);
+ }
+ }
+
+ final private MetricsUpdate<IceMX.DispatchMetrics> _userException = new MetricsUpdate<IceMX.DispatchMetrics>()
+ {
+ @Override
+ public void
+ update(IceMX.DispatchMetrics v)
+ {
+ ++v.userException;
+ }
+ };
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/DispatchWorkItem.java b/java-compat/src/Ice/src/main/java/IceInternal/DispatchWorkItem.java
new file mode 100644
index 00000000000..157cf841f78
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/DispatchWorkItem.java
@@ -0,0 +1,44 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+//
+// A helper class for thread pool work items that only need to call user
+// callbacks. If a dispatcher is installed with the communicator, the
+// thread pool work item is executed with the dispatcher, otherwise it's
+// executed by a thread pool thread (after promoting a follower thread).
+//
+abstract public class DispatchWorkItem implements ThreadPoolWorkItem, Runnable
+{
+ public DispatchWorkItem()
+ {
+ }
+
+ public DispatchWorkItem(Ice.Connection connection)
+ {
+ _connection = connection;
+ }
+
+ @Override
+ final public void
+ execute(ThreadPoolCurrent current)
+ {
+ current.ioCompleted(); // Promote a follower
+ current.dispatchFromThisThread(this);
+ }
+
+ public Ice.Connection
+ getConnection()
+ {
+ return _connection;
+ }
+
+ private Ice.Connection _connection;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/EndpointFactory.java b/java-compat/src/Ice/src/main/java/IceInternal/EndpointFactory.java
new file mode 100644
index 00000000000..350a9aa7e15
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/EndpointFactory.java
@@ -0,0 +1,21 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface EndpointFactory
+{
+ short type();
+ String protocol();
+ EndpointI create(java.util.ArrayList<String> args, boolean oaEndpoint);
+ EndpointI read(Ice.InputStream s);
+ void destroy();
+
+ EndpointFactory clone(ProtocolInstance instance, EndpointFactory delegate);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/EndpointFactoryManager.java b/java-compat/src/Ice/src/main/java/IceInternal/EndpointFactoryManager.java
new file mode 100644
index 00000000000..252baa39baf
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/EndpointFactoryManager.java
@@ -0,0 +1,183 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class EndpointFactoryManager
+{
+ EndpointFactoryManager(Instance instance)
+ {
+ _instance = instance;
+ }
+
+ public synchronized void add(EndpointFactory factory)
+ {
+ for(int i = 0; i < _factories.size(); i++)
+ {
+ EndpointFactory f = _factories.get(i);
+ if(f.type() == factory.type())
+ {
+ assert(false);
+ }
+ }
+ _factories.add(factory);
+ }
+
+ public synchronized EndpointFactory get(short type)
+ {
+ for(int i = 0; i < _factories.size(); i++)
+ {
+ EndpointFactory f = _factories.get(i);
+ if(f.type() == type)
+ {
+ return f;
+ }
+ }
+ return null;
+ }
+
+ public synchronized EndpointI create(String str, boolean oaEndpoint)
+ {
+ String[] arr = IceUtilInternal.StringUtil.splitString(str, " \t\r\n");
+ if(arr == null)
+ {
+ Ice.EndpointParseException e = new Ice.EndpointParseException();
+ e.str = "mismatched quote";
+ throw e;
+ }
+
+ if(arr.length == 0)
+ {
+ Ice.EndpointParseException e = new Ice.EndpointParseException();
+ e.str = "value has no non-whitespace characters";
+ throw e;
+ }
+
+ java.util.ArrayList<String> v = new java.util.ArrayList<String>(java.util.Arrays.asList(arr));
+ String protocol = v.get(0);
+ v.remove(0);
+
+ if(protocol.equals("default"))
+ {
+ protocol = _instance.defaultsAndOverrides().defaultProtocol;
+ }
+
+ EndpointFactory factory = null;
+
+ for(int i = 0; i < _factories.size(); i++)
+ {
+ EndpointFactory f = _factories.get(i);
+ if(f.protocol().equals(protocol))
+ {
+ factory = f;
+ }
+ }
+
+ if(factory != null)
+ {
+ EndpointI e = factory.create(v, oaEndpoint);
+ if(!v.isEmpty())
+ {
+ Ice.EndpointParseException ex = new Ice.EndpointParseException();
+ ex.str = "unrecognized argument `" + v.get(0) + "' in endpoint `" + str + "'";
+ throw ex;
+ }
+ return e;
+
+ // Code below left in place for debugging.
+
+ /*
+ EndpointI e = f.create(s.substring(m.end()), oaEndpoint);
+ BasicStream bs = new BasicStream(_instance, true, false);
+ e.streamWrite(bs);
+ java.nio.ByteBuffer buf = bs.getBuffer();
+ buf.position(0);
+ short type = bs.readShort();
+ EndpointI ue = new IceInternal.OpaqueEndpointI(type, bs);
+ System.err.println("Normal: " + e);
+ System.err.println("Opaque: " + ue);
+ return e;
+ */
+ }
+
+ //
+ // If the stringified endpoint is opaque, create an unknown endpoint,
+ // then see whether the type matches one of the known endpoints.
+ //
+ if(protocol.equals("opaque"))
+ {
+ EndpointI ue = new OpaqueEndpointI(v);
+ if(!v.isEmpty())
+ {
+ Ice.EndpointParseException ex = new Ice.EndpointParseException();
+ ex.str = "unrecognized argument `" + v.get(0) + "' in endpoint `" + str + "'";
+ throw ex;
+ }
+ factory = get(ue.type());
+ if(factory != null)
+ {
+ //
+ // 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.
+ //
+ Ice.OutputStream os = new Ice.OutputStream(_instance, Protocol.currentProtocolEncoding, false);
+ os.writeShort(ue.type());
+ ue.streamWrite(os);
+ Ice.InputStream is =
+ new Ice.InputStream(_instance, Protocol.currentProtocolEncoding, os.getBuffer(), true);
+ is.pos(0);
+ is.readShort(); // type
+ is.startEncapsulation();
+ EndpointI e = factory.read(is);
+ is.endEncapsulation();
+ return e;
+ }
+ return ue; // Endpoint is opaque, but we don't have a factory for its type.
+ }
+
+ return null;
+ }
+
+ public synchronized EndpointI read(Ice.InputStream s)
+ {
+ short type = s.readShort();
+
+ EndpointFactory factory = get(type);
+ EndpointI e = null;
+
+ s.startEncapsulation();
+
+ if(factory != null)
+ {
+ e = factory.read(s);
+ }
+ else
+ {
+ e = new OpaqueEndpointI(type, s);
+ }
+
+ s.endEncapsulation();
+
+ return e;
+ }
+
+ void destroy()
+ {
+ for(int i = 0; i < _factories.size(); i++)
+ {
+ EndpointFactory f = _factories.get(i);
+ f.destroy();
+ }
+ _factories.clear();
+ }
+
+ private Instance _instance;
+ private java.util.List<EndpointFactory> _factories = new java.util.ArrayList<EndpointFactory>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/EndpointHostResolver.java b/java-compat/src/Ice/src/main/java/IceInternal/EndpointHostResolver.java
new file mode 100644
index 00000000000..89cc00f4a3a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/EndpointHostResolver.java
@@ -0,0 +1,202 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+class EndpointHostResolver
+{
+ EndpointHostResolver(Instance instance)
+ {
+ _instance = instance;
+ _protocol = instance.protocolSupport();
+ _preferIPv6 = instance.preferIPv6();
+ try
+ {
+ _threadName = Util.createThreadName(_instance.initializationData().properties, "Ice.HostResolver");
+ _executor = java.util.concurrent.Executors.newFixedThreadPool(1,
+ Util.createThreadFactory(_instance.initializationData().properties, _threadName));
+ updateObserver();
+ }
+ catch(RuntimeException ex)
+ {
+ String s = "cannot create thread for endpoint host resolver thread:\n" + Ex.toString(ex);
+ _instance.initializationData().logger.error(s);
+ throw ex;
+ }
+ }
+
+ synchronized void resolve(final String host, final int port, final Ice.EndpointSelectionType selType,
+ final IPEndpointI endpoint, final EndpointI_connectors callback)
+ {
+ //
+ // TODO: Optimize to avoid the lookup if the given host is a textual IPv4 or IPv6
+ // address. This requires implementing parsing of IPv4/IPv6 addresses (Java does
+ // not provide such methods).
+ //
+
+ assert(!_destroyed);
+
+ NetworkProxy networkProxy = _instance.networkProxy();
+ if(networkProxy == null)
+ {
+ java.util.List<java.net.InetSocketAddress> addrs = Network.getAddresses(host, port, _protocol, selType,
+ _preferIPv6, false);
+ if(addrs != null)
+ {
+ callback.connectors(endpoint.connectors(addrs, networkProxy));
+ return;
+ }
+ }
+
+ final Ice.Instrumentation.ThreadObserver threadObserver = _observer;
+ final Ice.Instrumentation.Observer observer = getObserver(endpoint);
+ if(observer != null)
+ {
+ observer.attach();
+ }
+
+ _executor.execute(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ synchronized(EndpointHostResolver.this)
+ {
+ if(_destroyed)
+ {
+ Ice.CommunicatorDestroyedException ex = new Ice.CommunicatorDestroyedException();
+ if(observer != null)
+ {
+ observer.failed(ex.ice_id());
+ observer.detach();
+ }
+ callback.exception(ex);
+ return;
+ }
+ }
+
+ if(threadObserver != null)
+ {
+ threadObserver.stateChanged(Ice.Instrumentation.ThreadState.ThreadStateIdle,
+ Ice.Instrumentation.ThreadState.ThreadStateInUseForOther);
+ }
+
+ try
+ {
+ int protocol = _protocol;
+ NetworkProxy networkProxy = _instance.networkProxy();
+ if(networkProxy != null)
+ {
+ networkProxy = networkProxy.resolveHost(_protocol);
+ if(networkProxy != null)
+ {
+ protocol = networkProxy.getProtocolSupport();
+ }
+ }
+
+ callback.connectors(endpoint.connectors(Network.getAddresses(host,
+ port,
+ protocol,
+ selType,
+ _preferIPv6,
+ true),
+ networkProxy));
+ }
+ catch(Ice.LocalException ex)
+ {
+ if(observer != null)
+ {
+ observer.failed(ex.ice_id());
+ }
+ callback.exception(ex);
+ }
+ finally
+ {
+ if(threadObserver != null)
+ {
+ threadObserver.stateChanged(Ice.Instrumentation.ThreadState.ThreadStateInUseForOther,
+ Ice.Instrumentation.ThreadState.ThreadStateIdle);
+ }
+ if(observer != null)
+ {
+ observer.detach();
+ }
+ }
+ }
+ });
+ }
+
+ synchronized void destroy()
+ {
+ assert(!_destroyed);
+ _destroyed = true;
+
+ //
+ // Shutdown the executor. No new tasks will be accepted.
+ // Existing tasks will execute.
+ //
+ _executor.shutdown();
+ }
+
+ void joinWithThread()
+ throws InterruptedException
+ {
+ // Wait for the executor to terminate.
+ try
+ {
+ while(!_executor.isTerminated())
+ {
+ // A very long time.
+ _executor.awaitTermination(100000, java.util.concurrent.TimeUnit.SECONDS);
+ }
+
+ }
+ finally
+ {
+ if(_observer != null)
+ {
+ _observer.detach();
+ }
+ }
+ }
+
+ synchronized void updateObserver()
+ {
+ Ice.Instrumentation.CommunicatorObserver obsv = _instance.initializationData().observer;
+ if(obsv != null)
+ {
+ _observer = obsv.getThreadObserver("Communicator", _threadName,
+ Ice.Instrumentation.ThreadState.ThreadStateIdle,
+ _observer);
+ if(_observer != null)
+ {
+ _observer.attach();
+ }
+ }
+ }
+
+ private Ice.Instrumentation.Observer
+ getObserver(IPEndpointI endpoint)
+ {
+ Ice.Instrumentation.CommunicatorObserver obsv = _instance.initializationData().observer;
+ if(obsv != null)
+ {
+ return obsv.getEndpointLookupObserver(endpoint);
+ }
+ return null;
+ }
+
+ private final Instance _instance;
+ private final int _protocol;
+ private final boolean _preferIPv6;
+ private boolean _destroyed;
+ private Ice.Instrumentation.ThreadObserver _observer;
+ private String _threadName;
+ private java.util.concurrent.ExecutorService _executor;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/EndpointI.java b/java-compat/src/Ice/src/main/java/IceInternal/EndpointI.java
new file mode 100644
index 00000000000..d393916472d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/EndpointI.java
@@ -0,0 +1,197 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+abstract public class EndpointI implements Ice.Endpoint, java.lang.Comparable<EndpointI>
+{
+ public void streamWrite(Ice.OutputStream s)
+ {
+ s.startEncapsulation();
+ streamWriteImpl(s);
+ s.endEncapsulation();
+ }
+
+ @Override
+ public String toString()
+ {
+ return _toString();
+ }
+
+ @Override
+ public String _toString()
+ {
+ //
+ // 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.
+ //
+ return protocol() + options();
+ }
+
+ //
+ // Marshal the endpoint.
+ //
+ public abstract void streamWriteImpl(Ice.OutputStream s);
+
+ //
+ // Return the endpoint type.
+ //
+ public abstract short type();
+
+ //
+ // Return the protocol name.
+ //
+ public abstract String protocol();
+
+ //
+ // Return the timeout for the endpoint in milliseconds. 0 means
+ // non-blocking, -1 means no timeout.
+ //
+ public abstract int timeout();
+
+ //
+ // Return a new endpoint with a different timeout value, provided
+ // that timeouts are supported by the endpoint. Otherwise the same
+ // endpoint is returned.
+ //
+ public abstract EndpointI timeout(int t);
+
+ //
+ // Return the connection ID
+ //
+ public abstract String connectionId();
+
+ //
+ // Return a new endpoint with a different connection id.
+ //
+ public abstract EndpointI connectionId(String connectionId);
+
+ //
+ // Return true if the endpoints support bzip2 compress, or false
+ // otherwise.
+ //
+ public abstract boolean compress();
+
+ //
+ // Return a new endpoint with a different compression value,
+ // provided that compression is supported by the
+ // endpoint. Otherwise the same endpoint is returned.
+ //
+ public abstract EndpointI compress(boolean co);
+
+ //
+ // Return true if the endpoint is datagram-based.
+ //
+ public abstract boolean datagram();
+
+ //
+ // Return true if the endpoint is secure.
+ //
+ public abstract boolean secure();
+
+ //
+ // Return a server side transceiver for this endpoint, or null if a
+ // transceiver can only be created by an acceptor.
+ //
+ public abstract Transceiver transceiver();
+
+ //
+ // Return connectors for this endpoint, or empty list if no connector
+ // is available.
+ //
+ public abstract void connectors_async(Ice.EndpointSelectionType selType, EndpointI_connectors callback);
+
+ //
+ // Return an acceptor for this endpoint, or null if no acceptors
+ // is available.
+ //
+ public abstract Acceptor acceptor(String adapterName);
+
+ //
+ // Expand endpoint out in to separate endpoints for each local
+ // host if listening on INADDR_ANY.
+ //
+ public abstract java.util.List<EndpointI> expand();
+
+ //
+ // Check whether the endpoint is equivalent to another one.
+ //
+ public abstract boolean equivalent(EndpointI endpoint);
+
+ public abstract String options();
+
+ public void initWithOptions(java.util.ArrayList<String> args)
+ {
+ java.util.ArrayList<String> unknown = new java.util.ArrayList<String>();
+
+ String str = "`" + protocol() + " ";
+ for(String p : args)
+ {
+ if(IceUtilInternal.StringUtil.findFirstOf(p, " \t\n\r") != -1)
+ {
+ str += " \"" + p + "\"";
+ }
+ else
+ {
+ str += " " + p;
+ }
+ }
+ str += "'";
+
+ for(int n = 0; n < args.size(); ++n)
+ {
+ String option = args.get(n);
+ if(option.length() < 2 || option.charAt(0) != '-')
+ {
+ unknown.add(option);
+ continue;
+ }
+
+ String argument = null;
+ if(n + 1 < args.size() && args.get(n + 1).charAt(0) != '-')
+ {
+ argument = args.get(++n);
+ }
+
+ if(!checkOption(option, argument, str))
+ {
+ unknown.add(option);
+ if(argument != null)
+ {
+ unknown.add(argument);
+ }
+ }
+ }
+
+ args.clear();
+ args.addAll(unknown);
+ }
+
+ //
+ // Compare endpoints for sorting purposes.
+ //
+ @Override
+ public boolean equals(java.lang.Object obj)
+ {
+ if(!(obj instanceof EndpointI))
+ {
+ return false;
+ }
+ return compareTo((EndpointI)obj) == 0;
+ }
+
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ // Must be overridden to check for options.
+ return false;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/EndpointIHolder.java b/java-compat/src/Ice/src/main/java/IceInternal/EndpointIHolder.java
new file mode 100644
index 00000000000..226664113f1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/EndpointIHolder.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class EndpointIHolder
+{
+ public EndpointI value;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/EndpointI_connectors.java b/java-compat/src/Ice/src/main/java/IceInternal/EndpointI_connectors.java
new file mode 100644
index 00000000000..dfcdb479645
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/EndpointI_connectors.java
@@ -0,0 +1,16 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface EndpointI_connectors
+{
+ void connectors(java.util.List<Connector> connectors);
+ void exception(Ice.LocalException ex);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/EventHandler.java b/java-compat/src/Ice/src/main/java/IceInternal/EventHandler.java
new file mode 100644
index 00000000000..06fab81e580
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/EventHandler.java
@@ -0,0 +1,44 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class EventHandler
+{
+ //
+ // Called when there's a message ready to be processed.
+ //
+ abstract public void message(ThreadPoolCurrent current);
+
+ //
+ // Called when the event handler is unregistered.
+ //
+ abstract public void finished(ThreadPoolCurrent current, boolean close);
+
+ //
+ // Get a textual representation of the event handler.
+ //
+ @Override
+ abstract public String toString();
+
+ //
+ // Get the native information of the handler, this is used by the selector.
+ //
+ abstract public java.nio.channels.SelectableChannel fd();
+
+ //
+ // Set the ready callback
+ //
+ abstract public void setReadyCallback(ReadyCallback callback);
+
+ public int _disabled = 0;
+ public int _registered = 0;
+ public int _ready = 0;
+ public java.nio.channels.SelectionKey _key = null;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/EventHandlerOpPair.java b/java-compat/src/Ice/src/main/java/IceInternal/EventHandlerOpPair.java
new file mode 100644
index 00000000000..37deadd0ff4
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/EventHandlerOpPair.java
@@ -0,0 +1,22 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+class EventHandlerOpPair
+{
+ EventHandlerOpPair(EventHandler handler, int op)
+ {
+ this.handler = handler;
+ this.op = op;
+ }
+
+ EventHandler handler;
+ int op;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Ex.java b/java-compat/src/Ice/src/main/java/IceInternal/Ex.java
new file mode 100644
index 00000000000..dcffe92be76
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Ex.java
@@ -0,0 +1,49 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class Ex
+{
+ public static void throwUOE(String expectedType, Ice.Object v)
+ {
+ //
+ // If the object is an unknown sliced object, we didn't find an
+ // value factory, in this case raise a NoValueFactoryException
+ // instead.
+ //
+ if(v instanceof Ice.UnknownSlicedValue)
+ {
+ Ice.UnknownSlicedValue usv = (Ice.UnknownSlicedValue)v;
+ throw new Ice.NoValueFactoryException("", usv.getUnknownTypeId());
+ }
+
+ String type = v.ice_id();
+ throw new Ice.UnexpectedObjectException("expected element of type `" + expectedType + "' but received '" +
+ type, type, expectedType);
+ }
+
+ public static void throwMemoryLimitException(int requested, int maximum)
+ {
+ throw new Ice.MemoryLimitException("requested " + requested + " bytes, maximum allowed is " + maximum +
+ " bytes (see Ice.MessageSizeMax)");
+ }
+
+ //
+ // A small utility to get the strack trace of the exception (which also includes toString()).
+ //
+ public static String toString(java.lang.Throwable ex)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ return sw.toString();
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/FactoryACMMonitor.java b/java-compat/src/Ice/src/main/java/IceInternal/FactoryACMMonitor.java
new file mode 100644
index 00000000000..1944656bcfa
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/FactoryACMMonitor.java
@@ -0,0 +1,232 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+class FactoryACMMonitor implements ACMMonitor
+{
+ static class Change
+ {
+ Change(Ice.ConnectionI connection, boolean remove)
+ {
+ this.connection = connection;
+ this.remove = remove;
+ }
+
+ final Ice.ConnectionI connection;
+ final boolean remove;
+ }
+
+ FactoryACMMonitor(Instance instance, ACMConfig config)
+ {
+ _instance = instance;
+ _config = config;
+ }
+
+ @Override
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_instance == null);
+ IceUtilInternal.Assert.FinalizerAssert(_connections.isEmpty());
+ IceUtilInternal.Assert.FinalizerAssert(_changes.isEmpty());
+ IceUtilInternal.Assert.FinalizerAssert(_reapedConnections.isEmpty());
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ synchronized void
+ destroy()
+ {
+ if(_instance == null)
+ {
+ return;
+ }
+ _instance = null;
+ _connections.clear();
+ _changes.clear();
+ }
+
+ @Override
+ public void
+ add(Ice.ConnectionI connection)
+ {
+ if(_config.timeout == 0)
+ {
+ return;
+ }
+
+ synchronized(this)
+ {
+ if(_connections.isEmpty())
+ {
+ _connections.add(connection);
+ assert _future == null;
+ _future = _instance.timer().scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run()
+ {
+ monitorConnections();
+ }
+ },
+ _config.timeout / 2, _config.timeout / 2, java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+ else
+ {
+ _changes.add(new Change(connection, false));
+ }
+ }
+ }
+
+ @Override
+ public void
+ remove(Ice.ConnectionI connection)
+ {
+ if(_config.timeout == 0)
+ {
+ return;
+ }
+
+ synchronized(this)
+ {
+ assert(_instance != null);
+ _changes.add(new Change(connection, true));
+ }
+ }
+
+ @Override
+ public synchronized void
+ reap(Ice.ConnectionI connection)
+ {
+ _reapedConnections.add(connection);
+ }
+
+ @Override
+ public synchronized ACMMonitor
+ acm(Ice.IntOptional timeout, Ice.Optional<Ice.ACMClose> close, Ice.Optional<Ice.ACMHeartbeat> heartbeat)
+ {
+ assert(_instance != null);
+
+ ACMConfig config = _config.clone();
+ if(timeout != null && timeout.isSet())
+ {
+ config.timeout = timeout.get() * 1000; // To milliseconds
+ }
+ if(close != null && close.isSet())
+ {
+ config.close = close.get();
+ }
+ if(heartbeat != null && heartbeat.isSet())
+ {
+ config.heartbeat = heartbeat.get();
+ }
+ return new ConnectionACMMonitor(this, _instance.timer(), config);
+ }
+
+ @Override
+ public Ice.ACM
+ getACM()
+ {
+ Ice.ACM acm = new Ice.ACM();
+ acm.timeout = _config.timeout / 1000;
+ acm.close = _config.close;
+ acm.heartbeat = _config.heartbeat;
+ return acm;
+ }
+
+ synchronized java.util.List<Ice.ConnectionI>
+ swapReapedConnections()
+ {
+ if(_reapedConnections.isEmpty())
+ {
+ return null;
+ }
+ java.util.List<Ice.ConnectionI> connections = _reapedConnections;
+ _reapedConnections = new java.util.ArrayList<Ice.ConnectionI>();
+ return connections;
+ }
+
+ private void
+ monitorConnections()
+ {
+ synchronized(this)
+ {
+ if(_instance == null)
+ {
+ return;
+ }
+
+ for(Change change : _changes)
+ {
+ if(change.remove)
+ {
+ _connections.remove(change.connection);
+ }
+ else
+ {
+ _connections.add(change.connection);
+ }
+ }
+ _changes.clear();
+
+ if(_connections.isEmpty())
+ {
+ _future.cancel(false);
+ _future = null;
+ return;
+ }
+ }
+
+
+ //
+ // Monitor connections outside the thread synchronization, so
+ // that connections can be added or removed during monitoring.
+ //
+ long now = Time.currentMonotonicTimeMillis();
+ for(Ice.ConnectionI connection : _connections)
+ {
+ try
+ {
+ connection.monitor(now, _config);
+ }
+ catch(Exception ex)
+ {
+ handleException(ex);
+ }
+ }
+ }
+
+ synchronized void
+ handleException(Exception ex)
+ {
+ if(_instance == null)
+ {
+ return;
+ }
+ _instance.initializationData().logger.error("exception in connection monitor:\n" + ex);
+ }
+
+ private Instance _instance;
+ final private ACMConfig _config;
+
+ private java.util.Set<Ice.ConnectionI> _connections = new java.util.HashSet<Ice.ConnectionI>();
+ private java.util.List<Change> _changes = new java.util.ArrayList<Change>();
+ private java.util.List<Ice.ConnectionI> _reapedConnections = new java.util.ArrayList<Ice.ConnectionI>();
+ private java.util.concurrent.Future<?> _future;
+}
+
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/FixedReference.java b/java-compat/src/Ice/src/main/java/IceInternal/FixedReference.java
new file mode 100644
index 00000000000..6ae5fe1b4c2
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/FixedReference.java
@@ -0,0 +1,319 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class FixedReference extends Reference
+{
+ public
+ FixedReference(Instance instance,
+ Ice.Communicator communicator,
+ Ice.Identity identity,
+ String facet,
+ int mode,
+ boolean secure,
+ Ice.EncodingVersion encoding,
+ Ice.ConnectionI connection)
+ {
+ super(instance, communicator, identity, facet, mode, secure, Ice.Util.Protocol_1_0, encoding, -1, null);
+ _fixedConnection = connection;
+ }
+
+ @Override
+ public EndpointI[]
+ getEndpoints()
+ {
+ return _emptyEndpoints;
+ }
+
+ @Override
+ public String
+ getAdapterId()
+ {
+ return "";
+ }
+
+ @Override
+ public LocatorInfo
+ getLocatorInfo()
+ {
+ return null;
+ }
+
+ @Override
+ public RouterInfo
+ getRouterInfo()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean
+ getCollocationOptimized()
+ {
+ return false;
+ }
+
+ @Override
+ public final boolean
+ getCacheConnection()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean
+ getPreferSecure()
+ {
+ return false;
+ }
+
+ @Override
+ public final Ice.EndpointSelectionType
+ getEndpointSelection()
+ {
+ return Ice.EndpointSelectionType.Random;
+ }
+
+ @Override
+ public int
+ getLocatorCacheTimeout()
+ {
+ return 0;
+ }
+
+ @Override
+ public String
+ getConnectionId()
+ {
+ return "";
+ }
+
+ @Override
+ public Reference
+ changeEndpoints(EndpointI[] newEndpoints)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public Reference
+ changeAdapterId(String newAdapterId)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public Reference
+ changeLocator(Ice.LocatorPrx newLocator)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public Reference
+ changeRouter(Ice.RouterPrx newRouter)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public Reference
+ changeCollocationOptimized(boolean newCollocationOptimized)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public final Reference
+ changeCacheConnection(boolean newCache)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public Reference
+ changePreferSecure(boolean prefSec)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public final Reference
+ changeEndpointSelection(Ice.EndpointSelectionType newType)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public Reference
+ changeLocatorCacheTimeout(int newTimeout)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public Reference
+ changeTimeout(int newTimeout)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public Reference
+ changeConnectionId(String connectionId)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public boolean
+ isIndirect()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean
+ isWellKnown()
+ {
+ return false;
+ }
+
+ @Override
+ public void
+ streamWrite(Ice.OutputStream s)
+ throws Ice.MarshalException
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public String
+ toString()
+ throws Ice.MarshalException
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public java.util.Map<String, String>
+ toProperty(String prefix)
+ {
+ throw new Ice.FixedProxyException();
+ }
+
+ @Override
+ public RequestHandler
+ getRequestHandler(Ice.ObjectPrxHelperBase proxy)
+ {
+ switch(getMode())
+ {
+ case Reference.ModeTwoway:
+ case Reference.ModeOneway:
+ case Reference.ModeBatchOneway:
+ {
+ if(_fixedConnection.endpoint().datagram())
+ {
+ throw new Ice.NoEndpointException("");
+ }
+ break;
+ }
+
+ case Reference.ModeDatagram:
+ case Reference.ModeBatchDatagram:
+ {
+ if(!_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.
+ //
+ boolean secure;
+ DefaultsAndOverrides defaultsAndOverrides = getInstance().defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideSecure)
+ {
+ secure = defaultsAndOverrides.overrideSecureValue;
+ }
+ else
+ {
+ secure = getSecure();
+ }
+ if(secure && !_fixedConnection.endpoint().secure())
+ {
+ throw new Ice.NoEndpointException("");
+ }
+
+ _fixedConnection.throwException(); // Throw in case our connection is already destroyed.
+
+ boolean compress;
+ if(defaultsAndOverrides.overrideCompress)
+ {
+ compress = defaultsAndOverrides.overrideCompressValue;
+ }
+ else if(_overrideCompress)
+ {
+ compress = _compress;
+ }
+ else
+ {
+ compress = _fixedConnection.endpoint().compress();
+ }
+
+ RequestHandler handler = new ConnectionRequestHandler(this, _fixedConnection, compress);
+ if(getInstance().queueRequests())
+ {
+ handler = new QueueRequestHandler(getInstance(), handler);
+ }
+ return proxy.__setRequestHandler(handler);
+ }
+
+ @Override
+ public BatchRequestQueue
+ getBatchRequestQueue()
+ {
+ return _fixedConnection.getBatchRequestQueue();
+ }
+
+ @Override
+ public boolean
+ equals(java.lang.Object obj)
+ {
+ if(this == obj)
+ {
+ return true;
+ }
+ if(!(obj instanceof FixedReference))
+ {
+ return false;
+ }
+ FixedReference rhs = (FixedReference)obj;
+ if(!super.equals(rhs))
+ {
+ return false;
+ }
+ return _fixedConnection.equals(rhs._fixedConnection);
+ }
+
+ @Override
+ public int
+ hashCode()
+ {
+ return super.hashCode();
+ }
+
+ private Ice.ConnectionI _fixedConnection;
+ private static EndpointI[] _emptyEndpoints = new EndpointI[0];
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_BoolCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_BoolCallback.java
new file mode 100644
index 00000000000..71954017a36
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_BoolCallback.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Functional_BoolCallback
+{
+ void apply(boolean arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_ByteCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_ByteCallback.java
new file mode 100644
index 00000000000..06d44618159
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_ByteCallback.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Functional_ByteCallback
+{
+ void apply(byte arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_CallbackBase.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_CallbackBase.java
new file mode 100644
index 00000000000..dc200518c10
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_CallbackBase.java
@@ -0,0 +1,50 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_CallbackBase extends IceInternal.CallbackBase
+{
+ public Functional_CallbackBase(boolean responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ CallbackBase.check(responseCb || exceptionCb != null);
+ __exceptionCb = exceptionCb;
+ __sentCb = sentCb;
+ }
+
+ protected Functional_CallbackBase(Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ __exceptionCb = exceptionCb;
+ __sentCb = sentCb;
+ }
+
+ @Override
+ public final void __sent(Ice.AsyncResult __result)
+ {
+ if(__sentCb != null)
+ {
+ __sentCb.apply(__result.sentSynchronously());
+ }
+ }
+
+ @Override
+ public final boolean __hasSentCallback()
+ {
+ return __sentCb != null;
+ }
+
+ @Override
+ public abstract void __completed(Ice.AsyncResult __result);
+
+ protected final Functional_GenericCallback1<Ice.Exception> __exceptionCb;
+ protected final Functional_BoolCallback __sentCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_DoubleCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_DoubleCallback.java
new file mode 100644
index 00000000000..8aba3931756
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_DoubleCallback.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Functional_DoubleCallback
+{
+ void apply(double arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_FloatCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_FloatCallback.java
new file mode 100644
index 00000000000..69deb3ff76d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_FloatCallback.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Functional_FloatCallback
+{
+ void apply(float arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_GenericCallback1.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_GenericCallback1.java
new file mode 100644
index 00000000000..aae63a7e35b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_GenericCallback1.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Functional_GenericCallback1<T>
+{
+ void apply(T arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_IntCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_IntCallback.java
new file mode 100644
index 00000000000..ab901b9cad8
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_IntCallback.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Functional_IntCallback
+{
+ void apply(int arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_LongCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_LongCallback.java
new file mode 100644
index 00000000000..ff64e28b35e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_LongCallback.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Functional_LongCallback
+{
+ void apply(long arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_OnewayCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_OnewayCallback.java
new file mode 100644
index 00000000000..7962cd4e336
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_OnewayCallback.java
@@ -0,0 +1,44 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class Functional_OnewayCallback extends IceInternal.Functional_CallbackBase
+{
+ public Functional_OnewayCallback(Functional_VoidCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ CallbackBase.check(responseCb != null || exceptionCb != null);
+ __responseCb = responseCb;
+ }
+
+ @Override
+ public final void __completed(Ice.AsyncResult __result)
+ {
+ try
+ {
+ ((Ice.ObjectPrxHelperBase)__result.getProxy()).__end(__result, __result.getOperation());
+ if(__responseCb != null)
+ {
+ __responseCb.apply();
+ }
+ }
+ catch(Ice.Exception __ex)
+ {
+ if(__exceptionCb != null)
+ {
+ __exceptionCb.apply(__ex);
+ }
+ }
+ }
+
+ private final Functional_VoidCallback __responseCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_ShortCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_ShortCallback.java
new file mode 100644
index 00000000000..32a1d925ce6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_ShortCallback.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Functional_ShortCallback
+{
+ void apply(short arg);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallback.java
new file mode 100644
index 00000000000..f88b2d64ca6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallback.java
@@ -0,0 +1,44 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallback extends IceInternal.Functional_CallbackBase implements Ice.TwowayCallback
+{
+ public Functional_TwowayCallback(boolean responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb, exceptionCb, sentCb);
+ }
+
+ protected Functional_TwowayCallback(Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ }
+
+ @Override
+ public void exception(Ice.SystemException ex)
+ {
+ if(__exceptionCb != null)
+ {
+ __exceptionCb.apply(ex);
+ }
+ }
+
+ @Override
+ public final void exception(Ice.LocalException ex)
+ {
+ if(__exceptionCb != null)
+ {
+ __exceptionCb.apply(ex);
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackArg1.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackArg1.java
new file mode 100644
index 00000000000..c7b52ea9c52
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackArg1.java
@@ -0,0 +1,43 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackArg1<T> extends Functional_TwowayCallback
+ implements Ice.TwowayCallbackArg1<T>
+{
+ public Functional_TwowayCallbackArg1(Functional_GenericCallback1<T> responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb != null, exceptionCb, sentCb);
+ __responseCb = responseCb;
+ }
+
+ protected Functional_TwowayCallbackArg1(boolean userExceptionCb,
+ Functional_GenericCallback1<T> responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ CallbackBase.check(responseCb != null || (userExceptionCb && exceptionCb != null));
+ __responseCb = responseCb;
+ }
+
+ @Override
+ public void response(T arg)
+ {
+ if(__responseCb != null)
+ {
+ __responseCb.apply(arg);
+ }
+ }
+
+ final private Functional_GenericCallback1<T> __responseCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackArg1UE.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackArg1UE.java
new file mode 100644
index 00000000000..ed810994d8e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackArg1UE.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackArg1UE<T>
+ extends Functional_TwowayCallbackArg1<T> implements Ice.TwowayCallbackArg1UE<T>
+{
+ public Functional_TwowayCallbackArg1UE(
+ Functional_GenericCallback1<T> responseCb,
+ Functional_GenericCallback1<Ice.UserException> userExceptionCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(userExceptionCb != null, responseCb, exceptionCb, sentCb);
+ __userExceptionCb = userExceptionCb;
+ }
+
+ @Override
+ public void exception(Ice.UserException ex)
+ {
+ if(__userExceptionCb != null)
+ {
+ __userExceptionCb.apply(ex);
+ }
+ }
+
+ private final Functional_GenericCallback1<Ice.UserException> __userExceptionCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackBool.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackBool.java
new file mode 100644
index 00000000000..973b107f1ff
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackBool.java
@@ -0,0 +1,42 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackBool extends Functional_TwowayCallback implements Ice.TwowayCallbackBool
+{
+ public Functional_TwowayCallbackBool(Functional_BoolCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb != null, exceptionCb, sentCb);
+ this.__responseCb = responseCb;
+ }
+
+ protected Functional_TwowayCallbackBool(boolean userExceptionCb,
+ Functional_BoolCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ CallbackBase.check(responseCb != null || (userExceptionCb && exceptionCb != null));
+ this.__responseCb = responseCb;
+ }
+
+ @Override
+ public void response(boolean arg)
+ {
+ if(__responseCb != null)
+ {
+ __responseCb.apply(arg);
+ }
+ }
+
+ final private Functional_BoolCallback __responseCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackBoolUE.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackBoolUE.java
new file mode 100644
index 00000000000..28d2a92777f
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackBoolUE.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackBoolUE
+ extends Functional_TwowayCallbackBool implements Ice.TwowayCallbackBoolUE
+{
+ public Functional_TwowayCallbackBoolUE(
+ Functional_BoolCallback responseCb,
+ Functional_GenericCallback1<Ice.UserException> userExceptionCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(userExceptionCb != null, responseCb, exceptionCb, sentCb);
+ __userExceptionCb = userExceptionCb;
+ }
+
+ @Override
+ public void exception(Ice.UserException ex)
+ {
+ if(__userExceptionCb != null)
+ {
+ __userExceptionCb.apply(ex);
+ }
+ }
+
+ private final Functional_GenericCallback1<Ice.UserException> __userExceptionCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackByte.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackByte.java
new file mode 100644
index 00000000000..986163e8d80
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackByte.java
@@ -0,0 +1,42 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackByte extends Functional_TwowayCallback implements Ice.TwowayCallbackByte
+{
+ public Functional_TwowayCallbackByte(Functional_ByteCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb != null, exceptionCb, sentCb);
+ __responseCb = responseCb;
+ }
+
+ protected Functional_TwowayCallbackByte(boolean userExceptionCb,
+ Functional_ByteCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ CallbackBase.check(responseCb != null || (userExceptionCb && exceptionCb != null));
+ __responseCb = responseCb;
+ }
+
+ @Override
+ public void response(byte arg)
+ {
+ if(__responseCb != null)
+ {
+ __responseCb.apply(arg);
+ }
+ }
+
+ final private Functional_ByteCallback __responseCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackByteUE.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackByteUE.java
new file mode 100644
index 00000000000..1c0fb9bb8bc
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackByteUE.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackByteUE
+ extends Functional_TwowayCallbackByte implements Ice.TwowayCallbackByteUE
+{
+ public Functional_TwowayCallbackByteUE(
+ Functional_ByteCallback responseCb,
+ Functional_GenericCallback1<Ice.UserException> userExceptionCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(userExceptionCb != null, responseCb, exceptionCb, sentCb);
+ __userExceptionCb = userExceptionCb;
+ }
+
+ @Override
+ public void exception(Ice.UserException ex)
+ {
+ if(__userExceptionCb != null)
+ {
+ __userExceptionCb.apply(ex);
+ }
+ }
+
+ private final Functional_GenericCallback1<Ice.UserException> __userExceptionCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackDouble.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackDouble.java
new file mode 100644
index 00000000000..879014d73e5
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackDouble.java
@@ -0,0 +1,42 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackDouble
+ extends Functional_TwowayCallback implements Ice.TwowayCallbackDouble
+{
+ public Functional_TwowayCallbackDouble(Functional_DoubleCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb != null, exceptionCb, sentCb);
+ __responseCb = responseCb;
+ }
+
+ protected Functional_TwowayCallbackDouble(boolean userExceptionCb,
+ Functional_DoubleCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ CallbackBase.check(responseCb != null || (userExceptionCb && exceptionCb != null));
+ __responseCb = responseCb;
+ }
+
+ public void response(double arg)
+ {
+ if(__responseCb != null)
+ {
+ __responseCb.apply(arg);
+ }
+ }
+
+ final private Functional_DoubleCallback __responseCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackDoubleUE.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackDoubleUE.java
new file mode 100644
index 00000000000..a8d28cf12fe
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackDoubleUE.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackDoubleUE
+ extends Functional_TwowayCallbackDouble implements Ice.TwowayCallbackDoubleUE
+{
+ public Functional_TwowayCallbackDoubleUE(
+ Functional_DoubleCallback responseCb,
+ Functional_GenericCallback1<Ice.UserException> userExceptionCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(userExceptionCb != null, responseCb, exceptionCb, sentCb);
+ __userExceptionCb = userExceptionCb;
+ }
+
+ @Override
+ public void exception(Ice.UserException ex)
+ {
+ if(__userExceptionCb != null)
+ {
+ __userExceptionCb.apply(ex);
+ }
+ }
+
+ private final Functional_GenericCallback1<Ice.UserException> __userExceptionCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackFloat.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackFloat.java
new file mode 100644
index 00000000000..7ea9b1f9753
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackFloat.java
@@ -0,0 +1,43 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackFloat
+ extends Functional_TwowayCallback implements Ice.TwowayCallbackFloat
+{
+ public Functional_TwowayCallbackFloat(Functional_FloatCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb != null, exceptionCb, sentCb);
+ __responseCb = responseCb;
+ }
+
+ protected Functional_TwowayCallbackFloat(boolean userExceptionCb,
+ Functional_FloatCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ CallbackBase.check(responseCb != null || (userExceptionCb && exceptionCb != null));
+ __responseCb = responseCb;
+ }
+
+ @Override
+ public void response(float arg)
+ {
+ if(__responseCb != null)
+ {
+ __responseCb.apply(arg);
+ }
+ }
+
+ final private Functional_FloatCallback __responseCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackFloatUE.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackFloatUE.java
new file mode 100644
index 00000000000..d5dc8141064
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackFloatUE.java
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackFloatUE
+ extends Functional_TwowayCallbackFloat implements Ice.TwowayCallbackFloatUE
+{
+ public Functional_TwowayCallbackFloatUE(Functional_FloatCallback responseCb,
+ Functional_GenericCallback1<Ice.UserException> userExceptionCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(userExceptionCb != null, responseCb, exceptionCb, sentCb);
+ __userExceptionCb = userExceptionCb;
+ }
+
+ @Override
+ public void exception(Ice.UserException ex)
+ {
+ if(__userExceptionCb != null)
+ {
+ __userExceptionCb.apply(ex);
+ }
+ }
+
+ private final Functional_GenericCallback1<Ice.UserException> __userExceptionCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackInt.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackInt.java
new file mode 100644
index 00000000000..8c6fea2818e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackInt.java
@@ -0,0 +1,43 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackInt
+ extends Functional_TwowayCallback implements Ice.TwowayCallbackInt
+{
+ public Functional_TwowayCallbackInt(Functional_IntCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb != null, exceptionCb, sentCb);
+ __responseCb = responseCb;
+ }
+
+ protected Functional_TwowayCallbackInt(boolean userExceptionCb,
+ Functional_IntCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ CallbackBase.check(responseCb != null || (userExceptionCb && exceptionCb != null));
+ __responseCb = responseCb;
+ }
+
+ @Override
+ public void response(int arg)
+ {
+ if(__responseCb != null)
+ {
+ __responseCb.apply(arg);
+ }
+ }
+
+ final private Functional_IntCallback __responseCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackIntUE.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackIntUE.java
new file mode 100644
index 00000000000..b749b44b1ad
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackIntUE.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackIntUE
+ extends Functional_TwowayCallbackInt implements Ice.TwowayCallbackIntUE
+{
+ public Functional_TwowayCallbackIntUE(
+ Functional_IntCallback responseCb,
+ Functional_GenericCallback1<Ice.UserException> userExceptionCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(userExceptionCb != null, responseCb, exceptionCb, sentCb);
+ __userExceptionCb = userExceptionCb;
+ }
+
+ @Override
+ public void exception(Ice.UserException ex)
+ {
+ if(__userExceptionCb != null)
+ {
+ __userExceptionCb.apply(ex);
+ }
+ }
+
+ private final Functional_GenericCallback1<Ice.UserException> __userExceptionCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackLong.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackLong.java
new file mode 100644
index 00000000000..bc6c654643e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackLong.java
@@ -0,0 +1,43 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackLong
+ extends Functional_TwowayCallback implements Ice.TwowayCallbackLong
+{
+ public Functional_TwowayCallbackLong(Functional_LongCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb != null, exceptionCb, sentCb);
+ __responseCb = responseCb;
+ }
+
+ protected Functional_TwowayCallbackLong(boolean userExceptionCb,
+ Functional_LongCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ CallbackBase.check(responseCb != null || (userExceptionCb && exceptionCb != null));
+ __responseCb = responseCb;
+ }
+
+ @Override
+ public void response(long arg)
+ {
+ if(__responseCb != null)
+ {
+ __responseCb.apply(arg);
+ }
+ }
+
+ final private Functional_LongCallback __responseCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackLongUE.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackLongUE.java
new file mode 100644
index 00000000000..2eb6985fcb8
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackLongUE.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackLongUE
+ extends Functional_TwowayCallbackLong implements Ice.TwowayCallbackLongUE
+{
+ public Functional_TwowayCallbackLongUE(
+ Functional_LongCallback responseCb,
+ Functional_GenericCallback1<Ice.UserException> userExceptionCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb, exceptionCb, sentCb);
+ __userExceptionCb = userExceptionCb;
+ }
+
+ @Override
+ public void exception(Ice.UserException ex)
+ {
+ if(__userExceptionCb != null)
+ {
+ __userExceptionCb.apply(ex);
+ }
+ }
+
+ private final Functional_GenericCallback1<Ice.UserException> __userExceptionCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackShort.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackShort.java
new file mode 100644
index 00000000000..f6c835f0721
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackShort.java
@@ -0,0 +1,43 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackShort
+ extends Functional_TwowayCallback implements Ice.TwowayCallbackShort
+{
+ public Functional_TwowayCallbackShort(Functional_ShortCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb != null, exceptionCb, sentCb);
+ __responseCb = responseCb;
+ }
+
+ protected Functional_TwowayCallbackShort(boolean userExceptionCb,
+ Functional_ShortCallback responseCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ CallbackBase.check(responseCb != null || (userExceptionCb && exceptionCb != null));
+ __responseCb = responseCb;
+ }
+
+ @Override
+ public void response(short arg)
+ {
+ if(__responseCb != null)
+ {
+ __responseCb.apply(arg);
+ }
+ }
+
+ final private Functional_ShortCallback __responseCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackShortUE.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackShortUE.java
new file mode 100644
index 00000000000..47ff52de87c
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackShortUE.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackShortUE
+ extends Functional_TwowayCallbackShort implements Ice.TwowayCallbackShortUE
+{
+ public Functional_TwowayCallbackShortUE(
+ Functional_ShortCallback responseCb,
+ Functional_GenericCallback1<Ice.UserException> userExceptionCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb, exceptionCb, sentCb);
+ __userExceptionCb = userExceptionCb;
+ }
+
+ @Override
+ public void exception(Ice.UserException ex)
+ {
+ if(__userExceptionCb != null)
+ {
+ __userExceptionCb.apply(ex);
+ }
+ }
+
+ private final Functional_GenericCallback1<Ice.UserException> __userExceptionCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackUE.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackUE.java
new file mode 100644
index 00000000000..5ae5d838274
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackUE.java
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackUE extends Functional_TwowayCallback implements Ice.TwowayCallbackUE
+{
+ public Functional_TwowayCallbackUE(boolean responseCb,
+ Functional_GenericCallback1<Ice.UserException> userExceptionCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(exceptionCb, sentCb);
+ CallbackBase.check(responseCb || (userExceptionCb != null && exceptionCb != null));
+ __userExceptionCb = userExceptionCb;
+ }
+
+ @Override
+ public final void exception(Ice.UserException ex)
+ {
+ if(__userExceptionCb != null)
+ {
+ __userExceptionCb.apply(ex);
+ }
+ }
+
+ protected final Functional_GenericCallback1<Ice.UserException> __userExceptionCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackVoidUE.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackVoidUE.java
new file mode 100644
index 00000000000..080b4ad863a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_TwowayCallbackVoidUE.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Functional_TwowayCallbackVoidUE
+ extends Functional_TwowayCallbackUE implements Ice.TwowayCallbackVoidUE
+{
+ public Functional_TwowayCallbackVoidUE(
+ Functional_VoidCallback responseCb,
+ Functional_GenericCallback1<Ice.UserException> userExceptionCb,
+ Functional_GenericCallback1<Ice.Exception> exceptionCb,
+ Functional_BoolCallback sentCb)
+ {
+ super(responseCb != null, userExceptionCb, exceptionCb, sentCb);
+ __responseCb = responseCb;
+ }
+
+ @Override
+ public void response()
+ {
+ if(__responseCb != null)
+ {
+ __responseCb.apply();
+ }
+ }
+
+ private final Functional_VoidCallback __responseCb;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Functional_VoidCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/Functional_VoidCallback.java
new file mode 100644
index 00000000000..ca40c37cd7c
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Functional_VoidCallback.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Functional_VoidCallback
+{
+ void apply();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/HTTPNetworkProxy.java b/java-compat/src/Ice/src/main/java/IceInternal/HTTPNetworkProxy.java
new file mode 100644
index 00000000000..1214731fbea
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/HTTPNetworkProxy.java
@@ -0,0 +1,135 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class HTTPNetworkProxy implements NetworkProxy
+{
+ public HTTPNetworkProxy(String host, int port)
+ {
+ _host = host;
+ _port = port;
+ _protocolSupport = Network.EnableBoth;
+ }
+
+ private HTTPNetworkProxy(java.net.InetSocketAddress address, int protocolSupport)
+ {
+ _address = address;
+ _protocolSupport = protocolSupport;
+ }
+
+ @Override
+ public void beginWrite(java.net.InetSocketAddress endpoint, Buffer buf)
+ {
+ String addr = Network.addrToString(endpoint);
+ StringBuilder str = new StringBuilder();
+ str.append("CONNECT ");
+ str.append(addr);
+ str.append(" HTTP/1.1\r\nHost: ");
+ str.append(addr);
+ str.append("\r\n\r\n");
+
+ byte[] b = str.toString().getBytes(java.nio.charset.StandardCharsets.US_ASCII);
+
+ //
+ // HTTP connect request
+ //
+ buf.resize(b.length, false);
+ buf.b.position(0);
+ buf.b.put(b);
+ buf.b.position(0);
+ buf.b.limit(buf.size());
+ }
+
+ @Override
+ public int endWrite(Buffer buf)
+ {
+ // Once the request is sent, read the response
+ return buf.b.hasRemaining() ? SocketOperation.Write : SocketOperation.Read;
+ }
+
+ @Override
+ public void beginRead(Buffer buf)
+ {
+ //
+ // Read the HTTP response
+ //
+ buf.resize(7, true); // Enough space for reading at least HTTP1.1
+ buf.b.position(0);
+ }
+
+ @Override
+ public int endRead(Buffer buf)
+ {
+ //
+ // Check if we received the full HTTP response, if not, continue
+ // reading otherwise we're done.
+ //
+ int end = new HttpParser().isCompleteMessage(buf.b, 0, buf.b.position());
+ if(end < 0 && !buf.b.hasRemaining())
+ {
+ //
+ // Read one more byte, we can't easily read bytes in advance
+ // since the transport implenentation might be be able to read
+ // the data from the memory instead of the socket.
+ //
+ buf.resize(buf.size() + 1, true);
+ return SocketOperation.Read;
+ }
+ return SocketOperation.None;
+ }
+
+ @Override
+ public void finish(Buffer readBuffer, Buffer writeBuffer)
+ {
+ HttpParser parser = new HttpParser();
+ parser.parse(readBuffer.b, 0, readBuffer.b.position());
+ if(parser.status() != 200)
+ {
+ throw new Ice.ConnectFailedException();
+ }
+ }
+
+ @Override
+ public NetworkProxy resolveHost(int protocol)
+ {
+ assert(_host != null);
+ return new HTTPNetworkProxy(Network.getAddresses(_host,
+ _port,
+ protocol,
+ Ice.EndpointSelectionType.Random,
+ false,
+ true).get(0),
+ protocol);
+ }
+
+ @Override
+ public java.net.InetSocketAddress getAddress()
+ {
+ assert(_address != null); // Host must be resolved.
+ return _address;
+ }
+
+ @Override
+ public String getName()
+ {
+ return "HTTP";
+ }
+
+ @Override
+ public int getProtocolSupport()
+ {
+ return _protocolSupport;
+ }
+
+ private String _host;
+ private int _port;
+ private java.net.InetSocketAddress _address;
+ private int _protocolSupport;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/HashUtil.java b/java-compat/src/Ice/src/main/java/IceInternal/HashUtil.java
new file mode 100644
index 00000000000..fc931e8294f
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/HashUtil.java
@@ -0,0 +1,120 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class HashUtil
+{
+ public static int
+ hashAdd(int hashCode, boolean value)
+ {
+ return ((hashCode << 5) + hashCode) ^ (value ? 0 : 1);
+ }
+
+ public static int
+ hashAdd(int hashCode, short value)
+ {
+ return ((hashCode << 5) + hashCode) ^ (int)(2654435761l * value);
+ }
+
+ public static int
+ hashAdd(int hashCode, byte value)
+ {
+ return ((hashCode << 5) + hashCode) ^ (int)(2654435761l * value);
+ }
+
+ public static int
+ hashAdd(int hashCode, int value)
+ {
+ return ((hashCode << 5) + hashCode) ^ (int)(2654435761l * value);
+ }
+
+ public static int
+ hashAdd(int hashCode, long value)
+ {
+ return ((hashCode << 5) + hashCode) ^ (int)(value ^ (value >>> 32));
+ }
+
+ public static int
+ hashAdd(int hashCode, float value)
+ {
+ return ((hashCode << 5) + hashCode) ^ Float.floatToIntBits(value);
+ }
+
+ public static int
+ hashAdd(int hashCode, double value)
+ {
+ long v = Double.doubleToLongBits(value);
+ return ((hashCode << 5) + hashCode) ^ (int)(v ^ (v >>> 32));
+ }
+
+ public static int
+ hashAdd(int hashCode, java.lang.Object value)
+ {
+ if(value != null)
+ {
+ hashCode = ((hashCode << 5) + hashCode) ^ value.hashCode();
+ }
+ return hashCode;
+ }
+
+ public static int
+ hashAdd(int hashCode, boolean[] arr)
+ {
+ return ((hashCode << 5) + hashCode) ^ java.util.Arrays.hashCode(arr);
+ }
+
+ public static int
+ hashAdd(int hashCode, byte[] arr)
+ {
+ return ((hashCode << 5) + hashCode) ^ java.util.Arrays.hashCode(arr);
+ }
+
+ public static int
+ hashAdd(int hashCode, char[] arr)
+ {
+ return ((hashCode << 5) + hashCode) ^ java.util.Arrays.hashCode(arr);
+ }
+
+ public static int
+ hashAdd(int hashCode, double[] arr)
+ {
+ return ((hashCode << 5) + hashCode) ^ java.util.Arrays.hashCode(arr);
+ }
+
+ public static int
+ hashAdd(int hashCode, float[] arr)
+ {
+ return ((hashCode << 5) + hashCode) ^ java.util.Arrays.hashCode(arr);
+ }
+
+ public static int
+ hashAdd(int hashCode, int[] arr)
+ {
+ return ((hashCode << 5) + hashCode) ^ java.util.Arrays.hashCode(arr);
+ }
+
+ public static int
+ hashAdd(int hashCode, long[] arr)
+ {
+ return ((hashCode << 5) + hashCode) ^ java.util.Arrays.hashCode(arr);
+ }
+
+ public static int
+ hashAdd(int hashCode, Object[] arr)
+ {
+ return ((hashCode << 5) + hashCode) ^ java.util.Arrays.hashCode(arr);
+ }
+
+ public static int
+ hashAdd(int hashCode, short[] arr)
+ {
+ return ((hashCode << 5) + hashCode) ^ java.util.Arrays.hashCode(arr);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/HttpParser.java b/java-compat/src/Ice/src/main/java/IceInternal/HttpParser.java
new file mode 100644
index 00000000000..999b2a62430
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/HttpParser.java
@@ -0,0 +1,732 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class HttpParser
+{
+ HttpParser()
+ {
+ _type = Type.Unknown;
+ _versionMajor = 0;
+ _versionMinor = 0;
+ _status = 0;
+ _state = State.Init;
+ }
+
+ private enum Type
+ {
+ Unknown,
+ Request,
+ Response
+ }
+
+ int isCompleteMessage(java.nio.ByteBuffer buf, int begin, int end)
+ {
+ int p = begin;
+
+ //
+ // Skip any leading CR-LF characters.
+ //
+ while(p < end)
+ {
+ byte ch = buf.get(p);
+ if(ch != (byte)'\r' && ch != (byte)'\n')
+ {
+ break;
+ }
+ ++p;
+ }
+
+ //
+ // Look for adjacent CR-LF/CR-LF or LF/LF.
+ //
+ boolean seenFirst = false;
+ while(p < end)
+ {
+ byte ch = buf.get(p++);
+ if(ch == (byte)'\n')
+ {
+ if(seenFirst)
+ {
+ return p;
+ }
+ else
+ {
+ seenFirst = true;
+ }
+ }
+ else if(ch != (byte)'\r')
+ {
+ seenFirst = false;
+ }
+ }
+
+ return -1;
+ }
+
+ boolean parse(java.nio.ByteBuffer buf, int begin, int end)
+ {
+ int p = begin;
+ int start = 0;
+ final char CR = '\r';
+ final char LF = '\n';
+
+ if(_state == State.Complete)
+ {
+ _state = State.Init;
+ }
+
+ while(p != end && _state != State.Complete)
+ {
+ char c = (char)buf.get(p);
+
+ switch(_state)
+ {
+ case Init:
+ {
+ _method.setLength(0);
+ _uri.setLength(0);
+ _versionMajor = -1;
+ _versionMinor = -1;
+ _status = -1;
+ _reason = "";
+ _headers.clear();
+ _state = State.Type;
+ continue;
+ }
+ case Type:
+ {
+ if(c == CR || c == LF)
+ {
+ break;
+ }
+ else if(c == 'H')
+ {
+ //
+ // Could be the start of "HTTP/1.1" or "HEAD".
+ //
+ _state = State.TypeCheck;
+ break;
+ }
+ else
+ {
+ _state = State.Request;
+ continue;
+ }
+ }
+ case TypeCheck:
+ {
+ if(c == 'T') // Continuing "H_T_TP/1.1"
+ {
+ _state = State.Response;
+ }
+ else if(c == 'E') // Expecting "HEAD"
+ {
+ _state = State.Request;
+ _method.append('H');
+ _method.append('E');
+ }
+ else
+ {
+ throw new WebSocketException("malformed request or response");
+ }
+ break;
+ }
+ case Request:
+ {
+ _type = Type.Request;
+ _state = State.RequestMethod;
+ continue;
+ }
+ case RequestMethod:
+ {
+ if(c == ' ' || c == CR || c == LF)
+ {
+ _state = State.RequestMethodSP;
+ continue;
+ }
+ _method.append(c);
+ break;
+ }
+ case RequestMethodSP:
+ {
+ if(c == ' ')
+ {
+ break;
+ }
+ else if(c == CR || c == LF)
+ {
+ throw new WebSocketException("malformed request");
+ }
+ _state = State.RequestURI;
+ continue;
+ }
+ case RequestURI:
+ {
+ if(c == ' ' || c == CR || c == LF)
+ {
+ _state = State.RequestURISP;
+ continue;
+ }
+ _uri.append(c);
+ break;
+ }
+ case RequestURISP:
+ {
+ if(c == ' ')
+ {
+ break;
+ }
+ else if(c == CR || c == LF)
+ {
+ throw new WebSocketException("malformed request");
+ }
+ _state = State.Version;
+ continue;
+ }
+ case RequestLF:
+ {
+ if(c != LF)
+ {
+ throw new WebSocketException("malformed request");
+ }
+ _state = State.HeaderFieldStart;
+ break;
+ }
+ case HeaderFieldStart:
+ {
+ //
+ // We've already seen a LF to reach this state.
+ //
+ // Another CR or LF indicates the end of the header fields.
+ //
+ if(c == CR)
+ {
+ _state = State.HeaderFieldEndLF;
+ break;
+ }
+ else if(c == LF)
+ {
+ _state = State.Complete;
+ break;
+ }
+ else if(c == ' ')
+ {
+ //
+ // Could be a continuation line.
+ //
+ _state = State.HeaderFieldContStart;
+ break;
+ }
+
+ _state = State.HeaderFieldNameStart;
+ continue;
+ }
+ case HeaderFieldContStart:
+ {
+ if(c == ' ')
+ {
+ break;
+ }
+
+ _state = State.HeaderFieldCont;
+ start = p;
+ continue;
+ }
+ case HeaderFieldCont:
+ {
+ if(c == CR || c == LF)
+ {
+ if(p > start)
+ {
+ if(_headerName.isEmpty())
+ {
+ throw new WebSocketException("malformed header");
+ }
+ String s = _headers.get(_headerName);
+ assert(s != null);
+ StringBuffer newValue = new StringBuffer(s);
+ newValue.append(' ');
+ for(int i = start; i < p; ++i)
+ {
+ newValue.append((char)buf.get(i));
+ }
+ _headers.put(_headerName, newValue.toString());
+ _state = c == CR ? State.HeaderFieldLF : State.HeaderFieldStart;
+ }
+ else
+ {
+ //
+ // Could mark the end of the header fields.
+ //
+ _state = c == CR ? State.HeaderFieldEndLF : State.Complete;
+ }
+ }
+
+ break;
+ }
+ case HeaderFieldNameStart:
+ {
+ assert(c != ' ');
+ start = p;
+ _headerName = "";
+ _state = State.HeaderFieldName;
+ continue;
+ }
+ case HeaderFieldName:
+ {
+ if(c == ' ' || c == ':')
+ {
+ _state = State.HeaderFieldNameEnd;
+ continue;
+ }
+ else if(c == CR || c == LF)
+ {
+ throw new WebSocketException("malformed header");
+ }
+ break;
+ }
+ case HeaderFieldNameEnd:
+ {
+ if(_headerName.isEmpty())
+ {
+ StringBuffer str = new StringBuffer();
+ for(int i = start; i < p; ++i)
+ {
+ str.append((char)buf.get(i));
+ }
+ _headerName = str.toString().toLowerCase();
+ //
+ // Add a placeholder entry if necessary.
+ //
+ if(!_headers.containsKey(_headerName))
+ {
+ _headers.put(_headerName, "");
+ _headerNames.put(_headerName, str.toString());
+ }
+ }
+
+ if(c == ' ')
+ {
+ break;
+ }
+ else if(c != ':' || p == start)
+ {
+ throw new WebSocketException("malformed header");
+ }
+
+ _state = State.HeaderFieldValueStart;
+ break;
+ }
+ case HeaderFieldValueStart:
+ {
+ if(c == ' ')
+ {
+ break;
+ }
+
+ //
+ // Check for "Name:\r\n"
+ //
+ if(c == CR)
+ {
+ _state = State.HeaderFieldLF;
+ break;
+ }
+ else if(c == LF)
+ {
+ _state = State.HeaderFieldStart;
+ break;
+ }
+
+ start = p;
+ _state = State.HeaderFieldValue;
+ continue;
+ }
+ case HeaderFieldValue:
+ {
+ if(c == CR || c == LF)
+ {
+ _state = State.HeaderFieldValueEnd;
+ continue;
+ }
+ break;
+ }
+ case HeaderFieldValueEnd:
+ {
+ assert(c == CR || c == LF);
+ if(p > start)
+ {
+ StringBuffer str = new StringBuffer();
+ for(int i = start; i < p; ++i)
+ {
+ str.append((char)buf.get(i));
+ }
+ String s = _headers.get(_headerName);
+ if(s == null || s.length() == 0)
+ {
+ _headers.put(_headerName, str.toString());
+ }
+ else
+ {
+ _headers.put(_headerName, s + ", " + str.toString());
+ }
+ }
+
+ if(c == CR)
+ {
+ _state = State.HeaderFieldLF;
+ }
+ else
+ {
+ _state = State.HeaderFieldStart;
+ }
+ break;
+ }
+ case HeaderFieldLF:
+ {
+ if(c != LF)
+ {
+ throw new WebSocketException("malformed header");
+ }
+ _state = State.HeaderFieldStart;
+ break;
+ }
+ case HeaderFieldEndLF:
+ {
+ if(c != LF)
+ {
+ throw new WebSocketException("malformed header");
+ }
+ _state = State.Complete;
+ break;
+ }
+ case Version:
+ {
+ if(c != 'H')
+ {
+ throw new WebSocketException("malformed version");
+ }
+ _state = State.VersionH;
+ break;
+ }
+ case VersionH:
+ {
+ if(c != 'T')
+ {
+ throw new WebSocketException("malformed version");
+ }
+ _state = State.VersionHT;
+ break;
+ }
+ case VersionHT:
+ {
+ if(c != 'T')
+ {
+ throw new WebSocketException("malformed version");
+ }
+ _state = State.VersionHTT;
+ break;
+ }
+ case VersionHTT:
+ {
+ if(c != 'P')
+ {
+ throw new WebSocketException("malformed version");
+ }
+ _state = State.VersionHTTP;
+ break;
+ }
+ case VersionHTTP:
+ {
+ if(c != '/')
+ {
+ throw new WebSocketException("malformed version");
+ }
+ _state = State.VersionMajor;
+ break;
+ }
+ case VersionMajor:
+ {
+ if(c == '.')
+ {
+ if(_versionMajor == -1)
+ {
+ throw new WebSocketException("malformed version");
+ }
+ _state = State.VersionMinor;
+ break;
+ }
+ else if(c < '0' || c > '9')
+ {
+ throw new WebSocketException("malformed version");
+ }
+ if(_versionMajor == -1)
+ {
+ _versionMajor = 0;
+ }
+ _versionMajor *= 10;
+ _versionMajor += c - '0';
+ break;
+ }
+ case VersionMinor:
+ {
+ if(c == CR)
+ {
+ if(_versionMinor == -1 || _type != Type.Request)
+ {
+ throw new WebSocketException("malformed version");
+ }
+ _state = State.RequestLF;
+ break;
+ }
+ else if(c == LF)
+ {
+ if(_versionMinor == -1 || _type != Type.Request)
+ {
+ throw new WebSocketException("malformed version");
+ }
+ _state = State.HeaderFieldStart;
+ break;
+ }
+ else if(c == ' ')
+ {
+ if(_versionMinor == -1 || _type != Type.Response)
+ {
+ throw new WebSocketException("malformed version");
+ }
+ _state = State.ResponseVersionSP;
+ break;
+ }
+ else if(c < '0' || c > '9')
+ {
+ throw new WebSocketException("malformed version");
+ }
+ if(_versionMinor == -1)
+ {
+ _versionMinor = 0;
+ }
+ _versionMinor *= 10;
+ _versionMinor += c - '0';
+ break;
+ }
+ case Response:
+ {
+ _type = Type.Response;
+ _state = State.VersionHT;
+ continue;
+ }
+ case ResponseVersionSP:
+ {
+ if(c == ' ')
+ {
+ break;
+ }
+
+ _state = State.ResponseStatus;
+ continue;
+ }
+ case ResponseStatus:
+ {
+ // TODO: Is reason string optional?
+ if(c == CR)
+ {
+ if(_status == -1)
+ {
+ throw new WebSocketException("malformed response status");
+ }
+ _state = State.ResponseLF;
+ break;
+ }
+ else if(c == LF)
+ {
+ if(_status == -1)
+ {
+ throw new WebSocketException("malformed response status");
+ }
+ _state = State.HeaderFieldStart;
+ break;
+ }
+ else if(c == ' ')
+ {
+ if(_status == -1)
+ {
+ throw new WebSocketException("malformed response status");
+ }
+ _state = State.ResponseReasonStart;
+ break;
+ }
+ else if(c < '0' || c > '9')
+ {
+ throw new WebSocketException("malformed response status");
+ }
+ if(_status == -1)
+ {
+ _status = 0;
+ }
+ _status *= 10;
+ _status += c - '0';
+ break;
+ }
+ case ResponseReasonStart:
+ {
+ //
+ // Skip leading spaces.
+ //
+ if(c == ' ')
+ {
+ break;
+ }
+
+ _state = State.ResponseReason;
+ start = p;
+ continue;
+ }
+ case ResponseReason:
+ {
+ if(c == CR || c == LF)
+ {
+ if(p > start)
+ {
+ StringBuffer str = new StringBuffer();
+ for(int i = start; i < p; ++i)
+ {
+ str.append((char)buf.get(i));
+ }
+ _reason = str.toString();
+ }
+ _state = c == CR ? State.ResponseLF : State.HeaderFieldStart;
+ }
+
+ break;
+ }
+ case ResponseLF:
+ {
+ if(c != LF)
+ {
+ throw new WebSocketException("malformed status line");
+ }
+ _state = State.HeaderFieldStart;
+ break;
+ }
+ case Complete:
+ {
+ assert(false); // Shouldn't reach
+ }
+ }
+
+ ++p;
+ }
+
+ return _state == State.Complete;
+ }
+
+ String uri()
+ {
+ assert(_type == Type.Request);
+ return _uri.toString();
+ }
+
+ int versionMajor()
+ {
+ return _versionMajor;
+ }
+
+ int versionMinor()
+ {
+ return _versionMinor;
+ }
+
+ int status()
+ {
+ return _status;
+ }
+
+ String reason()
+ {
+ return _reason;
+ }
+
+ String getHeader(String name, boolean toLower)
+ {
+ String s = _headers.get(name.toLowerCase());
+ if(s != null)
+ {
+ return toLower ? s.trim().toLowerCase() : s.trim();
+ }
+
+ return null;
+ }
+
+ java.util.Map<String, String> getHeaders()
+ {
+ java.util.Map<String, String> headers = new java.util.HashMap<String, String>();
+ for(java.util.Map.Entry<String, String> entry : _headers.entrySet())
+ {
+ headers.put(_headerNames.get(entry.getKey()), entry.getValue().trim()); // Return original header name.
+ }
+ return headers;
+ }
+
+ private Type _type;
+
+ private StringBuffer _method = new StringBuffer();
+ private StringBuffer _uri = new StringBuffer();
+
+ private java.util.Map<String, String> _headers = new java.util.HashMap<String, String>();
+ private java.util.Map<String, String> _headerNames = new java.util.HashMap<String, String>();
+ private String _headerName = "";
+
+ private int _versionMajor;
+ private int _versionMinor;
+
+ private int _status;
+ private String _reason;
+
+ private enum State
+ {
+ Init,
+ Type,
+ TypeCheck,
+ Request,
+ RequestMethod,
+ RequestMethodSP,
+ RequestURI,
+ RequestURISP,
+ RequestLF,
+ HeaderFieldStart,
+ HeaderFieldContStart,
+ HeaderFieldCont,
+ HeaderFieldNameStart,
+ HeaderFieldName,
+ HeaderFieldNameEnd,
+ HeaderFieldValueStart,
+ HeaderFieldValue,
+ HeaderFieldValueEnd,
+ HeaderFieldLF,
+ HeaderFieldEndLF,
+ Version,
+ VersionH,
+ VersionHT,
+ VersionHTT,
+ VersionHTTP,
+ VersionMajor,
+ VersionMinor,
+ Response,
+ ResponseVersionSP,
+ ResponseStatus,
+ ResponseReasonStart,
+ ResponseReason,
+ ResponseLF,
+ Complete
+ }
+
+ private State _state;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/IPEndpointI.java b/java-compat/src/Ice/src/main/java/IceInternal/IPEndpointI.java
new file mode 100644
index 00000000000..7a6057800c6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/IPEndpointI.java
@@ -0,0 +1,377 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class IPEndpointI extends EndpointI
+{
+ protected IPEndpointI(ProtocolInstance instance, String host, int port, java.net.InetSocketAddress sourceAddr,
+ String connectionId)
+ {
+ _instance = instance;
+ _host = host;
+ _port = port;
+ _sourceAddr = sourceAddr;
+ _connectionId = connectionId;
+ _hashInitialized = false;
+ }
+
+ protected IPEndpointI(ProtocolInstance instance)
+ {
+ _instance = instance;
+ _host = null;
+ _port = 0;
+ _sourceAddr = null;
+ _connectionId = "";
+ _hashInitialized = false;
+ }
+
+ protected IPEndpointI(ProtocolInstance instance, Ice.InputStream s)
+ {
+ _instance = instance;
+ _host = s.readString();
+ _port = s.readInt();
+ _sourceAddr = null;
+ _connectionId = "";
+ _hashInitialized = false;
+ }
+
+ @Override
+ public Ice.EndpointInfo getInfo()
+ {
+ Ice.IPEndpointInfo info = new Ice.IPEndpointInfo()
+ {
+ @Override
+ public short type()
+ {
+ return IPEndpointI.this.type();
+ }
+
+ @Override
+ public boolean datagram()
+ {
+ return IPEndpointI.this.datagram();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return IPEndpointI.this.secure();
+ }
+ };
+ fillEndpointInfo(info);
+ return info;
+ }
+
+ @Override
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return _instance.secure();
+ }
+
+ @Override
+ public String connectionId()
+ {
+ return _connectionId;
+ }
+
+ @Override
+ public EndpointI connectionId(String connectionId)
+ {
+ if(connectionId.equals(_connectionId))
+ {
+ return this;
+ }
+ else
+ {
+ return createEndpoint(_host, _port, connectionId);
+ }
+ }
+
+ @Override
+ public void connectors_async(Ice.EndpointSelectionType selType, EndpointI_connectors callback)
+ {
+ _instance.resolve(_host, _port, selType, this, callback);
+ }
+
+ @Override
+ public java.util.List<EndpointI> expand()
+ {
+ java.util.List<EndpointI> endps = new java.util.ArrayList<EndpointI>();
+ java.util.List<String> hosts = Network.getHostsForEndpointExpand(_host, _instance.protocolSupport(), false);
+ if(hosts == null || hosts.isEmpty())
+ {
+ endps.add(this);
+ }
+ else
+ {
+ for(String h : hosts)
+ {
+ endps.add(createEndpoint(h, _port, _connectionId));
+ }
+ }
+ return endps;
+ }
+
+ @Override
+ public boolean equivalent(EndpointI endpoint)
+ {
+ if(!(endpoint instanceof IPEndpointI))
+ {
+ return false;
+ }
+ IPEndpointI ipEndpointI = (IPEndpointI)endpoint;
+ return ipEndpointI.type() == type() && ipEndpointI._host.equals(_host) && ipEndpointI._port == _port &&
+ Network.compareAddress(ipEndpointI._sourceAddr, _sourceAddr) == 0;
+ }
+
+ public java.util.List<Connector> connectors(java.util.List<java.net.InetSocketAddress> addresses,
+ NetworkProxy proxy)
+ {
+ java.util.List<Connector> connectors = new java.util.ArrayList<Connector>();
+ for(java.net.InetSocketAddress p : addresses)
+ {
+ connectors.add(createConnector(p, proxy));
+ }
+ return connectors;
+ }
+
+ @Override
+ synchronized public int hashCode()
+ {
+ if(!_hashInitialized)
+ {
+ _hashValue = 5381;
+ _hashValue = HashUtil.hashAdd(_hashValue, type());
+ _hashValue = hashInit(_hashValue);
+ _hashInitialized = true;
+ }
+ return _hashValue;
+ }
+
+ @Override
+ public String options()
+ {
+ //
+ // 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.
+ //
+ String s = "";
+
+ if(_host != null && _host.length() > 0)
+ {
+ s += " -h ";
+ boolean addQuote = _host.indexOf(':') != -1;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ s += _host;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ }
+
+ s += " -p " + _port;
+
+ if(_sourceAddr != null)
+ {
+ s += " --sourceAddress " + _sourceAddr.getAddress().getHostAddress();
+ }
+
+ return s;
+ }
+
+ @Override
+ public int compareTo(EndpointI obj) // From java.lang.Comparable
+ {
+ if(!(obj instanceof IPEndpointI))
+ {
+ return type() < obj.type() ? -1 : 1;
+ }
+
+ IPEndpointI p = (IPEndpointI)obj;
+ if(this == p)
+ {
+ return 0;
+ }
+
+ int v = _host.compareTo(p._host);
+ if(v != 0)
+ {
+ return v;
+ }
+
+ if(_port < p._port)
+ {
+ return -1;
+ }
+ else if(p._port < _port)
+ {
+ return 1;
+ }
+
+ int rc = Network.compareAddress(_sourceAddr, p._sourceAddr);
+ if(rc != 0)
+ {
+ return rc;
+ }
+
+ return _connectionId.compareTo(p._connectionId);
+ }
+
+ @Override
+ public void streamWriteImpl(Ice.OutputStream s)
+ {
+ s.writeString(_host);
+ s.writeInt(_port);
+ }
+
+ public int hashInit(int h)
+ {
+ h = HashUtil.hashAdd(h, _host);
+ h = HashUtil.hashAdd(h, _port);
+ if(_sourceAddr != null)
+ {
+ h = HashUtil.hashAdd(h, _sourceAddr.getAddress().getHostAddress());
+ }
+ h = HashUtil.hashAdd(h, _connectionId);
+ return h;
+ }
+
+ public void fillEndpointInfo(Ice.IPEndpointInfo info)
+ {
+ info.timeout = timeout();
+ info.compress = compress();
+ info.host = _host;
+ info.port = _port;
+ info.sourceAddress = _sourceAddr == null ? "" : _sourceAddr.getAddress().getHostAddress();
+ }
+
+ public void initWithOptions(java.util.ArrayList<String> args, boolean oaEndpoint)
+ {
+ super.initWithOptions(args);
+
+ if(_host == null || _host.length() == 0)
+ {
+ _host = _instance.defaultHost();
+ }
+ else if(_host.equals("*"))
+ {
+ if(oaEndpoint)
+ {
+ _host = "";
+ }
+ else
+ {
+ throw new Ice.EndpointParseException("`-h *' not valid for proxy endpoint `" + toString() + "'");
+ }
+ }
+
+ if(_host == null)
+ {
+ _host = "";
+ }
+
+ if(_sourceAddr == null)
+ {
+ if (!oaEndpoint)
+ {
+ _sourceAddr = _instance.defaultSourceAddress();
+ }
+ }
+ else if(oaEndpoint)
+ {
+ throw new Ice.EndpointParseException("`--sourceAddress' not valid for object adapter endpoint `" +
+ toString() + "'");
+ }
+ }
+
+ @Override
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ if(option.equals("-h"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -h option in endpoint " + endpoint);
+ }
+ _host = argument;
+ }
+ else if(option.equals("-p"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -p option in endpoint " + endpoint);
+ }
+
+ try
+ {
+ _port = Integer.parseInt(argument);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid port value `" + argument +
+ "' in endpoint " + endpoint);
+ }
+
+ if(_port < 0 || _port > 65535)
+ {
+ throw new Ice.EndpointParseException("port value `" + argument +
+ "' out of range in endpoint " + endpoint);
+ }
+ }
+ else if(option.equals("--sourceAddress"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for --sourceAddress option in endpoint " +
+ endpoint);
+ }
+ _sourceAddr = Network.getNumericAddress(argument);
+ if(_sourceAddr == null)
+ {
+ throw new Ice.EndpointParseException(
+ "invalid IP address provided for --sourceAddress option in endpoint " + endpoint);
+ }
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+ }
+
+ protected abstract Connector createConnector(java.net.InetSocketAddress addr, NetworkProxy proxy);
+ protected abstract IPEndpointI createEndpoint(String host, int port, String connectionId);
+
+ protected ProtocolInstance _instance;
+ protected String _host;
+ protected int _port;
+ protected java.net.InetSocketAddress _sourceAddr;
+ protected String _connectionId;
+ private boolean _hashInitialized;
+ private int _hashValue;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Incoming.java b/java-compat/src/Ice/src/main/java/IceInternal/Incoming.java
new file mode 100644
index 00000000000..6a7babc0c36
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Incoming.java
@@ -0,0 +1,415 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import Ice.Instrumentation.CommunicatorObserver;
+
+final public class Incoming extends IncomingBase implements Ice.Request
+{
+ public
+ Incoming(Instance instance, ResponseHandler responseHandler, Ice.ConnectionI connection, Ice.ObjectAdapter adapter,
+ boolean response, byte compress, int requestId)
+ {
+ super(instance, responseHandler, connection, adapter, response, compress, requestId);
+
+ //
+ // Prepare the response if necessary.
+ //
+ if(response)
+ {
+ _os.writeBlob(IceInternal.Protocol.replyHdr);
+
+ //
+ // Add the request ID.
+ //
+ _os.writeInt(requestId);
+ }
+ }
+
+ @Override
+ public Ice.Current
+ getCurrent()
+ {
+ return _current;
+ }
+
+ //
+ // These functions allow this object to be reused, rather than reallocated.
+ //
+ @Override
+ public void
+ reset(Instance instance, ResponseHandler handler, Ice.ConnectionI connection, Ice.ObjectAdapter adapter,
+ boolean response, byte compress, int requestId)
+ {
+ _cb = null;
+ _inParamPos = -1;
+
+ super.reset(instance, handler, connection, adapter, response, compress, requestId);
+
+ //
+ // Prepare the response if necessary.
+ //
+ if(response)
+ {
+ _os.writeBlob(IceInternal.Protocol.replyHdr);
+
+ //
+ // Add the request ID.
+ //
+ _os.writeInt(requestId);
+ }
+ }
+
+ @Override
+ public void
+ reclaim()
+ {
+ _cb = null;
+ _inParamPos = -1;
+
+ super.reclaim();
+ }
+
+ public void
+ invoke(ServantManager servantManager, Ice.InputStream stream)
+ {
+ _is = stream;
+
+ int start = _is.pos();
+
+ //
+ // Read the current.
+ //
+ _current.id.__read(_is);
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ String[] facetPath = _is.readStringSeq();
+ if(facetPath.length > 0)
+ {
+ if(facetPath.length > 1)
+ {
+ throw new Ice.MarshalException();
+ }
+ _current.facet = facetPath[0];
+ }
+ else
+ {
+ _current.facet = "";
+ }
+
+ _current.operation = _is.readString();
+ _current.mode = Ice.OperationMode.values()[_is.readByte()];
+ _current.ctx = new java.util.HashMap<String, String>();
+ int sz = _is.readSize();
+ while(sz-- > 0)
+ {
+ String first = _is.readString();
+ String second = _is.readString();
+ _current.ctx.put(first, second);
+ }
+
+ CommunicatorObserver obsv = _instance.initializationData().observer;
+ if(obsv != null)
+ {
+ // Read the parameter encapsulation size.
+ int size = _is.readInt();
+ _is.pos(_is.pos() - 4);
+
+ _observer = obsv.getDispatchObserver(_current, _is.pos() - start + size);
+ if(_observer != null)
+ {
+ _observer.attach();
+ }
+ }
+
+ //
+ // 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)
+ {
+ _servant = servantManager.findServant(_current.id, _current.facet);
+ if(_servant == null)
+ {
+ _locator = servantManager.findServantLocator(_current.id.category);
+ if(_locator == null && _current.id.category.length() > 0)
+ {
+ _locator = servantManager.findServantLocator("");
+ }
+
+ if(_locator != null)
+ {
+ try
+ {
+ _servant = _locator.locate(_current, _cookie);
+ }
+ catch(Ice.UserException ex)
+ {
+ Ice.EncodingVersion encoding = _is.skipEncapsulation(); // Required for batch requests.
+
+ if(_observer != null)
+ {
+ _observer.userException();
+ }
+
+ if(_response)
+ {
+ _os.writeByte(ReplyStatus.replyUserException);
+ _os.startEncapsulation(encoding, Ice.FormatType.DefaultFormat);
+ _os.writeException(ex);
+ _os.endEncapsulation();
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, false);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ _responseHandler = null;
+ return;
+ }
+ catch(java.lang.Exception ex)
+ {
+ _is.skipEncapsulation(); // Required for batch requests.
+ __handleException(ex, false);
+ return;
+ }
+ catch(java.lang.Error ex)
+ {
+ _is.skipEncapsulation(); // Required for batch requests.
+ __handleError(ex, false); // Always throws.
+ }
+ }
+ }
+ }
+
+ try
+ {
+ if(_servant != null)
+ {
+ if(_instance.useApplicationClassLoader())
+ {
+ Thread.currentThread().setContextClassLoader(_servant.getClass().getClassLoader());
+ }
+
+ try
+ {
+ //
+ // DispatchAsync is a "pseudo dispatch status", used internally only
+ // to indicate async dispatch.
+ //
+ if(_servant.__dispatch(this, _current) == Ice.DispatchStatus.DispatchAsync)
+ {
+ //
+ // If this was an asynchronous dispatch, we're done here.
+ //
+ return;
+ }
+ }
+ finally
+ {
+ if(_instance.useApplicationClassLoader())
+ {
+ Thread.currentThread().setContextClassLoader(null);
+ }
+ }
+
+ if(_locator != null && !__servantLocatorFinished(false))
+ {
+ return;
+ }
+ }
+ else
+ {
+ //
+ // Skip the input parameters, this is required for reading
+ // the next batch request if dispatching batch requests.
+ //
+ _is.skipEncapsulation();
+
+ if(servantManager != null && servantManager.hasServant(_current.id))
+ {
+ throw new Ice.FacetNotExistException(_current.id, _current.facet, _current.operation);
+ }
+ else
+ {
+ throw new Ice.ObjectNotExistException(_current.id, _current.facet, _current.operation);
+ }
+ }
+ }
+ catch(java.lang.Exception ex)
+ {
+ if(_servant != null && _locator != null && !__servantLocatorFinished(false))
+ {
+ return;
+ }
+ __handleException(ex, false);
+ return;
+ }
+ catch(java.lang.Error ex)
+ {
+ if(_servant != null && _locator != null && !__servantLocatorFinished(false))
+ {
+ return;
+ }
+ __handleError(ex, false); // Always throws.
+ }
+
+ //
+ // 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.
+ //
+
+ assert(_responseHandler != null);
+
+ if(_response)
+ {
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, false);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ _responseHandler = null;
+ }
+
+ public final void
+ push(Ice.DispatchInterceptorAsyncCallback cb)
+ {
+ if(_interceptorAsyncCallbackList == null)
+ {
+ _interceptorAsyncCallbackList = new java.util.LinkedList<Ice.DispatchInterceptorAsyncCallback>();
+ }
+
+ _interceptorAsyncCallbackList.addFirst(cb);
+ }
+
+ public final void
+ pop()
+ {
+ assert _interceptorAsyncCallbackList != null;
+ _interceptorAsyncCallbackList.removeFirst();
+ }
+
+ public final void
+ startOver()
+ {
+ if(_inParamPos == -1)
+ {
+ //
+ // That's the first startOver, so almost nothing to do
+ //
+ _inParamPos = _is.pos();
+ }
+ else
+ {
+ killAsync();
+
+ //
+ // Let's rewind _is and clean-up _os
+ //
+ _is.pos(_inParamPos);
+ if(_response)
+ {
+ _os.resize(Protocol.headerSize + 4);
+ }
+ }
+ }
+
+ public final void
+ killAsync()
+ {
+ //
+ // Always runs in the dispatch thread
+ //
+ if(_cb != null)
+ {
+ //
+ // May raise ResponseSentException
+ //
+ _cb.__deactivate(this);
+ _cb = null;
+ }
+ }
+
+ public final Ice.InputStream
+ startReadParams()
+ {
+ //
+ // Remember the encoding used by the input parameters, we'll
+ // encode the response parameters with the same encoding.
+ //
+ _current.encoding = _is.startEncapsulation();
+ return _is;
+ }
+
+ public final void
+ endReadParams()
+ {
+ _is.endEncapsulation();
+ }
+
+ public final void
+ readEmptyParams()
+ {
+ _current.encoding = _is.skipEmptyEncapsulation();
+ }
+
+ public final byte[]
+ readParamEncaps()
+ {
+ _current.encoding = new Ice.EncodingVersion();
+ return _is.readEncapsulation(_current.encoding);
+ }
+
+ final void
+ setActive(IncomingAsync cb)
+ {
+ assert _cb == null;
+ _cb = cb;
+ }
+
+ final boolean
+ isRetriable()
+ {
+ return _inParamPos != -1;
+ }
+
+ public Incoming next; // For use by ConnectionI.
+
+ private Ice.InputStream _is;
+
+ private IncomingAsync _cb;
+ private int _inParamPos = -1;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/IncomingAsync.java b/java-compat/src/Ice/src/main/java/IceInternal/IncomingAsync.java
new file mode 100644
index 00000000000..7abed77651d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/IncomingAsync.java
@@ -0,0 +1,204 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class IncomingAsync extends IncomingBase implements Ice.AMDCallback
+{
+ public
+ IncomingAsync(Incoming in) // Adopts the argument. It must not be used afterwards.
+ {
+ super(in);
+ _retriable = in.isRetriable();
+
+ if(_retriable)
+ {
+ in.setActive(this);
+ _active = true;
+ }
+ }
+
+ @Override
+ public void
+ ice_exception(java.lang.Exception ex)
+ {
+ //
+ // Only call __exception if this incoming is not retriable or if
+ // all the interceptors return true and no response has been sent
+ // yet.
+ //
+
+ if(_retriable)
+ {
+ try
+ {
+ if(_interceptorAsyncCallbackList != null)
+ {
+ for(Ice.DispatchInterceptorAsyncCallback cb : _interceptorAsyncCallbackList)
+ {
+ if(!cb.exception(ex))
+ {
+ return;
+ }
+ }
+ }
+ }
+ catch(java.lang.RuntimeException exc)
+ {
+ return;
+ }
+
+ synchronized(this)
+ {
+ if(!_active)
+ {
+ return;
+ }
+ _active = false;
+ }
+ }
+
+ if(_responseHandler != null)
+ {
+ __exception(ex);
+ }
+ else
+ {
+ //
+ // Response has already been sent.
+ //
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ __warning(ex);
+ }
+ }
+ }
+
+ final void
+ __deactivate(Incoming in)
+ {
+ assert _retriable;
+
+ synchronized(this)
+ {
+ if(!_active)
+ {
+ //
+ // Since _deactivate can only be called on an active object,
+ // this means the response has already been sent (see __validateXXX below)
+ //
+ throw new Ice.ResponseSentException();
+ }
+ _active = false;
+ }
+
+ in.adopt(this);
+ }
+
+ final protected void
+ __response()
+ {
+ try
+ {
+ if(_locator != null && !__servantLocatorFinished(true))
+ {
+ return;
+ }
+
+ assert(_responseHandler != null);
+
+ if(_response)
+ {
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, true);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ _responseHandler = null;
+ }
+ catch(Ice.LocalException ex)
+ {
+ _responseHandler.invokeException(_current.requestId, ex, 1, true);
+ }
+ }
+
+ final protected void
+ __exception(java.lang.Exception exc)
+ {
+ try
+ {
+ if(_locator != null && !__servantLocatorFinished(true))
+ {
+ return;
+ }
+
+ __handleException(exc, true);
+ }
+ catch(Ice.LocalException ex)
+ {
+ _responseHandler.invokeException(_current.requestId, ex, 1, true);
+ }
+ }
+
+ final protected boolean
+ __validateResponse(boolean ok)
+ {
+ //
+ // Only returns true if this incoming is not retriable or if all
+ // the interceptors return true and no response has been sent
+ // yet. Upon getting a true return value, the caller should send
+ // the response.
+ //
+
+ if(_retriable)
+ {
+ try
+ {
+ if(_interceptorAsyncCallbackList != null)
+ {
+ for(Ice.DispatchInterceptorAsyncCallback cb : _interceptorAsyncCallbackList)
+ {
+ if(!cb.response(ok))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ catch(java.lang.RuntimeException ex)
+ {
+ return false;
+ }
+
+ synchronized(this)
+ {
+ if(!_active)
+ {
+ return false;
+ }
+ _active = false;
+ }
+ }
+ return true;
+ }
+
+ private final boolean _retriable;
+ private boolean _active = false; // only meaningful when _retriable == true
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java b/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java
new file mode 100644
index 00000000000..93c853c9853
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java
@@ -0,0 +1,663 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+class IncomingBase
+{
+ protected
+ IncomingBase(Instance instance, ResponseHandler handler, Ice.ConnectionI connection, Ice.ObjectAdapter adapter,
+ boolean response, byte compress, int requestId)
+ {
+ _instance = instance;
+ _responseHandler = handler;
+ _response = response;
+ _compress = compress;
+ if(_response)
+ {
+ _os = new Ice.OutputStream(instance, Protocol.currentProtocolEncoding);
+ }
+
+ _current = new Ice.Current();
+ _current.id = new Ice.Identity();
+ _current.adapter = adapter;
+ _current.con = connection;
+ _current.requestId = requestId;
+
+ _cookie = new Ice.LocalObjectHolder();
+ }
+
+ protected
+ IncomingBase(IncomingBase in) // Adopts the argument. It must not be used afterwards.
+ {
+ //
+ // We don't change _current as it's exposed by Ice::Request
+ //
+ _current = in._current;
+
+ //
+ // Deep copy
+ //
+ if(in._interceptorAsyncCallbackList != null)
+ {
+ //
+ // Copy, not just reference
+ //
+ _interceptorAsyncCallbackList =
+ new java.util.LinkedList<Ice.DispatchInterceptorAsyncCallback>(in._interceptorAsyncCallbackList);
+ }
+
+ adopt(in);
+ }
+
+ protected void
+ adopt(IncomingBase other)
+ {
+ _instance = other._instance;
+ //other._instance = null; // Don't reset _instance.
+
+ _observer = other._observer;
+ other._observer = null;
+
+ _servant = other._servant;
+ other._servant = null;
+
+ _locator = other._locator;
+ other._locator = null;
+
+ _cookie = other._cookie;
+ other._cookie = null;
+
+ _response = other._response;
+ other._response = false;
+
+ _compress = other._compress;
+ other._compress = 0;
+
+ //
+ // Adopt the stream - it creates less garbage.
+ //
+ _os = other._os;
+ other._os = null;
+
+ _responseHandler = other._responseHandler;
+ other._responseHandler = null;
+ }
+
+ public Ice.OutputStream
+ __startWriteParams(Ice.FormatType format)
+ {
+ if(!_response)
+ {
+ throw new Ice.MarshalException("can't marshal out parameters for oneway dispatch");
+ }
+
+ assert(_os.size() == Protocol.headerSize + 4); // Reply status position.
+ assert(_current.encoding != null); // Encoding for reply is known.
+ _os.writeByte((byte)0);
+ _os.startEncapsulation(_current.encoding, format);
+ return _os;
+ }
+
+ public void
+ __endWriteParams(boolean ok)
+ {
+ if(!ok && _observer != null)
+ {
+ _observer.userException();
+ }
+
+ assert(_response);
+
+ int save = _os.pos();
+ _os.pos(Protocol.headerSize + 4); // Reply status position.
+ _os.writeByte(ok ? ReplyStatus.replyOK : ReplyStatus.replyUserException);
+ _os.pos(save);
+ _os.endEncapsulation();
+ }
+
+ public void
+ __writeEmptyParams()
+ {
+ if(_response)
+ {
+ assert(_os.size() == Protocol.headerSize + 4); // Reply status position.
+ assert(_current.encoding != null); // Encoding for reply is known.
+ _os.writeByte(ReplyStatus.replyOK);
+ _os.writeEmptyEncapsulation(_current.encoding);
+ }
+ }
+
+ public void
+ __writeParamEncaps(byte[] v, boolean ok)
+ {
+ if(!ok && _observer != null)
+ {
+ _observer.userException();
+ }
+
+ if(_response)
+ {
+ assert(_os.size() == Protocol.headerSize + 4); // Reply status position.
+ assert(_current.encoding != null); // Encoding for reply is known.
+ _os.writeByte(ok ? ReplyStatus.replyOK : ReplyStatus.replyUserException);
+ if(v == null || v.length == 0)
+ {
+ _os.writeEmptyEncapsulation(_current.encoding);
+ }
+ else
+ {
+ _os.writeEncapsulation(v);
+ }
+ }
+ }
+
+ public void
+ __writeUserException(Ice.UserException ex, Ice.FormatType format)
+ {
+ Ice.OutputStream __os = __startWriteParams(format);
+ __os.writeException(ex);
+ __endWriteParams(false);
+ }
+
+ //
+ // These functions allow this object to be reused, rather than reallocated.
+ //
+ public void
+ reset(Instance instance, ResponseHandler handler, Ice.ConnectionI connection, Ice.ObjectAdapter adapter,
+ boolean response, byte compress, int requestId)
+ {
+ _instance = instance;
+
+ //
+ // Don't recycle the Current object, because servants may keep a reference to it.
+ //
+ _current = new Ice.Current();
+ _current.id = new Ice.Identity();
+ _current.adapter = adapter;
+ _current.con = connection;
+ _current.requestId = requestId;
+
+ if(_cookie == null)
+ {
+ _cookie = new Ice.LocalObjectHolder();
+ }
+
+ _response = response;
+
+ _compress = compress;
+
+ if(_response && _os == null)
+ {
+ _os = new Ice.OutputStream(instance, Protocol.currentProtocolEncoding);
+ }
+
+ _responseHandler = handler;
+
+ _interceptorAsyncCallbackList = null;
+ }
+
+ public void
+ reclaim()
+ {
+ _servant = null;
+
+ _locator = null;
+
+ if(_cookie != null)
+ {
+ _cookie.value = null;
+ }
+
+ _observer = null;
+
+ if(_os != null)
+ {
+ _os.reset();
+ }
+
+ _interceptorAsyncCallbackList = null;
+ }
+
+ final protected void
+ __warning(java.lang.Exception ex)
+ {
+ assert(_instance != null);
+
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ IceUtilInternal.OutputBase out = new IceUtilInternal.OutputBase(pw);
+ out.setUseTab(false);
+ out.print("dispatch exception:");
+ out.print("\nidentity: " + Ice.Util.identityToString(_current.id));
+ out.print("\nfacet: " + IceUtilInternal.StringUtil.escapeString(_current.facet, ""));
+ out.print("\noperation: " + _current.operation);
+ if(_current.con != null)
+ {
+ for(Ice.ConnectionInfo connInfo = _current.con.getInfo(); connInfo != null; connInfo = connInfo.underlying)
+ {
+ if(connInfo instanceof Ice.IPConnectionInfo)
+ {
+ Ice.IPConnectionInfo ipConnInfo = (Ice.IPConnectionInfo)connInfo;
+ out.print("\nremote host: " + ipConnInfo.remoteAddress + " remote port: " + ipConnInfo.remotePort);
+ }
+ }
+ }
+ out.print("\n");
+ ex.printStackTrace(pw);
+ pw.flush();
+ _instance.initializationData().logger.warning(sw.toString());
+ }
+
+ final protected boolean
+ __servantLocatorFinished(boolean amd)
+ {
+ assert(_locator != null && _servant != null);
+ try
+ {
+ _locator.finished(_current, _servant, _cookie.value);
+ return true;
+ }
+ catch(Ice.UserException ex)
+ {
+ assert(_responseHandler != null);
+
+ if(_observer != null)
+ {
+ _observer.userException();
+ }
+
+ //
+ // The operation may have already marshaled a reply; we must overwrite that reply.
+ //
+ if(_response)
+ {
+ _os.resize(Protocol.headerSize + 4); // Reply status position.
+ _os.writeByte(ReplyStatus.replyUserException);
+ _os.startEncapsulation(_current.encoding, Ice.FormatType.DefaultFormat);
+ _os.writeException(ex);
+ _os.endEncapsulation();
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, amd);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ _responseHandler = null;
+ }
+ catch(java.lang.Exception ex)
+ {
+ __handleException(ex, amd);
+ }
+ catch(java.lang.Error ex)
+ {
+ __handleError(ex, amd); // Always throws.
+ }
+ return false;
+ }
+
+ final protected void
+ __handleException(java.lang.Exception exc, boolean amd)
+ {
+ assert(_responseHandler != null);
+
+ try
+ {
+ throw exc;
+ }
+ catch(Ice.RequestFailedException ex)
+ {
+ if(ex.id == null || ex.id.name == null || ex.id.name.isEmpty())
+ {
+ ex.id = _current.id;
+ }
+
+ if(ex.facet == null || ex.facet.isEmpty())
+ {
+ ex.facet = _current.facet;
+ }
+
+ if(ex.operation == null || ex.operation.length() == 0)
+ {
+ ex.operation = _current.operation;
+ }
+
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 1)
+ {
+ __warning(ex);
+ }
+
+ if(_observer != null)
+ {
+ _observer.failed(ex.ice_id());
+ }
+
+ if(_response)
+ {
+ _os.resize(Protocol.headerSize + 4); // Reply status position.
+ if(ex instanceof Ice.ObjectNotExistException)
+ {
+ _os.writeByte(ReplyStatus.replyObjectNotExist);
+ }
+ else if(ex instanceof Ice.FacetNotExistException)
+ {
+ _os.writeByte(ReplyStatus.replyFacetNotExist);
+ }
+ else if(ex instanceof Ice.OperationNotExistException)
+ {
+ _os.writeByte(ReplyStatus.replyOperationNotExist);
+ }
+ else
+ {
+ assert(false);
+ }
+ ex.id.__write(_os);
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ if(ex.facet == null || ex.facet.length() == 0)
+ {
+ _os.writeStringSeq(null);
+ }
+ else
+ {
+ String[] facetPath2 = { ex.facet };
+ _os.writeStringSeq(facetPath2);
+ }
+
+ _os.writeString(ex.operation);
+
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, amd);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+ }
+ catch(Ice.UnknownLocalException ex)
+ {
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ __warning(ex);
+ }
+
+ if(_observer != null)
+ {
+ _observer.failed(ex.ice_id());
+ }
+
+ if(_response)
+ {
+ _os.resize(Protocol.headerSize + 4); // Reply status position.
+ _os.writeByte(ReplyStatus.replyUnknownLocalException);
+ _os.writeString(ex.unknown);
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, amd);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+ }
+ catch(Ice.UnknownUserException ex)
+ {
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ __warning(ex);
+ }
+
+ if(_observer != null)
+ {
+ _observer.failed(ex.ice_id());
+ }
+
+ if(_response)
+ {
+ _os.resize(Protocol.headerSize + 4); // Reply status position.
+ _os.writeByte(ReplyStatus.replyUnknownUserException);
+ _os.writeString(ex.unknown);
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, amd);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+ }
+ catch(Ice.UnknownException ex)
+ {
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ __warning(ex);
+ }
+
+ if(_observer != null)
+ {
+ _observer.failed(ex.ice_id());
+ }
+
+ if(_response)
+ {
+ _os.resize(Protocol.headerSize + 4); // Reply status position.
+ _os.writeByte(ReplyStatus.replyUnknownException);
+ _os.writeString(ex.unknown);
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, amd);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+ }
+ catch(Ice.Exception ex)
+ {
+ if(ex instanceof Ice.SystemException)
+ {
+ if(_responseHandler.systemException(_current.requestId, (Ice.SystemException)ex, amd))
+ {
+ return;
+ }
+ }
+
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ __warning(ex);
+ }
+
+ if(_observer != null)
+ {
+ _observer.failed(ex.ice_id());
+ }
+
+ if(_response)
+ {
+ _os.resize(Protocol.headerSize + 4); // Reply status position.
+ _os.writeByte(ReplyStatus.replyUnknownLocalException);
+ //_os.writeString(ex.toString());
+ java.io.StringWriter sw = new java.io.StringWriter();
+ sw.write(ex.ice_id() + "\n");
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ _os.writeString(sw.toString());
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, amd);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+ }
+ catch(Ice.UserException ex)
+ {
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ __warning(ex);
+ }
+
+ if(_observer != null)
+ {
+ _observer.failed(ex.ice_id());
+ }
+
+ if(_response)
+ {
+ _os.resize(Protocol.headerSize + 4); // Reply status position.
+ _os.writeByte(ReplyStatus.replyUnknownUserException);
+ //_os.writeString(ex.toString());
+ java.io.StringWriter sw = new java.io.StringWriter();
+ sw.write(ex.ice_id() + "\n");
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ _os.writeString(sw.toString());
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, amd);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+ }
+ catch(java.lang.Exception ex)
+ {
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ __warning(ex);
+ }
+
+ if(_observer != null)
+ {
+ _observer.failed(ex.getClass().getName());
+ }
+
+ if(_response)
+ {
+ _os.resize(Protocol.headerSize + 4); // Reply status position.
+ _os.writeByte(ReplyStatus.replyUnknownException);
+ //_os.writeString(ex.toString());
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ _os.writeString(sw.toString());
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, amd);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+ }
+
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ _responseHandler = null;
+ }
+
+ final protected void
+ __handleError(java.lang.Error exc, boolean amd)
+ {
+ assert(_responseHandler != null);
+
+ Ice.UnknownException uex = new Ice.UnknownException(exc);
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ exc.printStackTrace(pw);
+ pw.flush();
+ uex.unknown = sw.toString();
+
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0)
+ {
+ __warning(uex);
+ }
+
+ if(_observer != null)
+ {
+ _observer.failed(uex.ice_id());
+ }
+
+ if(_response)
+ {
+ _os.resize(Protocol.headerSize + 4); // Reply status position.
+ _os.writeByte(ReplyStatus.replyUnknownException);
+ _os.writeString(uex.unknown);
+ if(_observer != null)
+ {
+ _observer.reply(_os.size() - Protocol.headerSize - 4);
+ }
+ _responseHandler.sendResponse(_current.requestId, _os, _compress, amd);
+ }
+ else
+ {
+ _responseHandler.sendNoResponse();
+ }
+
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ _responseHandler = null;
+
+ throw new ServantError(exc);
+ }
+
+ protected Instance _instance;
+ protected Ice.Current _current;
+ protected Ice.Object _servant;
+ protected Ice.ServantLocator _locator;
+ protected Ice.LocalObjectHolder _cookie;
+ protected Ice.Instrumentation.DispatchObserver _observer;
+
+ protected boolean _response;
+ protected byte _compress;
+
+ protected Ice.OutputStream _os;
+
+ protected ResponseHandler _responseHandler;
+
+ protected java.util.LinkedList<Ice.DispatchInterceptorAsyncCallback> _interceptorAsyncCallbackList;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/IncomingConnectionFactory.java b/java-compat/src/Ice/src/main/java/IceInternal/IncomingConnectionFactory.java
new file mode 100644
index 00000000000..2a6b69935a3
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/IncomingConnectionFactory.java
@@ -0,0 +1,658 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class IncomingConnectionFactory extends EventHandler implements Ice.ConnectionI.StartCallback
+{
+ public synchronized void
+ activate()
+ {
+ setState(StateActive);
+ }
+
+ public synchronized void
+ hold()
+ {
+ setState(StateHolding);
+ }
+
+ public synchronized void
+ destroy()
+ {
+ setState(StateClosed);
+ }
+
+ public synchronized void
+ updateConnectionObservers()
+ {
+ for(Ice.ConnectionI connection : _connections)
+ {
+ connection.updateObserver();
+ }
+ }
+
+ public void
+ waitUntilHolding()
+ throws InterruptedException
+ {
+ java.util.LinkedList<Ice.ConnectionI> connections;
+
+ synchronized(this)
+ {
+ //
+ // First we wait until the connection factory itself is in holding
+ // state.
+ //
+ while(_state < StateHolding)
+ {
+ wait();
+ }
+
+ //
+ // We want to wait until all connections are in holding state
+ // outside the thread synchronization.
+ //
+ connections = new java.util.LinkedList<Ice.ConnectionI>(_connections);
+ }
+
+ //
+ // Now we wait until each connection is in holding state.
+ //
+ for(Ice.ConnectionI connection : connections)
+ {
+ connection.waitUntilHolding();
+ }
+ }
+
+ public void
+ waitUntilFinished()
+ throws InterruptedException
+ {
+ java.util.LinkedList<Ice.ConnectionI> connections = null;
+
+ synchronized(this)
+ {
+ //
+ // First we wait until the factory is destroyed. If we are using
+ // an acceptor, we also wait for it to be closed.
+ //
+ while(_state != StateFinished)
+ {
+ wait();
+ }
+
+ //
+ // Clear the OA. See bug 1673 for the details of why this is necessary.
+ //
+ _adapter = null;
+
+ //
+ // We want to wait until all connections are finished outside the
+ // thread synchronization.
+ //
+ connections = new java.util.LinkedList<Ice.ConnectionI>(_connections);
+ }
+
+ if(connections != null)
+ {
+ for(Ice.ConnectionI connection : connections)
+ {
+ try
+ {
+ connection.waitUntilFinished();
+ }
+ catch(InterruptedException e)
+ {
+ //
+ // Force close all of the connections.
+ //
+ for(Ice.ConnectionI c : connections)
+ {
+ c.close(true);
+ }
+ throw e;
+ }
+ }
+ }
+
+ synchronized(this)
+ {
+ if(_transceiver != null)
+ {
+ assert(_connections.size() <= 1); // The connection isn't monitored or reaped.
+ }
+ else
+ {
+ // Ensure all the connections are finished and reapable at this point.
+ java.util.List<Ice.ConnectionI> cons = _monitor.swapReapedConnections();
+ assert((cons == null ? 0 : cons.size()) == _connections.size());
+ if(cons != null)
+ {
+ cons.clear();
+ }
+ }
+ _connections.clear();
+ _monitor.destroy();
+ }
+ }
+
+ public EndpointI
+ endpoint()
+ {
+ // No mutex protection necessary, _endpoint is immutable.
+ return _endpoint;
+ }
+
+ public synchronized java.util.LinkedList<Ice.ConnectionI>
+ connections()
+ {
+ java.util.LinkedList<Ice.ConnectionI> connections = new java.util.LinkedList<Ice.ConnectionI>();
+
+ //
+ // Only copy connections which have not been destroyed.
+ //
+ for(Ice.ConnectionI connection : _connections)
+ {
+ if(connection.isActiveOrHolding())
+ {
+ connections.add(connection);
+ }
+ }
+
+ return connections;
+ }
+
+ public void
+ flushAsyncBatchRequests(CommunicatorFlushBatch outAsync)
+ {
+ for(Ice.ConnectionI c : connections()) // connections() is synchronized, no need to synchronize here.
+ {
+ try
+ {
+ outAsync.flushConnection(c);
+ }
+ catch(Ice.LocalException ex)
+ {
+ // Ignore.
+ }
+ }
+ }
+
+ //
+ // Operations from EventHandler.
+ //
+
+ @Override
+ public void
+ message(ThreadPoolCurrent current)
+ {
+ Ice.ConnectionI connection = null;
+ synchronized(this)
+ {
+ if(_state >= StateClosed)
+ {
+ return;
+ }
+ else if(_state == StateHolding)
+ {
+ Thread.yield();
+ return;
+ }
+
+ //
+ // Reap closed connections.
+ //
+ java.util.List<Ice.ConnectionI> cons = _monitor.swapReapedConnections();
+ if(cons != null)
+ {
+ for(Ice.ConnectionI c : cons)
+ {
+ _connections.remove(c);
+ }
+ }
+
+ //
+ // Now accept a new connection.
+ //
+ Transceiver transceiver = null;
+ try
+ {
+ transceiver = _acceptor.accept();
+
+ if(_instance.traceLevels().network >= 2)
+ {
+ StringBuffer s = new StringBuffer("trying to accept ");
+ s.append(_endpoint.protocol());
+ s.append(" connection\n");
+ s.append(transceiver.toString());
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+ }
+ catch(Ice.SocketException ex)
+ {
+ if(Network.noMoreFds(ex.getCause()))
+ {
+ try
+ {
+ String s = "fatal error: can't accept more connections:\n" + ex.getCause().getMessage();
+ s += '\n' + _acceptor.toString();
+ _instance.initializationData().logger.error(s);
+ }
+ finally
+ {
+ Runtime.getRuntime().halt(1);
+ }
+ }
+
+ // Ignore socket exceptions.
+ return;
+ }
+ catch(Ice.LocalException ex)
+ {
+ // Warn about other Ice local exceptions.
+ if(_warn)
+ {
+ warning(ex);
+ }
+ return;
+ }
+
+ assert(transceiver != null);
+
+ try
+ {
+ connection = new Ice.ConnectionI(_adapter.getCommunicator(), _instance, _monitor, transceiver, null,
+ _endpoint, _adapter);
+ }
+ catch(Ice.LocalException ex)
+ {
+ try
+ {
+ transceiver.close();
+ }
+ catch(Ice.LocalException exc)
+ {
+ // Ignore
+ }
+
+ if(_warn)
+ {
+ warning(ex);
+ }
+ return;
+ }
+
+ _connections.add(connection);
+ }
+
+ assert(connection != null);
+ connection.start(this);
+ }
+
+ @Override
+ public synchronized void
+ finished(ThreadPoolCurrent current, boolean close)
+ {
+ assert(_state == StateClosed);
+ setState(StateFinished);
+
+ if(close)
+ {
+ closeAcceptor();
+ }
+ }
+
+ @Override
+ public synchronized String
+ toString()
+ {
+ if(_transceiver != null)
+ {
+ return _transceiver.toString();
+ }
+ return _acceptor.toString();
+ }
+
+ @Override
+ public java.nio.channels.SelectableChannel
+ fd()
+ {
+ assert(_acceptor != null);
+ return _acceptor.fd();
+ }
+
+ @Override
+ public void setReadyCallback(ReadyCallback readyCallback)
+ {
+ if(_acceptor != null)
+ {
+ _acceptor.setReadyCallback(readyCallback);
+ }
+ }
+
+ //
+ // Operations from ConnectionI.StartCallback
+ //
+ @Override
+ public synchronized void
+ connectionStartCompleted(Ice.ConnectionI connection)
+ {
+ //
+ // Initially, connections are in the holding state. If the factory is active
+ // we activate the connection.
+ //
+ if(_state == StateActive)
+ {
+ connection.activate();
+ }
+ }
+
+ @Override
+ public synchronized void
+ connectionStartFailed(Ice.ConnectionI connection, Ice.LocalException ex)
+ {
+ if(_state >= StateClosed)
+ {
+ return;
+ }
+ //
+ // Do not warn about connection exceptions here. The connection is not yet validated.
+ //
+ }
+
+ public
+ IncomingConnectionFactory(Instance instance, EndpointI endpoint, Ice.ObjectAdapterI adapter)
+ {
+ _instance = instance;
+ _endpoint = endpoint;
+ _adapter = adapter;
+ _warn = _instance.initializationData().properties.getPropertyAsInt("Ice.Warn.Connections") > 0 ? true : false;
+ _state = StateHolding;
+ _monitor = new FactoryACMMonitor(instance, adapter.getACM());
+
+ DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideTimeout)
+ {
+ _endpoint = _endpoint.timeout(defaultsAndOverrides.overrideTimeoutValue);
+ }
+
+ if(defaultsAndOverrides.overrideCompress)
+ {
+ _endpoint = _endpoint.compress(defaultsAndOverrides.overrideCompressValue);
+ }
+
+ try
+ {
+ _transceiver = _endpoint.transceiver();
+ if(_transceiver != null)
+ {
+ if(_instance.traceLevels().network >= 2)
+ {
+ StringBuffer s = new StringBuffer("attempting to bind to ");
+ s.append(_endpoint.protocol());
+ s.append(" socket\n");
+ s.append(_transceiver.toString());
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+ _endpoint = _transceiver.bind();
+
+ Ice.ConnectionI connection =
+ new Ice.ConnectionI(_adapter.getCommunicator(), _instance, null, _transceiver, null, _endpoint,
+ _adapter);
+ connection.startAndWait();
+
+ _connections.add(connection);
+ }
+ else
+ {
+ createAcceptor();
+ }
+ }
+ catch(java.lang.Exception ex)
+ {
+ //
+ // Clean up for finalizer.
+ //
+ if(_transceiver != null)
+ {
+ try
+ {
+ _transceiver.close();
+ }
+ catch(Ice.LocalException e)
+ {
+ // Here we ignore any exceptions in close().
+ }
+ }
+
+ _state = StateFinished;
+ _monitor.destroy();
+ _connections.clear();
+
+ if(ex instanceof Ice.LocalException)
+ {
+ throw (Ice.LocalException)ex;
+ }
+ else if(ex instanceof InterruptedException)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ else
+ {
+ throw new Ice.SyscallException(ex);
+ }
+ }
+ }
+
+ @Override
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_state == StateFinished);
+ IceUtilInternal.Assert.FinalizerAssert(_connections.isEmpty());
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ private static final int StateActive = 0;
+ private static final int StateHolding = 1;
+ private static final int StateClosed = 2;
+ private static final int StateFinished = 3;
+
+ private void
+ setState(int state)
+ {
+ if(_state == state) // Don't switch twice.
+ {
+ return;
+ }
+
+ switch(state)
+ {
+ case StateActive:
+ {
+ if(_state != StateHolding) // Can only switch from holding to active.
+ {
+ return;
+ }
+ if(_acceptor != null)
+ {
+ if(_instance.traceLevels().network >= 1)
+ {
+ StringBuffer s = new StringBuffer("accepting ");
+ s.append(_endpoint.protocol());
+ s.append(" connections at ");
+ s.append(_acceptor.toString());
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+ _adapter.getThreadPool().register(this, SocketOperation.Read);
+ }
+
+ for(Ice.ConnectionI connection : _connections)
+ {
+ connection.activate();
+ }
+ break;
+ }
+
+ case StateHolding:
+ {
+ if(_state != StateActive) // Can only switch from active to holding.
+ {
+ return;
+ }
+ if(_acceptor != null)
+ {
+ if(_instance.traceLevels().network >= 1)
+ {
+ StringBuffer s = new StringBuffer("holding ");
+ s.append(_endpoint.protocol());
+ s.append(" connections at ");
+ s.append(_acceptor.toString());
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+ _adapter.getThreadPool().unregister(this, SocketOperation.Read);
+ }
+
+ for(Ice.ConnectionI connection : _connections)
+ {
+ connection.hold();
+ }
+ break;
+ }
+
+ case StateClosed:
+ {
+ if(_acceptor != null)
+ {
+ //
+ // If possible, close the acceptor now to prevent new connections from
+ // being accepted while we are deactivating. This is especially useful
+ // if there are no more threads in the thread pool available to dispatch
+ // the finish() call.
+ //
+ if(_adapter.getThreadPool().finish(this, true))
+ {
+ closeAcceptor();
+ }
+ }
+ else
+ {
+ state = StateFinished;
+ }
+
+ for(Ice.ConnectionI connection : _connections)
+ {
+ connection.destroy(Ice.ConnectionI.ObjectAdapterDeactivated);
+ }
+ break;
+ }
+
+ case StateFinished:
+ {
+ assert(_state == StateClosed);
+ break;
+ }
+ }
+
+ _state = state;
+ notifyAll();
+ }
+
+ private void
+ createAcceptor()
+ {
+ try
+ {
+ _acceptor = _endpoint.acceptor(_adapter.getName());
+ assert(_acceptor != null);
+
+ if(_instance.traceLevels().network >= 2)
+ {
+ StringBuffer s = new StringBuffer("attempting to bind to ");
+ s.append(_endpoint.protocol());
+ s.append(" socket ");
+ s.append(_acceptor.toString());
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+
+ _endpoint = _acceptor.listen();
+
+ if(_instance.traceLevels().network >= 1)
+ {
+ StringBuffer s = new StringBuffer("listening for ");
+ s.append(_endpoint.protocol());
+ s.append(" connections\n");
+ s.append(_acceptor.toDetailedString());
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+
+ _adapter.getThreadPool().initialize(this);
+
+ if(_state == StateActive)
+ {
+ _adapter.getThreadPool().register(this, SocketOperation.Read);
+ }
+ }
+ catch(Exception ex)
+ {
+ if(_acceptor != null)
+ {
+ _acceptor.close();
+ }
+ throw ex;
+ }
+ }
+
+ private void
+ closeAcceptor()
+ {
+ if(_instance.traceLevels().network >= 1)
+ {
+ StringBuffer s = new StringBuffer("stopping to accept ");
+ s.append(_endpoint.protocol());
+ s.append(" connections at ");
+ s.append(_acceptor.toString());
+ _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
+ }
+ _acceptor.close();
+ }
+
+ private void
+ warning(Ice.LocalException ex)
+ {
+ String s = "connection exception:\n" + Ex.toString(ex) + '\n' + _acceptor.toString();
+ _instance.initializationData().logger.warning(s);
+ }
+
+ private final Instance _instance;
+ private final FactoryACMMonitor _monitor;
+
+ private Acceptor _acceptor;
+ private Transceiver _transceiver;
+ private EndpointI _endpoint;
+
+ private Ice.ObjectAdapterI _adapter;
+
+ private final boolean _warn;
+
+ private java.util.Set<Ice.ConnectionI> _connections = new java.util.HashSet<Ice.ConnectionI>();
+
+ private int _state;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/InputStreamWrapper.java b/java-compat/src/Ice/src/main/java/IceInternal/InputStreamWrapper.java
new file mode 100644
index 00000000000..8359235b692
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/InputStreamWrapper.java
@@ -0,0 +1,96 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+//
+// Class to provide a java.io.InputStream on top of a ByteBuffer.
+// We use this to deserialize arbitrary Java serializable classes from
+// a Slice byte sequence. This class is a wrapper around a Buffer
+// that passes all methods through.
+//
+
+public class InputStreamWrapper extends java.io.InputStream
+{
+ public InputStreamWrapper(int size, java.nio.ByteBuffer buf)
+ {
+ _buf = buf;
+ _markPos = 0;
+ }
+
+ @Override
+ public int read()
+ throws java.io.IOException
+ {
+ try
+ {
+ return _buf.get();
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new java.io.IOException(ex.toString());
+ }
+ }
+
+ @Override
+ public int read(byte[] b)
+ throws java.io.IOException
+ {
+ return read(b, 0, b.length);
+ }
+
+ @Override
+ public int read(byte[] b, int offset, int count)
+ throws java.io.IOException
+ {
+ try
+ {
+ _buf.get(b, offset, count);
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new java.io.IOException(ex.toString());
+ }
+ return count;
+ }
+
+ @Override
+ public int available()
+ {
+ return _buf.remaining();
+ }
+
+ @Override
+ public void mark(int readlimit)
+ {
+ _markPos = _buf.position();
+ }
+
+ @Override
+ public void reset()
+ throws java.io.IOException
+ {
+ _buf.position(_markPos);
+ }
+
+ @Override
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+ @Override
+ public void close()
+ throws java.io.IOException
+ {
+ }
+
+ private java.nio.ByteBuffer _buf;
+ private int _markPos;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Instance.java b/java-compat/src/Ice/src/main/java/IceInternal/Instance.java
new file mode 100644
index 00000000000..30b78609ca8
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Instance.java
@@ -0,0 +1,1863 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.util.concurrent.TimeUnit;
+
+public final class Instance implements Ice.ClassResolver
+{
+ static private class ThreadObserverHelper
+ {
+ ThreadObserverHelper(String threadName)
+ {
+ _threadName = threadName;
+ }
+
+ synchronized public void updateObserver(Ice.Instrumentation.CommunicatorObserver obsv)
+ {
+ assert(obsv != null);
+
+ _observer = obsv.getThreadObserver("Communicator",
+ _threadName,
+ Ice.Instrumentation.ThreadState.ThreadStateIdle,
+ _observer);
+ if(_observer != null)
+ {
+ _observer.attach();
+ }
+ }
+
+ protected void beforeExecute()
+ {
+ _threadObserver = _observer;
+ if(_threadObserver != null)
+ {
+ _threadObserver.stateChanged(Ice.Instrumentation.ThreadState.ThreadStateIdle,
+ Ice.Instrumentation.ThreadState.ThreadStateInUseForOther);
+ }
+ }
+
+ protected void afterExecute()
+ {
+ if(_threadObserver != null)
+ {
+ _threadObserver.stateChanged(Ice.Instrumentation.ThreadState.ThreadStateInUseForOther,
+ Ice.Instrumentation.ThreadState.ThreadStateIdle);
+ _threadObserver = null;
+ }
+ }
+
+ final private String _threadName;
+ //
+ // We use a volatile to avoid synchronization when reading
+ // _observer. Reference assignement is atomic in Java so it
+ // also doesn't need to be synchronized.
+ //
+ private volatile Ice.Instrumentation.ThreadObserver _observer;
+ private Ice.Instrumentation.ThreadObserver _threadObserver;
+ }
+
+ static private class Timer extends java.util.concurrent.ScheduledThreadPoolExecutor
+ {
+ Timer(Ice.Properties props, String threadName)
+ {
+ super(1, Util.createThreadFactory(props, threadName)); // Single thread executor
+ if(!Util.isAndroid())
+ {
+ // This API doesn't exist on Android up to API level 20.
+ setRemoveOnCancelPolicy(true);
+ }
+ setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
+ _observerHelper = new ThreadObserverHelper(threadName);
+ }
+
+ public void updateObserver(Ice.Instrumentation.CommunicatorObserver obsv)
+ {
+ _observerHelper.updateObserver(obsv);
+ }
+
+ @Override
+ protected void beforeExecute(Thread t, Runnable r)
+ {
+ _observerHelper.beforeExecute();
+ }
+
+ @Override
+ protected void afterExecute(Runnable t, Throwable e)
+ {
+ _observerHelper.afterExecute();
+ }
+
+ private final ThreadObserverHelper _observerHelper;
+ }
+
+ static private class QueueExecutor extends java.util.concurrent.ThreadPoolExecutor
+ {
+ QueueExecutor(Ice.Properties props, String threadName)
+ {
+ super(1, 1, 0, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue<Runnable>(),
+ Util.createThreadFactory(props, threadName));
+ _observerHelper = new ThreadObserverHelper(threadName);
+ }
+
+ public void updateObserver(Ice.Instrumentation.CommunicatorObserver obsv)
+ {
+ _observerHelper.updateObserver(obsv);
+ }
+
+ @Override
+ protected void beforeExecute(Thread t, Runnable r)
+ {
+ _observerHelper.beforeExecute();
+ }
+
+ @Override
+ protected void afterExecute(Runnable t, Throwable e)
+ {
+ _observerHelper.afterExecute();
+ }
+
+ public void destroy()
+ throws InterruptedException
+ {
+ shutdown();
+ while(!isTerminated())
+ {
+ // A very long time.
+ awaitTermination(100000, java.util.concurrent.TimeUnit.SECONDS);
+ }
+ }
+
+ private final ThreadObserverHelper _observerHelper;
+ }
+
+ private class ObserverUpdaterI implements Ice.Instrumentation.ObserverUpdater
+ {
+ @Override
+ public void
+ updateConnectionObservers()
+ {
+ Instance.this.updateConnectionObservers();
+ }
+
+ @Override
+ public void
+ updateThreadObservers()
+ {
+ Instance.this.updateThreadObservers();
+ }
+ }
+
+ public Ice.InitializationData
+ initializationData()
+ {
+ //
+ // No check for destruction. It must be possible to access the
+ // initialization data after destruction.
+ //
+ // No mutex lock, immutable.
+ //
+ return _initData;
+ }
+
+ public TraceLevels
+ traceLevels()
+ {
+ // No mutex lock, immutable.
+ assert(_traceLevels != null);
+ return _traceLevels;
+ }
+
+ public DefaultsAndOverrides
+ defaultsAndOverrides()
+ {
+ // No mutex lock, immutable.
+ assert(_defaultsAndOverrides != null);
+ return _defaultsAndOverrides;
+ }
+
+ public synchronized RouterManager
+ routerManager()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_routerManager != null);
+ return _routerManager;
+ }
+
+ public synchronized LocatorManager
+ locatorManager()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_locatorManager != null);
+ return _locatorManager;
+ }
+
+ public synchronized ReferenceFactory
+ referenceFactory()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_referenceFactory != null);
+ return _referenceFactory;
+ }
+
+ public synchronized RequestHandlerFactory
+ requestHandlerFactory()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_requestHandlerFactory != null);
+ return _requestHandlerFactory;
+ }
+
+ public synchronized ProxyFactory
+ proxyFactory()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_proxyFactory != null);
+ return _proxyFactory;
+ }
+
+ public synchronized OutgoingConnectionFactory
+ outgoingConnectionFactory()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_outgoingConnectionFactory != null);
+ return _outgoingConnectionFactory;
+ }
+
+ public synchronized ObjectAdapterFactory
+ objectAdapterFactory()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_objectAdapterFactory != null);
+ return _objectAdapterFactory;
+ }
+
+ public int
+ protocolSupport()
+ {
+ return _protocolSupport;
+ }
+
+ public boolean
+ preferIPv6()
+ {
+ return _preferIPv6;
+ }
+
+ public NetworkProxy
+ networkProxy()
+ {
+ return _networkProxy;
+ }
+
+ public synchronized ThreadPool
+ clientThreadPool()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_clientThreadPool != null);
+ return _clientThreadPool;
+ }
+
+ public synchronized ThreadPool
+ serverThreadPool()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ if(_serverThreadPool == null) // Lazy initialization.
+ {
+ if(_state == StateDestroyInProgress)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ int timeout = _initData.properties.getPropertyAsInt("Ice.ServerIdleTime");
+ _serverThreadPool = new ThreadPool(this, "Ice.ThreadPool.Server", timeout);
+ }
+
+ return _serverThreadPool;
+ }
+
+ public synchronized EndpointHostResolver
+ endpointHostResolver()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_endpointHostResolver != null);
+ return _endpointHostResolver;
+ }
+
+ synchronized public RetryQueue
+ retryQueue()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_retryQueue != null);
+ return _retryQueue;
+ }
+
+ synchronized public java.util.concurrent.ScheduledExecutorService
+ timer()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_timer != null);
+ return _timer;
+ }
+
+ public synchronized EndpointFactoryManager
+ endpointFactoryManager()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_endpointFactoryManager != null);
+ return _endpointFactoryManager;
+ }
+
+ public synchronized Ice.PluginManager
+ pluginManager()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(_pluginManager != null);
+ return _pluginManager;
+ }
+
+ public int
+ messageSizeMax()
+ {
+ // No mutex lock, immutable.
+ return _messageSizeMax;
+ }
+
+ public int
+ batchAutoFlushSize()
+ {
+ // No mutex lock, immutable.
+ return _batchAutoFlushSize;
+ }
+
+ public int
+ cacheMessageBuffers()
+ {
+ // No mutex lock, immutable.
+ return _cacheMessageBuffers;
+ }
+
+ public ACMConfig
+ clientACM()
+ {
+ // No mutex lock, immutable.
+ return _clientACM;
+ }
+
+ public ACMConfig
+ serverACM()
+ {
+ // No mutex lock, immutable.
+ return _serverACM;
+ }
+
+ public Ice.ImplicitContextI
+ getImplicitContext()
+ {
+ return _implicitContext;
+ }
+
+ public synchronized Ice.ObjectPrx
+ createAdmin(Ice.ObjectAdapter adminAdapter, Ice.Identity adminIdentity)
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+
+ boolean createAdapter = (adminAdapter == null);
+
+ synchronized(this)
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ if(adminIdentity == null || adminIdentity.name == null || adminIdentity.name.isEmpty())
+ {
+ throw new Ice.IllegalIdentityException(adminIdentity);
+ }
+
+ if(_adminAdapter != null)
+ {
+ throw new Ice.InitializationException("Admin already created");
+ }
+
+ if(!_adminEnabled)
+ {
+ throw new Ice.InitializationException("Admin is disabled");
+ }
+
+ if(createAdapter)
+ {
+ if(!_initData.properties.getProperty("Ice.Admin.Endpoints").isEmpty())
+ {
+ adminAdapter = _objectAdapterFactory.createObjectAdapter("Ice.Admin", null);
+ }
+ else
+ {
+ throw new Ice.InitializationException("Ice.Admin.Endpoints is not set");
+ }
+ }
+
+ _adminIdentity = adminIdentity;
+ _adminAdapter = adminAdapter;
+ addAllAdminFacets();
+ }
+
+ if(createAdapter)
+ {
+ try
+ {
+ adminAdapter.activate();
+ }
+ catch(Ice.LocalException ex)
+ {
+ //
+ // We cleanup _adminAdapter, however this error is not recoverable
+ // (can't call again getAdmin() after fixing the problem)
+ // since all the facets (servants) in the adapter are lost
+ //
+ adminAdapter.destroy();
+ synchronized(this)
+ {
+ _adminAdapter = null;
+ }
+ throw ex;
+ }
+ }
+ setServerProcessProxy(adminAdapter, adminIdentity);
+ return adminAdapter.createProxy(adminIdentity);
+ }
+
+ public Ice.ObjectPrx
+ getAdmin()
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+
+ Ice.ObjectAdapter adminAdapter;
+ Ice.Identity adminIdentity;
+
+ synchronized(this)
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ if(_adminAdapter != null)
+ {
+ return _adminAdapter.createProxy(_adminIdentity);
+ }
+ else if(_adminEnabled)
+ {
+ if(!_initData.properties.getProperty("Ice.Admin.Endpoints").isEmpty())
+ {
+ adminAdapter = _objectAdapterFactory.createObjectAdapter("Ice.Admin", null);
+ }
+ else
+ {
+ return null;
+ }
+ adminIdentity = new Ice.Identity("admin", _initData.properties.getProperty("Ice.Admin.InstanceName"));
+ if(adminIdentity.category.isEmpty())
+ {
+ adminIdentity.category = java.util.UUID.randomUUID().toString();
+ }
+
+ _adminIdentity = adminIdentity;
+ _adminAdapter = adminAdapter;
+ addAllAdminFacets();
+ // continue below outside synchronization
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ try
+ {
+ adminAdapter.activate();
+ }
+ catch(Ice.LocalException ex)
+ {
+ //
+ // We cleanup _adminAdapter, however this error is not recoverable
+ // (can't call again getAdmin() after fixing the problem)
+ // since all the facets (servants) in the adapter are lost
+ //
+ adminAdapter.destroy();
+ synchronized(this)
+ {
+ _adminAdapter = null;
+ }
+ throw ex;
+ }
+
+ setServerProcessProxy(adminAdapter, adminIdentity);
+ return adminAdapter.createProxy(adminIdentity);
+ }
+
+ public synchronized void
+ addAdminFacet(Ice.Object servant, String facet)
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ if(_adminAdapter == null || (!_adminFacetFilter.isEmpty() && !_adminFacetFilter.contains(facet)))
+ {
+ if(_adminFacets.get(facet) != null)
+ {
+ throw new Ice.AlreadyRegisteredException("facet", facet);
+ }
+ _adminFacets.put(facet, servant);
+ }
+ else
+ {
+ _adminAdapter.addFacet(servant, _adminIdentity, facet);
+ }
+ }
+
+ public synchronized Ice.Object
+ removeAdminFacet(String facet)
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Ice.Object result;
+
+ if(_adminAdapter == null || (!_adminFacetFilter.isEmpty() && !_adminFacetFilter.contains(facet)))
+ {
+ result = _adminFacets.remove(facet);
+ if(result == null)
+ {
+ throw new Ice.NotRegisteredException("facet", facet);
+ }
+ }
+ else
+ {
+ result = _adminAdapter.removeFacet(_adminIdentity, facet);
+ }
+
+ return result;
+ }
+
+ public synchronized Ice.Object
+ findAdminFacet(String facet)
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Ice.Object result = null;
+
+ if(_adminAdapter == null || (!_adminFacetFilter.isEmpty() && !_adminFacetFilter.contains(facet)))
+ {
+ result = _adminFacets.get(facet);
+ }
+ else
+ {
+ result = _adminAdapter.findFacet(_adminIdentity, facet);
+ }
+
+ return result;
+ }
+
+ public synchronized java.util.Map<String, Ice.Object>
+ findAllAdminFacets()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ if(_adminAdapter == null)
+ {
+ return new java.util.HashMap<String, Ice.Object>(_adminFacets);
+ }
+ else
+ {
+ java.util.Map<String, Ice.Object> result = _adminAdapter.findAllFacets(_adminIdentity);
+ if(!_adminFacets.isEmpty())
+ {
+ // Also returns filtered facets
+ result.putAll(_adminFacets);
+ }
+ return result;
+ }
+ }
+
+ public synchronized void
+ setDefaultLocator(Ice.LocatorPrx locator)
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ _referenceFactory = _referenceFactory.setDefaultLocator(locator);
+ }
+
+ public synchronized void
+ setDefaultRouter(Ice.RouterPrx router)
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ _referenceFactory = _referenceFactory.setDefaultRouter(router);
+ }
+
+ public void
+ setLogger(Ice.Logger logger)
+ {
+ //
+ // No locking, as it can only be called during plug-in loading
+ //
+ _initData.logger = logger;
+ }
+
+ public void
+ setThreadHook(Ice.ThreadNotification threadHook)
+ {
+ //
+ // No locking, as it can only be called during plug-in loading
+ //
+ _initData.threadHook = threadHook;
+ }
+
+ public Class<?>
+ findClass(String className)
+ {
+ return Util.findClass(className, _initData.classLoader);
+ }
+
+ public ClassLoader
+ getClassLoader()
+ {
+ return _initData.classLoader;
+ }
+
+ //
+ // From Ice.ClassResolver.
+ //
+ public Class<?> resolveClass(String typeId)
+ throws LinkageError
+ {
+ Class<?> c = null;
+
+ //
+ // To convert a Slice type id into a Java class, we do the following:
+ //
+ // 1. Convert the Slice type id into a classname (e.g., ::M::X -> M.X).
+ // 2. If that fails, extract the top-level module (if any) from the type id
+ // and check for an Package property. If found, prepend the property
+ // value to the classname.
+ // 3. If that fails, check for an Default.Package property. If found,
+ // prepend the property value to the classname.
+ //
+ String className;
+ boolean addClass = false;
+
+ synchronized(this)
+ {
+ className = _typeToClassMap.get(typeId);
+ }
+
+ if(className == null)
+ {
+ className = Ice.Util.typeIdToClass(typeId);
+ addClass = true;
+ }
+
+ c = getConcreteClass(className);
+
+ if(c == null)
+ {
+ int pos = typeId.indexOf(':', 2);
+ if(pos != -1)
+ {
+ String topLevelModule = typeId.substring(2, pos);
+ String pkg = _initData.properties.getProperty("Ice.Package." + topLevelModule);
+ if(pkg.length() > 0)
+ {
+ c = getConcreteClass(pkg + "." + className);
+ }
+ }
+ }
+
+ if(c == null)
+ {
+ String pkg = _initData.properties.getProperty("Ice.Default.Package");
+ if(pkg.length() > 0)
+ {
+ c = getConcreteClass(pkg + "." + className);
+ }
+ }
+
+ if(c != null && addClass)
+ {
+ synchronized(this)
+ {
+ className = c.getName();
+ if(_typeToClassMap.containsKey(typeId))
+ {
+ assert(_typeToClassMap.get(typeId).equals(className));
+ }
+ else
+ {
+ _typeToClassMap.put(typeId, className);
+ }
+ }
+ }
+
+ return c;
+ }
+
+ public String resolveCompactId(int compactId)
+ {
+ String className = "IceCompactId.TypeId_" + Integer.toString(compactId);
+ Class<?> c = getConcreteClass(className);
+ if(c == null)
+ {
+ for(String pkg : _packages)
+ {
+ c = getConcreteClass(pkg + "." + className);
+ if(c != null)
+ {
+ break;
+ }
+ }
+ }
+ if(c != null)
+ {
+ try
+ {
+ return (String)c.getField("typeId").get(null);
+ }
+ catch(Exception ex)
+ {
+ assert(false);
+ }
+ }
+ return "";
+ }
+
+ public Class<?> getConcreteClass(String className)
+ throws LinkageError
+ {
+ Class<?> c = findClass(className);
+
+ if(c != null)
+ {
+ //
+ // Ensure the class is instantiable. The constants are
+ // defined in the JVM specification (0x200 = interface,
+ // 0x400 = abstract).
+ //
+ final int modifiers = c.getModifiers();
+ if((modifiers & 0x200) == 0 && (modifiers & 0x400) == 0)
+ {
+ return c;
+ }
+ }
+
+ return null;
+ }
+
+ public boolean
+ useApplicationClassLoader()
+ {
+ return _useApplicationClassLoader;
+ }
+
+ public boolean
+ queueRequests()
+ {
+ return _queueExecutorService != null;
+ }
+
+ synchronized public QueueExecutorService
+ getQueueExecutor()
+ {
+ if(_state == StateDestroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+ return _queueExecutorService;
+ }
+
+ //
+ // Only for use by Ice.CommunicatorI
+ //
+ public
+ Instance(Ice.Communicator communicator, Ice.InitializationData initData)
+ {
+ _state = StateActive;
+ _initData = initData;
+
+ try
+ {
+ if(_initData.properties == null)
+ {
+ _initData.properties = Ice.Util.createProperties();
+ }
+
+ synchronized(Instance.class)
+ {
+ if(!_oneOffDone)
+ {
+ String stdOut = _initData.properties.getProperty("Ice.StdOut");
+ String stdErr = _initData.properties.getProperty("Ice.StdErr");
+
+ java.io.PrintStream outStream = null;
+
+ if(stdOut.length() > 0)
+ {
+ //
+ // We need to close the existing stdout for JVM thread dump to go
+ // to the new file
+ //
+ System.out.close();
+
+ try
+ {
+ outStream = new java.io.PrintStream(new java.io.FileOutputStream(stdOut, true));
+ }
+ catch(java.io.FileNotFoundException ex)
+ {
+ throw new Ice.FileException(0, stdOut, ex);
+ }
+
+ System.setOut(outStream);
+ }
+ if(stdErr.length() > 0)
+ {
+ //
+ // close for consistency with stdout
+ //
+ System.err.close();
+
+ if(stdErr.equals(stdOut))
+ {
+ System.setErr(outStream);
+ }
+ else
+ {
+ try
+ {
+ System.setErr(new java.io.PrintStream(new java.io.FileOutputStream(stdErr, true)));
+ }
+ catch(java.io.FileNotFoundException ex)
+ {
+ throw new Ice.FileException(0, stdErr, ex);
+ }
+
+ }
+ }
+ _oneOffDone = true;
+ }
+ }
+
+ if(_initData.logger == null)
+ {
+ String logfile = _initData.properties.getProperty("Ice.LogFile");
+ if(_initData.properties.getPropertyAsInt("Ice.UseSyslog") > 0 &&
+ !System.getProperty("os.name").startsWith("Windows"))
+ {
+ if(logfile.length() != 0)
+ {
+ throw new Ice.InitializationException("Both syslog and file logger cannot be enabled.");
+ }
+ _initData.logger = new Ice.SysLoggerI(_initData.properties.getProperty("Ice.ProgramName"),
+ _initData.properties.getPropertyWithDefault("Ice.SyslogFacility", "LOG_USER"));
+ }
+ else if(logfile.length() != 0)
+ {
+ _initData.logger = new Ice.LoggerI(_initData.properties.getProperty("Ice.ProgramName"), logfile);
+ }
+ else
+ {
+ _initData.logger = Ice.Util.getProcessLogger();
+ }
+ }
+
+ _packages = validatePackages();
+
+ _useApplicationClassLoader = _initData.properties.getPropertyAsInt("Ice.UseApplicationClassLoader") > 0;
+
+ _traceLevels = new TraceLevels(_initData.properties);
+
+ _defaultsAndOverrides = new DefaultsAndOverrides(_initData.properties, _initData.logger);
+
+ _clientACM = new ACMConfig(_initData.properties,
+ _initData.logger,
+ "Ice.ACM.Client",
+ new ACMConfig(_initData.properties, _initData.logger, "Ice.ACM",
+ new ACMConfig(false)));
+
+ _serverACM = new ACMConfig(_initData.properties,
+ _initData.logger,
+ "Ice.ACM.Server",
+ new ACMConfig(_initData.properties, _initData.logger, "Ice.ACM",
+ new ACMConfig(true)));
+
+ {
+ final int defaultMessageSizeMax = 1024;
+ int num = _initData.properties.getPropertyAsIntWithDefault("Ice.MessageSizeMax", defaultMessageSizeMax);
+ if(num < 1 || num > 0x7fffffff / 1024)
+ {
+ _messageSizeMax = 0x7fffffff;
+ }
+ else
+ {
+ _messageSizeMax = num * 1024; // Property is in kilobytes, _messageSizeMax in bytes
+ }
+ }
+
+ if(_initData.properties.getProperty("Ice.BatchAutoFlushSize").isEmpty() &&
+ !_initData.properties.getProperty("Ice.BatchAutoFlush").isEmpty())
+ {
+ if(_initData.properties.getPropertyAsInt("Ice.BatchAutoFlush") > 0)
+ {
+ _batchAutoFlushSize = _messageSizeMax;
+ }
+ else
+ {
+ _batchAutoFlushSize = 0;
+ }
+ }
+ else
+ {
+ int num = _initData.properties.getPropertyAsIntWithDefault("Ice.BatchAutoFlushSize", 1024); // 1MB
+ if(num < 1)
+ {
+ _batchAutoFlushSize = num;
+ }
+ else if(num > 0x7fffffff / 1024)
+ {
+ _batchAutoFlushSize = 0x7fffffff;
+ }
+ else
+ {
+ _batchAutoFlushSize = num * 1024; // Property is in kilobytes, _batchAutoFlushSize in bytes
+ }
+ }
+
+ _implicitContext = Ice.ImplicitContextI.create(_initData.properties.getProperty("Ice.ImplicitContext"));
+
+ _routerManager = new RouterManager();
+
+ _locatorManager = new LocatorManager(_initData.properties);
+
+ _referenceFactory = new ReferenceFactory(this, communicator);
+
+ _requestHandlerFactory = new RequestHandlerFactory(this);
+
+ _proxyFactory = new ProxyFactory(this);
+
+ boolean isIPv6Supported = Network.isIPv6Supported();
+ boolean ipv4 = _initData.properties.getPropertyAsIntWithDefault("Ice.IPv4", 1) > 0;
+ boolean ipv6 = _initData.properties.getPropertyAsIntWithDefault("Ice.IPv6", isIPv6Supported ? 1 : 0) > 0;
+ if(!ipv4 && !ipv6)
+ {
+ throw new Ice.InitializationException("Both IPV4 and IPv6 support cannot be disabled.");
+ }
+ else if(ipv4 && ipv6)
+ {
+ _protocolSupport = Network.EnableBoth;
+ }
+ else if(ipv4)
+ {
+ _protocolSupport = Network.EnableIPv4;
+ }
+ else
+ {
+ _protocolSupport = Network.EnableIPv6;
+ }
+ _preferIPv6 = _initData.properties.getPropertyAsInt("Ice.PreferIPv6Address") > 0;
+
+ _networkProxy = createNetworkProxy(_initData.properties, _protocolSupport);
+
+ _endpointFactoryManager = new EndpointFactoryManager(this);
+
+ ProtocolInstance tcpProtocolInstance = new ProtocolInstance(this, Ice.TCPEndpointType.value, "tcp", false);
+ _endpointFactoryManager.add(new TcpEndpointFactory(tcpProtocolInstance));
+
+ ProtocolInstance udpProtocolInstance = new ProtocolInstance(this, Ice.UDPEndpointType.value, "udp", false);
+ _endpointFactoryManager.add(new UdpEndpointFactory(udpProtocolInstance));
+
+ _pluginManager = new Ice.PluginManagerI(communicator, this);
+
+ if(_initData.valueFactoryManager == null)
+ {
+ _initData.valueFactoryManager = new ValueFactoryManagerI();
+ }
+
+ _outgoingConnectionFactory = new OutgoingConnectionFactory(communicator, this);
+
+ _objectAdapterFactory = new ObjectAdapterFactory(this, communicator);
+
+ _retryQueue = new RetryQueue(this);
+
+ //
+ // If Ice.ThreadInterruptSafe is set or we're running on Android all
+ // IO is done on the background thread. For Android we use the queue
+ // executor as Android doesn't allow any network invocations on the main
+ // thread even if the call is non-blocking.
+ //
+ if(_initData.properties.getPropertyAsInt("Ice.ThreadInterruptSafe") > 0 || Util.isAndroid())
+ {
+ _queueExecutor = new QueueExecutor(_initData.properties,
+ Util.createThreadName(_initData.properties, "Ice.BackgroundIO"));
+ _queueExecutorService = new QueueExecutorService(_queueExecutor);
+
+ // Caching message buffers is not supported with background IO.
+ _cacheMessageBuffers = 0;
+ }
+ else
+ {
+ _cacheMessageBuffers = _initData.properties.getPropertyAsIntWithDefault("Ice.CacheMessageBuffers", 2);
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ destroy();
+ throw ex;
+ }
+ }
+
+ @Override
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_state == StateDestroyed);
+ IceUtilInternal.Assert.FinalizerAssert(_referenceFactory == null);
+ IceUtilInternal.Assert.FinalizerAssert(_requestHandlerFactory == null);
+ IceUtilInternal.Assert.FinalizerAssert(_proxyFactory == null);
+ IceUtilInternal.Assert.FinalizerAssert(_outgoingConnectionFactory == null);
+ IceUtilInternal.Assert.FinalizerAssert(_objectAdapterFactory == null);
+ IceUtilInternal.Assert.FinalizerAssert(_clientThreadPool == null);
+ IceUtilInternal.Assert.FinalizerAssert(_serverThreadPool == null);
+ IceUtilInternal.Assert.FinalizerAssert(_endpointHostResolver == null);
+ IceUtilInternal.Assert.FinalizerAssert(_timer == null);
+ IceUtilInternal.Assert.FinalizerAssert(_routerManager == null);
+ IceUtilInternal.Assert.FinalizerAssert(_locatorManager == null);
+ IceUtilInternal.Assert.FinalizerAssert(_endpointFactoryManager == null);
+ IceUtilInternal.Assert.FinalizerAssert(_pluginManager == null);
+ IceUtilInternal.Assert.FinalizerAssert(_retryQueue == null);
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ public void
+ finishSetup(Ice.StringSeqHolder args, Ice.Communicator communicator)
+ {
+ //
+ // Load plug-ins.
+ //
+ assert(_serverThreadPool == null);
+ Ice.PluginManagerI pluginManagerImpl = (Ice.PluginManagerI)_pluginManager;
+ pluginManagerImpl.loadPlugins(args);
+
+ //
+ // Add WS and WSS endpoint factories if TCP/SSL factories are installed.
+ //
+ final EndpointFactory tcpFactory = _endpointFactoryManager.get(Ice.TCPEndpointType.value);
+ if(tcpFactory != null)
+ {
+ final ProtocolInstance instance = new ProtocolInstance(this, Ice.WSEndpointType.value, "ws", false);
+ _endpointFactoryManager.add(new WSEndpointFactory(instance, tcpFactory.clone(instance, null)));
+ }
+ final EndpointFactory sslFactory = _endpointFactoryManager.get(Ice.SSLEndpointType.value);
+ if(sslFactory != null)
+ {
+ final ProtocolInstance instance = new ProtocolInstance(this, Ice.WSSEndpointType.value, "wss", true);
+ _endpointFactoryManager.add(new WSEndpointFactory(instance, sslFactory.clone(instance, null)));
+ }
+
+ //
+ // Create Admin facets, if enabled.
+ //
+ // Note that any logger-dependent admin facet must be created after we load all plugins,
+ // since one of these plugins can be a Logger plugin that sets a new logger during loading
+ //
+
+ if(_initData.properties.getProperty("Ice.Admin.Enabled").isEmpty())
+ {
+ _adminEnabled = !_initData.properties.getProperty("Ice.Admin.Endpoints").isEmpty();
+ }
+ else
+ {
+ _adminEnabled = _initData.properties.getPropertyAsInt("Ice.Admin.Enabled") > 0;
+ }
+
+ String[] facetFilter = _initData.properties.getPropertyAsList("Ice.Admin.Facets");
+ if(facetFilter.length > 0)
+ {
+ _adminFacetFilter.addAll(java.util.Arrays.asList(facetFilter));
+ }
+
+ if(_adminEnabled)
+ {
+ //
+ // Process facet
+ //
+ String processFacetName = "Process";
+ if(_adminFacetFilter.isEmpty() || _adminFacetFilter.contains(processFacetName))
+ {
+ _adminFacets.put(processFacetName, new ProcessI(communicator));
+ }
+
+ //
+ // Logger facet
+ //
+ String loggerFacetName = "Logger";
+ if(_adminFacetFilter.isEmpty() || _adminFacetFilter.contains(loggerFacetName))
+ {
+ LoggerAdminLogger logger = new LoggerAdminLoggerI(_initData.properties, _initData.logger);
+ setLogger(logger);
+ _adminFacets.put(loggerFacetName, logger.getFacet());
+ }
+
+ //
+ // Properties facet
+ //
+ String propertiesFacetName = "Properties";
+ PropertiesAdminI propsAdmin = null;
+ if(_adminFacetFilter.isEmpty() || _adminFacetFilter.contains(propertiesFacetName))
+ {
+ propsAdmin = new PropertiesAdminI(this);
+ _adminFacets.put(propertiesFacetName, propsAdmin);
+ }
+
+ //
+ // Metrics facet
+ //
+ String metricsFacetName = "Metrics";
+ if(_adminFacetFilter.isEmpty() || _adminFacetFilter.contains(metricsFacetName))
+ {
+ CommunicatorObserverI observer = new CommunicatorObserverI(_initData);
+ _initData.observer = observer;
+ _adminFacets.put(metricsFacetName, observer.getFacet());
+
+ //
+ // Make sure the admin plugin receives property updates.
+ //
+ if(propsAdmin != null)
+ {
+ propsAdmin.addUpdateCallback(observer.getFacet());
+ }
+ }
+ }
+
+ //
+ // Set observer updater
+ //
+ if(_initData.observer != null)
+ {
+ _initData.observer.setObserverUpdater(new ObserverUpdaterI());
+ }
+
+ //
+ // Create threads.
+ //
+ try
+ {
+ _timer = new Timer(_initData.properties, Util.createThreadName(_initData.properties, "Ice.Timer"));
+ }
+ catch(RuntimeException ex)
+ {
+ String s = "cannot create thread for timer:\n" + Ex.toString(ex);
+ _initData.logger.error(s);
+ throw ex;
+ }
+
+ try
+ {
+ _endpointHostResolver = new EndpointHostResolver(this);
+ }
+ catch(RuntimeException ex)
+ {
+ String s = "cannot create thread for endpoint host resolver:\n" + Ex.toString(ex);
+ _initData.logger.error(s);
+ throw ex;
+ }
+
+ _clientThreadPool = new ThreadPool(this, "Ice.ThreadPool.Client", 0);
+
+ //
+ // The default router/locator may have been set during the loading of plugins.
+ // Therefore we make sure it is not already set before checking the property.
+ //
+ if(_referenceFactory.getDefaultRouter() == null)
+ {
+ Ice.RouterPrx router =
+ Ice.RouterPrxHelper.uncheckedCast(_proxyFactory.propertyToProxy("Ice.Default.Router"));
+ if(router != null)
+ {
+ _referenceFactory = _referenceFactory.setDefaultRouter(router);
+ }
+ }
+
+ if(_referenceFactory.getDefaultLocator() == null)
+ {
+ Ice.LocatorPrx loc =
+ Ice.LocatorPrxHelper.uncheckedCast(_proxyFactory.propertyToProxy("Ice.Default.Locator"));
+ if(loc != null)
+ {
+ _referenceFactory = _referenceFactory.setDefaultLocator(loc);
+ }
+ }
+
+ //
+ // Server thread pool initialization is lazy in serverThreadPool().
+ //
+
+ //
+ // An application can set Ice.InitPlugins=0 if it wants to postpone
+ // initialization until after it has interacted directly with the
+ // plug-ins.
+ //
+ if(_initData.properties.getPropertyAsIntWithDefault("Ice.InitPlugins", 1) > 0)
+ {
+ pluginManagerImpl.initializePlugins();
+ }
+
+ //
+ // This must be done last as this call creates the Ice.Admin object adapter
+ // and eventually registers a process proxy with the Ice locator (allowing
+ // remote clients to invoke on Ice.Admin facets as soon as it's registered).
+ //
+ if(_initData.properties.getPropertyAsIntWithDefault("Ice.Admin.DelayCreation", 0) <= 0)
+ {
+ getAdmin();
+ }
+ }
+
+ //
+ // Only for use by Ice.CommunicatorI
+ //
+ @SuppressWarnings("deprecation")
+ public void
+ destroy()
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+
+ synchronized(this)
+ {
+ //
+ // If destroy is in progress, wait for it to be done. This
+ // is necessary in case destroy() is called concurrently
+ // by multiple threads.
+ //
+ while(_state == StateDestroyInProgress)
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+
+ if(_state == StateDestroyed)
+ {
+ return;
+ }
+ _state = StateDestroyInProgress;
+ }
+
+ try
+ {
+ //
+ // Shutdown and destroy all the incoming and outgoing Ice
+ // connections and wait for the connections to be finished.
+ //
+ if(_objectAdapterFactory != null)
+ {
+ _objectAdapterFactory.shutdown();
+ }
+
+ if(_outgoingConnectionFactory != null)
+ {
+ _outgoingConnectionFactory.destroy();
+ }
+
+ if(_objectAdapterFactory != null)
+ {
+ _objectAdapterFactory.destroy();
+ }
+
+ if(_outgoingConnectionFactory != null)
+ {
+ _outgoingConnectionFactory.waitUntilFinished();
+ }
+
+ if(_retryQueue != null)
+ {
+ _retryQueue.destroy(); // Must be called before destroying thread pools.
+ }
+
+ if(_initData.observer != null)
+ {
+ _initData.observer.setObserverUpdater(null);
+ }
+
+ if(_initData.logger instanceof LoggerAdminLogger)
+ {
+ //
+ // This only disables the remote logging; we don't set or reset _initData.logger
+ //
+ ((LoggerAdminLogger)_initData.logger).destroy();
+ }
+
+ //
+ // Now, destroy the thread pools. This must be done *only* after
+ // all the connections are finished (the connections destruction
+ // can require invoking callbacks with the thread pools).
+ //
+ if(_serverThreadPool != null)
+ {
+ _serverThreadPool.destroy();
+ }
+ if(_clientThreadPool != null)
+ {
+ _clientThreadPool.destroy();
+ }
+ if(_endpointHostResolver != null)
+ {
+ _endpointHostResolver.destroy();
+ }
+ if(_timer != null)
+ {
+ _timer.shutdown(); // Don't use shutdownNow(), timers don't support interrupts
+ }
+
+ //
+ // Wait for all the threads to be finished.
+ //
+ try
+ {
+ if(_clientThreadPool != null)
+ {
+ _clientThreadPool.joinWithAllThreads();
+ }
+ if(_serverThreadPool != null)
+ {
+ _serverThreadPool.joinWithAllThreads();
+ }
+ if(_endpointHostResolver != null)
+ {
+ _endpointHostResolver.joinWithThread();
+ }
+ if(_queueExecutor != null)
+ {
+ _queueExecutor.destroy();
+ }
+ if(_timer != null)
+ {
+ while(!_timer.isTerminated())
+ {
+ // A very long time.
+ _timer.awaitTermination(100000, java.util.concurrent.TimeUnit.SECONDS);
+ }
+ }
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+
+ //
+ // NOTE: at this point destroy() can't be interrupted
+ // anymore. The calls below are therefore guaranteed to be
+ // called once.
+ //
+
+ for(Ice.ObjectFactory f : _objectFactoryMap.values())
+ {
+ f.destroy();
+ }
+ _objectFactoryMap.clear();
+
+ if(_routerManager != null)
+ {
+ _routerManager.destroy();
+ }
+
+ if(_locatorManager != null)
+ {
+ _locatorManager.destroy();
+ }
+
+ if(_endpointFactoryManager != null)
+ {
+ _endpointFactoryManager.destroy();
+ }
+
+ if(_initData.properties.getPropertyAsInt("Ice.Warn.UnusedProperties") > 0)
+ {
+ java.util.List<String> unusedProperties = ((Ice.PropertiesI)_initData.properties).getUnusedProperties();
+ if(unusedProperties.size() != 0)
+ {
+ StringBuilder message = new StringBuilder("The following properties were set but never read:");
+ for(String p : unusedProperties)
+ {
+ message.append("\n ");
+ message.append(p);
+ }
+ _initData.logger.warning(message.toString());
+ }
+ }
+
+ //
+ // Destroy last so that a Logger plugin can receive all log/traces before its destruction.
+ //
+ if(_pluginManager != null)
+ {
+ _pluginManager.destroy();
+ }
+
+ synchronized(this)
+ {
+ _objectAdapterFactory = null;
+ _outgoingConnectionFactory = null;
+ _retryQueue = null;
+
+ _serverThreadPool = null;
+ _clientThreadPool = null;
+ _endpointHostResolver = null;
+ _timer = null;
+
+ _referenceFactory = null;
+ _requestHandlerFactory = null;
+ _proxyFactory = null;
+ _routerManager = null;
+ _locatorManager = null;
+ _endpointFactoryManager = null;
+
+ _pluginManager = null;
+
+ _adminAdapter = null;
+ _adminFacets.clear();
+
+ _queueExecutor = null;
+ _queueExecutorService = null;
+
+ _typeToClassMap.clear();
+
+ _state = StateDestroyed;
+ notifyAll();
+ }
+ }
+ finally
+ {
+ synchronized(this)
+ {
+ if(_state == StateDestroyInProgress)
+ {
+ _state = StateActive;
+ notifyAll();
+ }
+ }
+ }
+ }
+
+ public BufSizeWarnInfo getBufSizeWarn(short type)
+ {
+ synchronized(_setBufSizeWarn)
+ {
+ BufSizeWarnInfo info;
+ if(!_setBufSizeWarn.containsKey(type))
+ {
+ info = new BufSizeWarnInfo();
+ info.sndWarn = false;
+ info.sndSize = -1;
+ info.rcvWarn = false;
+ info.rcvSize = -1;
+ _setBufSizeWarn.put(type, info);
+ }
+ else
+ {
+ info = _setBufSizeWarn.get(type);
+ }
+ return info;
+ }
+ }
+
+ public void setSndBufSizeWarn(short type, int size)
+ {
+ synchronized(_setBufSizeWarn)
+ {
+ BufSizeWarnInfo info = getBufSizeWarn(type);
+ info.sndWarn = true;
+ info.sndSize = size;
+ _setBufSizeWarn.put(type, info);
+ }
+ }
+
+ public void setRcvBufSizeWarn(short type, int size)
+ {
+ synchronized(_setBufSizeWarn)
+ {
+ BufSizeWarnInfo info = getBufSizeWarn(type);
+ info.rcvWarn = true;
+ info.rcvSize = size;
+ _setBufSizeWarn.put(type, info);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public synchronized void addObjectFactory(final Ice.ObjectFactory factory, String id)
+ {
+ //
+ // Create a ValueFactory wrapper around the given ObjectFactory and register the wrapper
+ // with the value factory manager. This may raise AlreadyRegisteredException.
+ //
+ _initData.valueFactoryManager.add(
+ new Ice.ValueFactory()
+ {
+ public Ice.Object create(String id)
+ {
+ return factory.create(id);
+ }
+ }, id);
+
+ _objectFactoryMap.put(id, factory);
+ }
+
+ @SuppressWarnings("deprecation")
+ public synchronized Ice.ObjectFactory findObjectFactory(String id)
+ {
+ return _objectFactoryMap.get(id);
+ }
+
+ private void
+ updateConnectionObservers()
+ {
+ try
+ {
+ assert(_outgoingConnectionFactory != null);
+ _outgoingConnectionFactory.updateConnectionObservers();
+ assert(_objectAdapterFactory != null);
+ _objectAdapterFactory.updateConnectionObservers();
+ }
+ catch(Ice.CommunicatorDestroyedException ex)
+ {
+ }
+ }
+
+ private void
+ updateThreadObservers()
+ {
+ try
+ {
+ if(_clientThreadPool != null)
+ {
+ _clientThreadPool.updateObservers();
+ }
+ if(_serverThreadPool != null)
+ {
+ _serverThreadPool.updateObservers();
+ }
+ assert(_objectAdapterFactory != null);
+ _objectAdapterFactory.updateThreadObservers();
+ if(_endpointHostResolver != null)
+ {
+ _endpointHostResolver.updateObserver();
+ }
+ if(_timer != null)
+ {
+ _timer.updateObserver(_initData.observer);
+ }
+ if(_queueExecutor != null)
+ {
+ _queueExecutor.updateObserver(_initData.observer);
+ }
+ }
+ catch(Ice.CommunicatorDestroyedException ex)
+ {
+ }
+ }
+
+ private String[]
+ validatePackages()
+ {
+ final String prefix = "Ice.Package.";
+ java.util.Map<String, String> map = _initData.properties.getPropertiesForPrefix(prefix);
+ java.util.List<String> packages = new java.util.ArrayList<String>();
+ for(java.util.Map.Entry<String, String> p : map.entrySet())
+ {
+ String key = p.getKey();
+ String pkg = p.getValue();
+ if(key.length() == prefix.length())
+ {
+ _initData.logger.warning("ignoring invalid property: " + key + "=" + pkg);
+ }
+ String module = key.substring(prefix.length());
+ String className = pkg + "." + module + "._Marker";
+ Class<?> cls = null;
+ try
+ {
+ cls = findClass(className);
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ if(cls == null)
+ {
+ _initData.logger.warning("unable to validate package: " + key + "=" + pkg);
+ }
+ else
+ {
+ packages.add(pkg);
+ }
+ }
+
+ String pkg = _initData.properties.getProperty("Ice.Default.Package");
+ if(pkg.length() > 0)
+ {
+ packages.add(pkg);
+ }
+ return packages.toArray(new String[packages.size()]);
+ }
+
+ private synchronized void
+ addAllAdminFacets()
+ {
+ java.util.Map<String, Ice.Object> filteredFacets = new java.util.HashMap<String, Ice.Object>();
+ for(java.util.Map.Entry<String, Ice.Object> p : _adminFacets.entrySet())
+ {
+ if(_adminFacetFilter.isEmpty() || _adminFacetFilter.contains(p.getKey()))
+ {
+ _adminAdapter.addFacet(p.getValue(), _adminIdentity, p.getKey());
+ }
+ else
+ {
+ filteredFacets.put(p.getKey(), p.getValue());
+ }
+ }
+ _adminFacets = filteredFacets;
+ }
+
+ private void
+ setServerProcessProxy(Ice.ObjectAdapter adminAdapter, Ice.Identity adminIdentity)
+ {
+ Ice.ObjectPrx admin = adminAdapter.createProxy(adminIdentity);
+ Ice.LocatorPrx locator = adminAdapter.getLocator();
+ String serverId = _initData.properties.getProperty("Ice.Admin.ServerId");
+
+ if(locator != null && !serverId.isEmpty())
+ {
+ Ice.ProcessPrx process = Ice.ProcessPrxHelper.uncheckedCast(admin.ice_facet("Process"));
+ try
+ {
+ //
+ // Note that as soon as the process proxy is registered, the communicator might be
+ // shutdown by a remote client and admin facets might start receiving calls.
+ //
+ locator.getRegistry().setServerProcessProxy(serverId, process);
+ }
+ catch(Ice.ServerNotFoundException ex)
+ {
+ if(_traceLevels.location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("couldn't register server `");
+ s.append(serverId);
+ s.append("' with the locator registry:\n");
+ s.append("the server is not known to the locator registry");
+ _initData.logger.trace(_traceLevels.locationCat, s.toString());
+ }
+
+ throw new Ice.InitializationException("Locator knows nothing about server `" + serverId + "'");
+ }
+ catch(Ice.LocalException ex)
+ {
+ if(_traceLevels.location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("couldn't register server `");
+ s.append(serverId);
+ s.append("' with the locator registry:\n");
+ s.append(ex.toString());
+ _initData.logger.trace(_traceLevels.locationCat, s.toString());
+ }
+ throw ex;
+ }
+
+ if(_traceLevels.location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("registered server `");
+ s.append(serverId);
+ s.append("' with the locator registry");
+ _initData.logger.trace(_traceLevels.locationCat, s.toString());
+ }
+ }
+ }
+
+ private NetworkProxy createNetworkProxy(Ice.Properties properties, int protocolSupport)
+ {
+ String proxyHost;
+
+ proxyHost = properties.getProperty("Ice.SOCKSProxyHost");
+ if(!proxyHost.isEmpty())
+ {
+ if(protocolSupport == Network.EnableIPv6)
+ {
+ throw new Ice.InitializationException("IPv6 only is not supported with SOCKS4 proxies");
+ }
+ int proxyPort = properties.getPropertyAsIntWithDefault("Ice.SOCKSProxyPort", 1080);
+ return new SOCKSNetworkProxy(proxyHost, proxyPort);
+ }
+
+ proxyHost = properties.getProperty("Ice.HTTPProxyHost");
+ if(!proxyHost.isEmpty())
+ {
+ return new HTTPNetworkProxy(proxyHost, properties.getPropertyAsIntWithDefault("Ice.HTTPProxyPort", 1080));
+ }
+
+ return null;
+ }
+
+ private static final int StateActive = 0;
+ private static final int StateDestroyInProgress = 1;
+ private static final int StateDestroyed = 2;
+ private int _state;
+
+ private final Ice.InitializationData _initData; // Immutable, not reset by destroy().
+ private final TraceLevels _traceLevels; // Immutable, not reset by destroy().
+ private final DefaultsAndOverrides _defaultsAndOverrides; // Immutable, not reset by destroy().
+ private final int _messageSizeMax; // Immutable, not reset by destroy().
+ private final int _batchAutoFlushSize; // Immutable, not reset by destroy().
+ private final int _cacheMessageBuffers; // Immutable, not reset by destroy().
+ private final ACMConfig _clientACM; // Immutable, not reset by destroy().
+ private final ACMConfig _serverACM; // Immutable, not reset by destroy().
+ private final Ice.ImplicitContextI _implicitContext;
+ private RouterManager _routerManager;
+ private LocatorManager _locatorManager;
+ private ReferenceFactory _referenceFactory;
+ private RequestHandlerFactory _requestHandlerFactory;
+ private ProxyFactory _proxyFactory;
+ private OutgoingConnectionFactory _outgoingConnectionFactory;
+ private ObjectAdapterFactory _objectAdapterFactory;
+ private int _protocolSupport;
+ private boolean _preferIPv6;
+ private NetworkProxy _networkProxy;
+ private ThreadPool _clientThreadPool;
+ private ThreadPool _serverThreadPool;
+ private EndpointHostResolver _endpointHostResolver;
+ private RetryQueue _retryQueue;
+ private Timer _timer;
+ private EndpointFactoryManager _endpointFactoryManager;
+ private Ice.PluginManager _pluginManager;
+
+ private boolean _adminEnabled = false;
+ private Ice.ObjectAdapter _adminAdapter;
+ private java.util.Map<String, Ice.Object> _adminFacets = new java.util.HashMap<String, Ice.Object>();
+ private java.util.Set<String> _adminFacetFilter = new java.util.HashSet<String>();
+ private Ice.Identity _adminIdentity;
+ private java.util.Map<Short, BufSizeWarnInfo> _setBufSizeWarn = new java.util.HashMap<Short, BufSizeWarnInfo>();
+
+ private java.util.Map<String, String> _typeToClassMap = new java.util.HashMap<String, String>();
+ final private String[] _packages;
+ final private boolean _useApplicationClassLoader;
+
+ private static boolean _oneOffDone = false;
+ private QueueExecutorService _queueExecutorService;
+ private QueueExecutor _queueExecutor;
+
+ @SuppressWarnings("deprecation")
+ private java.util.HashMap<String, Ice.ObjectFactory> _objectFactoryMap =
+ new java.util.HashMap<String, Ice.ObjectFactory>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/InvocationObserverI.java b/java-compat/src/Ice/src/main/java/IceInternal/InvocationObserverI.java
new file mode 100644
index 00000000000..93cb2fb906a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/InvocationObserverI.java
@@ -0,0 +1,249 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import IceMX.*;
+
+public class InvocationObserverI
+ extends IceMX.ObserverWithDelegate<IceMX.InvocationMetrics, Ice.Instrumentation.InvocationObserver>
+ implements Ice.Instrumentation.InvocationObserver
+{
+ static public final class RemoteInvocationHelper extends MetricsHelper<RemoteMetrics>
+ {
+ static private final AttributeResolver _attributes = new AttributeResolver()
+ {
+ {
+ try
+ {
+ Class<?> cl = RemoteInvocationHelper.class;
+ add("parent", cl.getDeclaredMethod("getParent"));
+ add("id", cl.getDeclaredMethod("getId"));
+ add("requestId", cl.getDeclaredMethod("getRequestId"));
+ CommunicatorObserverI.addConnectionAttributes(this, RemoteInvocationHelper.class);
+ }
+ catch(Exception ex)
+ {
+ ex.printStackTrace();
+ assert(false);
+ }
+ }
+ };
+
+ RemoteInvocationHelper(Ice.ConnectionInfo con, Ice.Endpoint endpt, int requestId, int size)
+ {
+ super(_attributes);
+ _connectionInfo = con;
+ _endpoint = endpt;
+ _requestId = requestId;
+ _size = size;
+ }
+
+ @Override
+ public void
+ initMetrics(RemoteMetrics v)
+ {
+ v.size += _size;
+ }
+
+ public String
+ getId()
+ {
+ if(_id == null)
+ {
+ _id = _endpoint.toString();
+ if(_connectionInfo.connectionId != null && !_connectionInfo.connectionId.isEmpty())
+ {
+ _id += " [" + _connectionInfo.connectionId + "]";
+ }
+ }
+ return _id;
+ }
+
+ int
+ getRequestId()
+ {
+ return _requestId;
+ }
+
+ public String
+ getParent()
+ {
+ if(_connectionInfo.adapterName != null && !_connectionInfo.adapterName.isEmpty())
+ {
+ return _connectionInfo.adapterName;
+ }
+ else
+ {
+ return "Communicator";
+ }
+ }
+
+ public Ice.ConnectionInfo
+ getConnectionInfo()
+ {
+ return _connectionInfo;
+ }
+
+ public Ice.Endpoint
+ getEndpoint()
+ {
+ return _endpoint;
+ }
+
+ public Ice.EndpointInfo
+ getEndpointInfo()
+ {
+ if(_endpointInfo == null)
+ {
+ _endpointInfo = _endpoint.getInfo();
+ }
+ return _endpointInfo;
+ }
+
+ final private Ice.ConnectionInfo _connectionInfo;
+ final private Ice.Endpoint _endpoint;
+ final private int _requestId;
+ final private int _size;
+ private String _id;
+ private Ice.EndpointInfo _endpointInfo;
+ }
+
+ static public final class CollocatedInvocationHelper extends MetricsHelper<CollocatedMetrics>
+ {
+ static private final AttributeResolver _attributes = new AttributeResolver()
+ {
+ {
+ try
+ {
+ Class<?> cl = CollocatedInvocationHelper.class;
+ add("parent", cl.getDeclaredMethod("getParent"));
+ add("id", cl.getDeclaredMethod("getId"));
+ add("requestId", cl.getDeclaredMethod("getRequestId"));
+ }
+ catch(Exception ex)
+ {
+ ex.printStackTrace();
+ assert(false);
+ }
+ }
+ };
+
+ CollocatedInvocationHelper(Ice.ObjectAdapter adapter, int requestId, int size)
+ {
+ super(_attributes);
+ _id = adapter.getName();
+ _requestId = requestId;
+ _size = size;
+ }
+
+ @Override
+ public void
+ initMetrics(CollocatedMetrics v)
+ {
+ v.size += _size;
+ }
+
+ public String
+ getId()
+ {
+ return _id;
+ }
+
+ int
+ getRequestId()
+ {
+ return _requestId;
+ }
+
+ public String
+ getParent()
+ {
+ return "Communicator";
+ }
+
+ final private int _requestId;
+ final private int _size;
+ final private String _id;
+ }
+
+ @Override
+ public void
+ userException()
+ {
+ forEach(_userException);
+ if(_delegate != null)
+ {
+ _delegate.userException();
+ }
+ }
+
+ @Override
+ public void
+ retried()
+ {
+ forEach(_incrementRetry);
+ if(_delegate != null)
+ {
+ _delegate.retried();
+ }
+ }
+
+ @Override
+ public Ice.Instrumentation.RemoteObserver
+ getRemoteObserver(Ice.ConnectionInfo con, Ice.Endpoint edpt, int requestId, int sz)
+ {
+ Ice.Instrumentation.RemoteObserver delegate = null;
+ if(_delegate != null)
+ {
+ delegate = _delegate.getRemoteObserver(con, edpt, requestId, sz);
+ }
+ return getObserver("Remote",
+ new RemoteInvocationHelper(con, edpt, requestId, sz),
+ RemoteMetrics.class,
+ RemoteObserverI.class,
+ delegate);
+ }
+
+ @Override
+ public Ice.Instrumentation.CollocatedObserver
+ getCollocatedObserver(Ice.ObjectAdapter adapter, int requestId, int sz)
+ {
+ Ice.Instrumentation.CollocatedObserver delegate = null;
+ if(_delegate != null)
+ {
+ delegate = _delegate.getCollocatedObserver(adapter, requestId, sz);
+ }
+ return getObserver("Collocated",
+ new CollocatedInvocationHelper(adapter, requestId, sz),
+ CollocatedMetrics.class,
+ CollocatedObserverI.class,
+ delegate);
+ }
+
+ final MetricsUpdate<InvocationMetrics> _incrementRetry = new MetricsUpdate<InvocationMetrics>()
+ {
+ @Override
+ public void
+ update(InvocationMetrics v)
+ {
+ ++v.retry;
+ }
+ };
+
+ final MetricsUpdate<InvocationMetrics> _userException = new MetricsUpdate<InvocationMetrics>()
+ {
+ @Override
+ public void
+ update(InvocationMetrics v)
+ {
+ ++v.userException;
+ }
+ };
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ListPatcher.java b/java-compat/src/Ice/src/main/java/IceInternal/ListPatcher.java
new file mode 100644
index 00000000000..56f3472d567
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ListPatcher.java
@@ -0,0 +1,46 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ListPatcher<T> implements Ice.ReadValueCallback
+{
+ public ListPatcher(java.util.List<T> list, Class<T> cls, int index)
+ {
+ _list = list;
+ _cls = cls;
+ _index = index;
+ }
+
+ public void valueReady(Ice.Object v)
+ {
+ if(v != null)
+ {
+ //
+ // Raise ClassCastException if the element doesn't match the expected type.
+ //
+ if(!_cls.isInstance(v))
+ {
+ throw new ClassCastException("expected element of type " + _cls.getName() + " but received " +
+ v.getClass().getName());
+ }
+ }
+
+ //
+ // This isn't very efficient for sequentially-accessed lists, but there
+ // isn't much we can do about it as long as a new patcher instance is
+ // created for each element.
+ //
+ _list.set(_index, _cls.cast(v));
+ }
+
+ private java.util.List<T> _list;
+ private Class<T> _cls;
+ private int _index;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java b/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java
new file mode 100644
index 00000000000..82c4dea0e25
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java
@@ -0,0 +1,708 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class LocatorInfo
+{
+ interface GetEndpointsCallback
+ {
+ void setEndpoints(EndpointI[] endpoints, boolean cached);
+ void setException(Ice.LocalException ex);
+ }
+
+ private static class RequestCallback
+ {
+ public void
+ response(LocatorInfo locatorInfo, Ice.ObjectPrx proxy)
+ {
+ EndpointI[] endpoints = null;
+ if(proxy != null)
+ {
+ Reference r = ((Ice.ObjectPrxHelperBase)proxy).__reference();
+ if(_ref.isWellKnown() && !Protocol.isSupported(_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(_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.
+ //
+ locatorInfo.getEndpoints(r, _ref, _ttl, _callback);
+ return;
+ }
+ }
+
+ if(_ref.getInstance().traceLevels().location >= 1)
+ {
+ locatorInfo.getEndpointsTrace(_ref, endpoints, false);
+ }
+ if(_callback != null)
+ {
+ _callback.setEndpoints(endpoints == null ? new EndpointI[0] : endpoints, false);
+ }
+ }
+
+ public void
+ exception(LocatorInfo locatorInfo, Exception exc)
+ {
+ try
+ {
+ locatorInfo.getEndpointsException(_ref, exc); // This throws.
+ }
+ catch(Ice.LocalException ex)
+ {
+ if(_callback != null)
+ {
+ _callback.setException(ex);
+ }
+ }
+ }
+
+ RequestCallback(Reference ref, int ttl, GetEndpointsCallback cb)
+ {
+ _ref = ref;
+ _ttl = ttl;
+ _callback = cb;
+ }
+
+ final Reference _ref;
+ final int _ttl;
+ final GetEndpointsCallback _callback;
+ }
+
+ private abstract class Request
+ {
+ public void
+ addCallback(Reference ref, Reference wellKnownRef, int ttl, GetEndpointsCallback cb)
+ {
+ RequestCallback callback = new RequestCallback(ref, ttl, cb);
+ synchronized(this)
+ {
+ if(!_response && _exception == null)
+ {
+ _callbacks.add(callback);
+ if(wellKnownRef != null) // This request is to resolve the endpoints of a cached well-known object ref
+ {
+ _wellKnownRefs.add(wellKnownRef);
+ }
+ if(!_sent)
+ {
+ _sent = true;
+ send();
+ }
+ return;
+ }
+ }
+
+ if(_response)
+ {
+ callback.response(_locatorInfo, _proxy);
+ }
+ else
+ {
+ assert(_exception != null);
+ callback.exception(_locatorInfo, _exception);
+ }
+ }
+
+ Request(LocatorInfo locatorInfo, Reference ref)
+ {
+ _locatorInfo = locatorInfo;
+ _ref = ref;
+ _sent = false;
+ _response = false;
+ }
+
+ protected void
+ response(Ice.ObjectPrx proxy)
+ {
+ synchronized(this)
+ {
+ _locatorInfo.finishRequest(_ref, _wellKnownRefs, proxy, false);
+ _response = true;
+ _proxy = proxy;
+ notifyAll();
+ }
+ for(RequestCallback callback : _callbacks)
+ {
+ callback.response(_locatorInfo, proxy);
+ }
+ }
+
+ protected void
+ exception(Exception ex)
+ {
+ synchronized(this)
+ {
+ _locatorInfo.finishRequest(_ref, _wellKnownRefs, null, ex instanceof Ice.UserException);
+ _exception = ex;
+ notifyAll();
+ }
+ for(RequestCallback callback : _callbacks)
+ {
+ callback.exception(_locatorInfo, ex);
+ }
+ }
+
+ protected abstract void send();
+
+ final protected LocatorInfo _locatorInfo;
+ final protected Reference _ref;
+
+ private java.util.List<RequestCallback> _callbacks = new java.util.ArrayList<RequestCallback>();
+ private java.util.List<Reference> _wellKnownRefs = new java.util.ArrayList<Reference>();
+ private boolean _sent;
+ private boolean _response;
+ private Ice.ObjectPrx _proxy;
+ private Exception _exception;
+ }
+
+ private class ObjectRequest extends Request
+ {
+ public ObjectRequest(LocatorInfo locatorInfo, Reference reference)
+ {
+ super(locatorInfo, reference);
+ assert(reference.isWellKnown());
+ }
+
+ @Override
+ protected void
+ send()
+ {
+ try
+ {
+ _locatorInfo.getLocator().begin_findObjectById(
+ _ref.getIdentity(),
+ new Ice.Callback_Locator_findObjectById()
+ {
+ @Override
+ public void
+ response(Ice.ObjectPrx proxy)
+ {
+ ObjectRequest.this.response(proxy);
+ }
+
+ @Override
+ public void
+ exception(Ice.UserException ex)
+ {
+ ObjectRequest.this.exception(ex);
+ }
+
+ @Override
+ public void
+ exception(Ice.LocalException ex)
+ {
+ ObjectRequest.this.exception(ex);
+ }
+ });
+ }
+ catch(Exception ex)
+ {
+ exception(ex);
+ }
+ }
+ }
+
+ private class AdapterRequest extends Request
+ {
+ public AdapterRequest(LocatorInfo locatorInfo, Reference reference)
+ {
+ super(locatorInfo, reference);
+ assert(reference.isIndirect());
+ }
+
+ @Override
+ protected void
+ send()
+ {
+ try
+ {
+ _locatorInfo.getLocator().begin_findAdapterById(
+ _ref.getAdapterId(),
+ new Ice.Callback_Locator_findAdapterById()
+ {
+ @Override
+ public void
+ response(Ice.ObjectPrx proxy)
+ {
+ AdapterRequest.this.response(proxy);
+ }
+
+ @Override
+ public void
+ exception(Ice.UserException ex)
+ {
+ AdapterRequest.this.exception(ex);
+ }
+
+ @Override
+ public void
+ exception(Ice.LocalException ex)
+ {
+ AdapterRequest.this.exception(ex);
+ }
+ });
+ }
+ catch(Exception ex)
+ {
+ exception(ex);
+ }
+ }
+ }
+
+ LocatorInfo(Ice.LocatorPrx locator, LocatorTable table, boolean background)
+ {
+ _locator = locator;
+ _table = table;
+ _background = background;
+ }
+
+ synchronized public void
+ destroy()
+ {
+ _locatorRegistry = null;
+ _table.clear();
+ }
+
+ @Override
+ public boolean
+ equals(java.lang.Object obj)
+ {
+ if(this == obj)
+ {
+ return true;
+ }
+
+ if(obj instanceof LocatorInfo)
+ {
+ return _locator.equals(((LocatorInfo)obj)._locator);
+ }
+
+ return false;
+ }
+
+ @Override
+ public int
+ hashCode()
+ {
+ return _locator.hashCode();
+ }
+
+ public Ice.LocatorPrx
+ getLocator()
+ {
+ //
+ // No synchronization necessary, _locator is immutable.
+ //
+ return _locator;
+ }
+
+ public Ice.LocatorRegistryPrx
+ getLocatorRegistry()
+ {
+ synchronized(this)
+ {
+ if(_locatorRegistry != null)
+ {
+ return _locatorRegistry;
+ }
+ }
+
+ //
+ // Do not make locator calls from within sync.
+ //
+ Ice.LocatorRegistryPrx locatorRegistry = _locator.getRegistry();
+ if(locatorRegistry == null)
+ {
+ return null;
+ }
+
+ synchronized(this)
+ {
+ //
+ // The locator registry can't be located. We use ordered
+ // endpoint selection in case the locator returned a proxy
+ // with some endpoints which are prefered to be tried first.
+ //
+ _locatorRegistry = (Ice.LocatorRegistryPrx)locatorRegistry.ice_locator(null).ice_endpointSelection(
+ Ice.EndpointSelectionType.Ordered);
+ return _locatorRegistry;
+ }
+ }
+
+ public void
+ getEndpoints(Reference ref, int ttl, GetEndpointsCallback callback)
+ {
+ getEndpoints(ref, null, ttl, callback);
+ }
+
+ public void
+ getEndpoints(Reference ref, Reference wellKnownRef, int ttl, GetEndpointsCallback callback)
+ {
+ assert(ref.isIndirect());
+ EndpointI[] endpoints = null;
+ Ice.Holder<Boolean> cached = new Ice.Holder<Boolean>();
+ if(!ref.isWellKnown())
+ {
+ endpoints = _table.getAdapterEndpoints(ref.getAdapterId(), ttl, cached);
+ if(!cached.value)
+ {
+ if(_background && endpoints != null)
+ {
+ getAdapterRequest(ref).addCallback(ref, wellKnownRef, ttl, null);
+ }
+ else
+ {
+ getAdapterRequest(ref).addCallback(ref, wellKnownRef, ttl, callback);
+ return;
+ }
+ }
+ }
+ else
+ {
+ Reference r = _table.getObjectReference(ref.getIdentity(), ttl, cached);
+ if(!cached.value)
+ {
+ if(_background && r != null)
+ {
+ getObjectRequest(ref).addCallback(ref, null, ttl, null);
+ }
+ else
+ {
+ getObjectRequest(ref).addCallback(ref, null, ttl, callback);
+ return;
+ }
+ }
+
+ if(!r.isIndirect())
+ {
+ endpoints = r.getEndpoints();
+ }
+ else if(!r.isWellKnown())
+ {
+ getEndpoints(r, ref, ttl, callback);
+ return;
+ }
+ }
+
+ assert(endpoints != null);
+ if(ref.getInstance().traceLevels().location >= 1)
+ {
+ getEndpointsTrace(ref, endpoints, true);
+ }
+ if(callback != null)
+ {
+ callback.setEndpoints(endpoints, true);
+ }
+ }
+
+ public void
+ clearCache(Reference ref)
+ {
+ assert(ref.isIndirect());
+
+ if(!ref.isWellKnown())
+ {
+ EndpointI[] endpoints = _table.removeAdapterEndpoints(ref.getAdapterId());
+
+ if(endpoints != null && ref.getInstance().traceLevels().location >= 2)
+ {
+ trace("removed endpoints from locator table\n", ref, endpoints);
+ }
+ }
+ else
+ {
+ Reference r = _table.removeObjectReference(ref.getIdentity());
+ if(r != null)
+ {
+ if(!r.isIndirect())
+ {
+ if(ref.getInstance().traceLevels().location >= 2)
+ {
+ trace("removed endpoints from locator table", ref, r.getEndpoints());
+ }
+ }
+ else if(!r.isWellKnown())
+ {
+ clearCache(r);
+ }
+ }
+ }
+ }
+
+ private void
+ trace(String msg, Reference ref, EndpointI[] endpoints)
+ {
+ assert(ref.isIndirect());
+
+ StringBuilder s = new StringBuilder(128);
+ s.append(msg);
+ s.append("\n");
+ if(!ref.isWellKnown())
+ {
+ s.append("adapter = ");
+ s.append(ref.getAdapterId());
+ s.append("\n");
+ }
+ else
+ {
+ s.append("object = ");
+ s.append(Ice.Util.identityToString(ref.getIdentity()));
+ s.append("\n");
+ }
+
+ s.append("endpoints = ");
+ final int sz = endpoints.length;
+ for(int i = 0; i < sz; i++)
+ {
+ s.append(endpoints[i].toString());
+ if(i + 1 < sz)
+ {
+ s.append(":");
+ }
+ }
+
+ ref.getInstance().initializationData().logger.trace(ref.getInstance().traceLevels().locationCat, s.toString());
+ }
+
+ private void
+ getEndpointsException(Reference ref, Exception exc)
+ {
+ assert(ref.isIndirect());
+
+ try
+ {
+ throw exc;
+ }
+ catch(Ice.AdapterNotFoundException ex)
+ {
+ final Instance instance = ref.getInstance();
+ if(instance.traceLevels().location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("adapter not found\n");
+ s.append("adapter = ");
+ s.append(ref.getAdapterId());
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
+ }
+
+ Ice.NotRegisteredException e = new Ice.NotRegisteredException();
+ e.kindOfObject = "object adapter";
+ e.id = ref.getAdapterId();
+ throw e;
+ }
+ catch(Ice.ObjectNotFoundException ex)
+ {
+ final Instance instance = ref.getInstance();
+ if(instance.traceLevels().location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("object not found\n");
+ s.append("object = ");
+ s.append(Ice.Util.identityToString(ref.getIdentity()));
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
+ }
+
+ Ice.NotRegisteredException e = new Ice.NotRegisteredException();
+ e.kindOfObject = "object";
+ e.id = Ice.Util.identityToString(ref.getIdentity());
+ throw e;
+ }
+ catch(Ice.NotRegisteredException ex)
+ {
+ throw ex;
+ }
+ catch(Ice.LocalException ex)
+ {
+ final Instance instance = ref.getInstance();
+ if(instance.traceLevels().location >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("couldn't contact the locator to retrieve adapter endpoints\n");
+ if(ref.getAdapterId().length() > 0)
+ {
+ s.append("adapter = ");
+ s.append(ref.getAdapterId());
+ s.append("\n");
+ }
+ else
+ {
+ s.append("object = ");
+ s.append(Ice.Util.identityToString(ref.getIdentity()));
+ s.append("\n");
+ }
+ s.append("reason = " + ex);
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
+ }
+ throw ex;
+ }
+ catch(Exception ex)
+ {
+ assert(false);
+ }
+ }
+
+ private void
+ getEndpointsTrace(Reference ref, EndpointI[] endpoints, boolean cached)
+ {
+ if(endpoints != null && endpoints.length > 0)
+ {
+ if(cached)
+ {
+ trace("found endpoints in locator table", ref, endpoints);
+ }
+ else
+ {
+ trace("retrieved endpoints from locator, adding to locator table", ref, endpoints);
+ }
+ }
+ else
+ {
+ final Instance instance = ref.getInstance();
+ StringBuilder s = new StringBuilder(128);
+ s.append("no endpoints configured for ");
+ if(ref.getAdapterId().length() > 0)
+ {
+ s.append("adapter\n");
+ s.append("adapter = ");
+ s.append(ref.getAdapterId());
+ s.append("\n");
+ }
+ else
+ {
+ s.append("object\n");
+ s.append("object = ");
+ s.append(Ice.Util.identityToString(ref.getIdentity()));
+ s.append("\n");
+ }
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
+ }
+ }
+
+ synchronized private Request
+ getAdapterRequest(Reference ref)
+ {
+ if(ref.getInstance().traceLevels().location >= 1)
+ {
+ Instance instance = ref.getInstance();
+ StringBuilder s = new StringBuilder(128);
+ s.append("searching for adapter by id\n");
+ s.append("adapter = ");
+ s.append(ref.getAdapterId());
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
+ }
+
+ Request request = _adapterRequests.get(ref.getAdapterId());
+ if(request != null)
+ {
+ return request;
+ }
+ request = new AdapterRequest(this, ref);
+ _adapterRequests.put(ref.getAdapterId(), request);
+ return request;
+ }
+
+ synchronized private Request
+ getObjectRequest(Reference ref)
+ {
+ if(ref.getInstance().traceLevels().location >= 1)
+ {
+ Instance instance = ref.getInstance();
+ StringBuilder s = new StringBuilder(128);
+ s.append("searching for object by id\n");
+ s.append("object = ");
+ s.append(Ice.Util.identityToString(ref.getIdentity()));
+ instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
+ }
+
+ Request request = _objectRequests.get(ref.getIdentity());
+ if(request != null)
+ {
+ return request;
+ }
+ request = new ObjectRequest(this, ref);
+ _objectRequests.put(ref.getIdentity(), request);
+ return request;
+ }
+
+ private void
+ finishRequest(Reference ref, java.util.List<Reference> wellKnownRefs, Ice.ObjectPrx proxy, boolean notRegistered)
+ {
+ if(proxy == null || ((Ice.ObjectPrxHelperBase)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(Reference r : wellKnownRefs)
+ {
+ _table.removeObjectReference(r.getIdentity());
+ }
+ }
+
+ if(!ref.isWellKnown())
+ {
+ if(proxy != null && !((Ice.ObjectPrxHelperBase)proxy).__reference().isIndirect())
+ {
+ // Cache the adapter endpoints.
+ _table.addAdapterEndpoints(ref.getAdapterId(),
+ ((Ice.ObjectPrxHelperBase)proxy).__reference().getEndpoints());
+ }
+ else if(notRegistered) // If the adapter isn't registered anymore, remove it from the cache.
+ {
+ _table.removeAdapterEndpoints(ref.getAdapterId());
+ }
+
+ synchronized(this)
+ {
+ assert(_adapterRequests.get(ref.getAdapterId()) != null);
+ _adapterRequests.remove(ref.getAdapterId());
+ }
+ }
+ else
+ {
+ if(proxy != null && !((Ice.ObjectPrxHelperBase)proxy).__reference().isWellKnown())
+ {
+ // Cache the well-known object reference.
+ _table.addObjectReference(ref.getIdentity(), ((Ice.ObjectPrxHelperBase)proxy).__reference());
+ }
+ else if(notRegistered) // If the well-known object isn't registered anymore, remove it from the cache.
+ {
+ _table.removeObjectReference(ref.getIdentity());
+ }
+
+ synchronized(this)
+ {
+ assert(_objectRequests.get(ref.getIdentity()) != null);
+ _objectRequests.remove(ref.getIdentity());
+ }
+ }
+ }
+
+ private final Ice.LocatorPrx _locator;
+ private Ice.LocatorRegistryPrx _locatorRegistry;
+ private final LocatorTable _table;
+ private final boolean _background;
+
+ private java.util.Map<String, Request> _adapterRequests = new java.util.HashMap<String, Request>();
+ private java.util.Map<Ice.Identity, Request> _objectRequests = new java.util.HashMap<Ice.Identity, Request>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/LocatorManager.java b/java-compat/src/Ice/src/main/java/IceInternal/LocatorManager.java
new file mode 100644
index 00000000000..201dacf41b2
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/LocatorManager.java
@@ -0,0 +1,140 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class LocatorManager
+{
+ static private final class LocatorKey implements Cloneable
+ {
+ @Override
+ public boolean
+ equals(Object o)
+ {
+ assert(o instanceof LocatorKey);
+ LocatorKey k = (LocatorKey)o;
+ if(!k._id.equals(_id))
+ {
+ return false;
+ }
+ if(!k._encoding.equals(_encoding))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int
+ hashCode()
+ {
+ int h = 5381;
+ h = IceInternal.HashUtil.hashAdd(h, _id);
+ h = IceInternal.HashUtil.hashAdd(h, _encoding);
+ return h;
+ }
+
+ @Override
+ public LocatorKey
+ clone()
+ {
+ LocatorKey c = null;
+ try
+ {
+ c = (LocatorKey)super.clone();
+ }
+ catch(CloneNotSupportedException ex)
+ {
+ assert false; // impossible
+ }
+ return c;
+ }
+
+ LocatorKey set(Ice.LocatorPrx locator)
+ {
+ Reference r = ((Ice.ObjectPrxHelperBase)locator).__reference();
+ _id = r.getIdentity();
+ _encoding = r.getEncoding();
+ return this;
+ }
+
+ private Ice.Identity _id;
+ private Ice.EncodingVersion _encoding;
+ }
+
+ LocatorManager(Ice.Properties properties)
+ {
+ _background = properties.getPropertyAsInt("Ice.BackgroundLocatorCacheUpdates") > 0;
+ }
+
+ synchronized void
+ destroy()
+ {
+ for(LocatorInfo info : _table.values())
+ {
+ info.destroy();
+ }
+ _table.clear();
+ _locatorTables.clear();
+ }
+
+ //
+ // Returns locator info for a given locator. Automatically creates
+ // the locator info if it doesn't exist yet.
+ //
+ public LocatorInfo
+ get(Ice.LocatorPrx loc)
+ {
+ if(loc == null)
+ {
+ return null;
+ }
+
+ //
+ // The locator can't be located.
+ //
+ Ice.LocatorPrx locator = Ice.LocatorPrxHelper.uncheckedCast(loc.ice_locator(null));
+
+ //
+ // TODO: reap unused locator info objects?
+ //
+
+ synchronized(this)
+ {
+ LocatorInfo info = _table.get(locator);
+ if(info == null)
+ {
+ //
+ // Rely on locator identity for the adapter table. We want to
+ // have only one table per locator (not one per locator
+ // proxy).
+ //
+ LocatorTable table = _locatorTables.get(_lookupKey.set(locator));
+ if(table == null)
+ {
+ table = new LocatorTable();
+ _locatorTables.put(_lookupKey.clone(), table);
+ }
+
+ info = new LocatorInfo(locator, table, _background);
+ _table.put(locator, info);
+ }
+
+ return info;
+ }
+ }
+
+ final private boolean _background;
+
+ private java.util.HashMap<Ice.LocatorPrx, LocatorInfo> _table =
+ new java.util.HashMap<Ice.LocatorPrx, LocatorInfo>();
+ private java.util.HashMap<LocatorKey, LocatorTable> _locatorTables =
+ new java.util.HashMap<LocatorKey, LocatorTable>();
+ private LocatorKey _lookupKey = new LocatorKey(); // A key used for the lookup
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/LocatorTable.java b/java-compat/src/Ice/src/main/java/IceInternal/LocatorTable.java
new file mode 100644
index 00000000000..0f2a13bda37
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/LocatorTable.java
@@ -0,0 +1,132 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class LocatorTable
+{
+ LocatorTable()
+ {
+ }
+
+ synchronized void
+ clear()
+ {
+ _adapterEndpointsTable.clear();
+ _objectTable.clear();
+ }
+
+ synchronized IceInternal.EndpointI[]
+ getAdapterEndpoints(String adapter, int ttl, Ice.Holder<Boolean> cached)
+ {
+ if(ttl == 0) // Locator cache disabled.
+ {
+ cached.value = false;
+ return null;
+ }
+
+ EndpointTableEntry entry = _adapterEndpointsTable.get(adapter);
+ if(entry != null)
+ {
+ cached.value = checkTTL(entry.time, ttl);
+ return entry.endpoints;
+ }
+ cached.value = false;
+ return null;
+ }
+
+ synchronized void
+ addAdapterEndpoints(String adapter, IceInternal.EndpointI[] endpoints)
+ {
+ _adapterEndpointsTable.put(adapter,
+ new EndpointTableEntry(IceInternal.Time.currentMonotonicTimeMillis(), endpoints));
+ }
+
+ synchronized IceInternal.EndpointI[]
+ removeAdapterEndpoints(String adapter)
+ {
+ EndpointTableEntry entry = _adapterEndpointsTable.remove(adapter);
+ return entry != null ? entry.endpoints : null;
+ }
+
+ synchronized Reference
+ getObjectReference(Ice.Identity id, int ttl, Ice.Holder<Boolean> cached)
+ {
+ if(ttl == 0) // Locator cache disabled.
+ {
+ cached.value = false;
+ return null;
+ }
+
+ ReferenceTableEntry entry = _objectTable.get(id);
+ if(entry != null)
+ {
+ cached.value = checkTTL(entry.time, ttl);
+ return entry.reference;
+ }
+ cached.value = false;
+ return null;
+ }
+
+ synchronized void
+ addObjectReference(Ice.Identity id, Reference ref)
+ {
+ _objectTable.put(id, new ReferenceTableEntry(IceInternal.Time.currentMonotonicTimeMillis(), ref));
+ }
+
+ synchronized Reference
+ removeObjectReference(Ice.Identity id)
+ {
+ ReferenceTableEntry entry = _objectTable.remove(id);
+ return entry != null ? entry.reference : null;
+ }
+
+ private boolean
+ checkTTL(long time, int ttl)
+ {
+ assert(ttl != 0);
+ if(ttl < 0) // TTL = infinite
+ {
+ return true;
+ }
+ else
+ {
+ return IceInternal.Time.currentMonotonicTimeMillis() - time <= ((long)ttl * 1000);
+ }
+ }
+
+ private static final class EndpointTableEntry
+ {
+ public EndpointTableEntry(long time, IceInternal.EndpointI[] endpoints)
+ {
+ this.time = time;
+ this.endpoints = endpoints;
+ }
+
+ final public long time;
+ final public IceInternal.EndpointI[] endpoints;
+ }
+
+ private static final class ReferenceTableEntry
+ {
+ public ReferenceTableEntry(long time, Reference reference)
+ {
+ this.time = time;
+ this.reference = reference;
+ }
+
+ final public long time;
+ final public Reference reference;
+ }
+
+ private java.util.Map<String, EndpointTableEntry> _adapterEndpointsTable =
+ new java.util.HashMap<String, EndpointTableEntry>();
+ private java.util.Map<Ice.Identity, ReferenceTableEntry> _objectTable =
+ new java.util.HashMap<Ice.Identity, ReferenceTableEntry>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminI.java b/java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminI.java
new file mode 100644
index 00000000000..4a322318fad
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminI.java
@@ -0,0 +1,465 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class LoggerAdminI extends Ice._LoggerAdminDisp
+{
+ @Override
+ public void attachRemoteLogger(Ice.RemoteLoggerPrx prx, Ice.LogMessageType[] messageTypes, String[] categories,
+ int messageMax, Ice.Current current)
+ throws Ice.RemoteLoggerAlreadyAttachedException
+ {
+ if(prx == null)
+ {
+ return; // can't send this null RemoteLogger anything!
+ }
+
+ Ice.RemoteLoggerPrx remoteLogger = Ice.RemoteLoggerPrxHelper.uncheckedCast(prx.ice_twoway());
+
+ Filters filters = new Filters(messageTypes, categories);
+ java.util.List<Ice.LogMessage> initLogMessages = null;
+
+ synchronized(this)
+ {
+ if(_sendLogCommunicator == null)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+
+ _sendLogCommunicator =
+ createSendLogCommunicator(current.adapter.getCommunicator(), _logger.getLocalLogger());
+ }
+
+ Ice.Identity remoteLoggerId = remoteLogger.ice_getIdentity();
+
+ if(_remoteLoggerMap.containsKey(remoteLoggerId))
+ {
+ if(_traceLevel > 0)
+ {
+ _logger.trace(_traceCategory, "rejecting `" + remoteLogger.toString() +
+ "' with RemoteLoggerAlreadyAttachedException");
+ }
+
+ throw new Ice.RemoteLoggerAlreadyAttachedException();
+ }
+
+ _remoteLoggerMap.put(remoteLoggerId,
+ new RemoteLoggerData(changeCommunicator(remoteLogger, _sendLogCommunicator), filters));
+
+ if(messageMax != 0)
+ {
+ initLogMessages = new java.util.LinkedList<Ice.LogMessage>(_queue); // copy
+ }
+ else
+ {
+ initLogMessages = new java.util.LinkedList<Ice.LogMessage>();
+ }
+ }
+
+ if(_traceLevel > 0)
+ {
+ _logger.trace(_traceCategory, "attached `" + remoteLogger.toString() + "'");
+ }
+
+ if(!initLogMessages.isEmpty())
+ {
+ filterLogMessages(initLogMessages, filters.messageTypes, filters.traceCategories, messageMax);
+ }
+
+ final Ice.Callback initCompletedCb = new Ice.Callback()
+ {
+ @Override
+ public void completed(Ice.AsyncResult r)
+ {
+ Ice.RemoteLoggerPrx remoteLogger = Ice.RemoteLoggerPrxHelper.uncheckedCast(r.getProxy());
+
+ try
+ {
+ remoteLogger.end_init(r);
+
+ if(_traceLevel > 1)
+ {
+ _logger.trace(_traceCategory, r.getOperation() + " on `" + remoteLogger.toString() +
+ "' completed successfully");
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ deadRemoteLogger(remoteLogger, _logger, ex, r.getOperation());
+ }
+ }
+ };
+
+ try
+ {
+ remoteLogger.begin_init(_logger.getPrefix(), initLogMessages.toArray(new Ice.LogMessage[0]),
+ initCompletedCb);
+ }
+ catch(Ice.LocalException ex)
+ {
+ deadRemoteLogger(remoteLogger, _logger, ex, "init");
+ throw ex;
+ }
+ }
+
+ @Override
+ public boolean detachRemoteLogger(Ice.RemoteLoggerPrx remoteLogger, Ice.Current current)
+ {
+ if(remoteLogger == null)
+ {
+ return false;
+ }
+
+ //
+ // No need to convert the proxy as we only use its identity
+ //
+ boolean found = removeRemoteLogger(remoteLogger);
+
+ if(_traceLevel > 0)
+ {
+ if(found)
+ {
+ _logger.trace(_traceCategory, "detached `" + remoteLogger.toString() + "'");
+ }
+ else
+ {
+ _logger.trace(_traceCategory, "cannot detach `" + remoteLogger.toString() + "': not found");
+ }
+ }
+
+ return found;
+ }
+
+ @Override
+ public Ice.LogMessage[] getLog(Ice.LogMessageType[] messageTypes, String[] categories, int messageMax,
+ Ice.StringHolder prefix, Ice.Current current)
+ {
+ java.util.List<Ice.LogMessage> logMessages = null;
+ synchronized(this)
+ {
+ if(messageMax != 0)
+ {
+ logMessages = new java.util.LinkedList<Ice.LogMessage>(_queue);
+ }
+ else
+ {
+ logMessages = new java.util.LinkedList<Ice.LogMessage>();
+ }
+ }
+
+ prefix.value = _logger.getPrefix();
+
+ if(!logMessages.isEmpty())
+ {
+ Filters filters = new Filters(messageTypes, categories);
+ filterLogMessages(logMessages, filters.messageTypes, filters.traceCategories, messageMax);
+ }
+ return logMessages.toArray(new Ice.LogMessage[0]);
+ }
+
+
+ LoggerAdminI(Ice.Properties props, LoggerAdminLoggerI logger)
+ {
+ _maxLogCount = props.getPropertyAsIntWithDefault("Ice.Admin.Logger.KeepLogs", 100);
+ _maxTraceCount = props.getPropertyAsIntWithDefault("Ice.Admin.Logger.KeepTraces", 100);
+ _traceLevel = props.getPropertyAsInt("Ice.Trace.Admin.Logger");
+ _logger = logger;
+ }
+
+ void destroy()
+ {
+ Ice.Communicator sendLogCommunicator = null;
+
+ synchronized(this)
+ {
+ if(!_destroyed)
+ {
+ _destroyed = true;
+ sendLogCommunicator = _sendLogCommunicator;
+ _sendLogCommunicator = null;
+ }
+ }
+
+ //
+ // Destroy outside lock to avoid deadlock when there are outstanding two-way log calls sent to
+ // remote logggers
+ //
+ if(sendLogCommunicator != null)
+ {
+ sendLogCommunicator.destroy();
+ }
+ }
+
+ synchronized java.util.List<Ice.RemoteLoggerPrx> log(Ice.LogMessage logMessage)
+ {
+ java.util.List<Ice.RemoteLoggerPrx> remoteLoggers = null;
+
+ //
+ // Put message in _queue
+ //
+ if((logMessage.type != Ice.LogMessageType.TraceMessage && _maxLogCount > 0) ||
+ (logMessage.type == Ice.LogMessageType.TraceMessage && _maxTraceCount > 0))
+ {
+ _queue.add(logMessage); // add at the end
+
+ if(logMessage.type != Ice.LogMessageType.TraceMessage)
+ {
+ assert(_maxLogCount > 0);
+ if(_logCount == _maxLogCount)
+ {
+ //
+ // Need to remove the oldest log from the queue
+ //
+ assert(_oldestLog != -1);
+ _queue.remove(_oldestLog);
+ int qs = _queue.size();
+
+ while(_oldestLog < qs && _queue.get(_oldestLog).type == Ice.LogMessageType.TraceMessage)
+ {
+ _oldestLog++;
+ }
+ assert(_oldestLog < qs); // remember: we just added a log message at end
+ }
+ else
+ {
+ assert(_logCount < _maxLogCount);
+ _logCount++;
+ if(_oldestLog == -1)
+ {
+ _oldestLog = _queue.size() - 1;
+ }
+ }
+ }
+ else
+ {
+ assert(_maxTraceCount > 0);
+ if(_traceCount == _maxTraceCount)
+ {
+ //
+ // Need to remove the oldest trace from the queue
+ //
+ assert(_oldestTrace != -1);
+ _queue.remove(_oldestTrace);
+ int qs = _queue.size();
+ while(_oldestTrace < qs && _queue.get(_oldestTrace).type != Ice.LogMessageType.TraceMessage)
+ {
+ _oldestTrace++;
+ }
+ assert(_oldestTrace < qs); // remember: we just added a trace message at end
+ }
+ else
+ {
+ assert(_traceCount < _maxTraceCount);
+ _traceCount++;
+ if(_oldestTrace == -1)
+ {
+ _oldestTrace = _queue.size() - 1;
+ }
+ }
+ }
+
+ //
+ // Queue updated, now find which remote loggers want this message
+ //
+ for(RemoteLoggerData p : _remoteLoggerMap.values())
+ {
+ Filters filters = p.filters;
+
+ if(filters.messageTypes.isEmpty() || filters.messageTypes.contains(logMessage.type))
+ {
+ if(logMessage.type != Ice.LogMessageType.TraceMessage || filters.traceCategories.isEmpty() ||
+ filters.traceCategories.contains(logMessage.traceCategory))
+ {
+ if(remoteLoggers == null)
+ {
+ remoteLoggers = new java.util.ArrayList<Ice.RemoteLoggerPrx>();
+ }
+ remoteLoggers.add(p.remoteLogger);
+ }
+ }
+ }
+ }
+
+ return remoteLoggers;
+ }
+
+ void deadRemoteLogger(Ice.RemoteLoggerPrx remoteLogger, Ice.Logger logger, Ice.LocalException ex, String operation)
+ {
+ //
+ // No need to convert remoteLogger as we only use its identity
+ //
+ if(removeRemoteLogger(remoteLogger))
+ {
+ if(_traceLevel > 0)
+ {
+ logger.trace(_traceCategory, "detached `" + remoteLogger.toString() + "' because "
+ + operation + " raised:\n" + ex.toString());
+ }
+ }
+ }
+
+ int getTraceLevel()
+ {
+ return _traceLevel;
+ }
+
+ private synchronized boolean removeRemoteLogger(Ice.RemoteLoggerPrx remoteLogger)
+ {
+ return _remoteLoggerMap.remove(remoteLogger.ice_getIdentity()) != null;
+ }
+
+ private static void filterLogMessages(java.util.List<Ice.LogMessage> logMessages,
+ java.util.Set<Ice.LogMessageType> messageTypes,
+ java.util.Set<String> traceCategories, int messageMax)
+ {
+ assert(!logMessages.isEmpty() && messageMax != 0);
+
+ //
+ // Filter only if one of the 3 filters is set; messageMax < 0 means "give me all"
+ // that match the other filters, if any.
+ //
+ if(!messageTypes.isEmpty() || !traceCategories.isEmpty() || messageMax > 0)
+ {
+ int count = 0;
+ java.util.ListIterator<Ice.LogMessage> p = logMessages.listIterator(logMessages.size());
+ while(p.hasPrevious())
+ {
+ boolean keepIt = false;
+ Ice.LogMessage msg = p.previous();
+ if(messageTypes.isEmpty() || messageTypes.contains(msg.type))
+ {
+ if(msg.type != Ice.LogMessageType.TraceMessage || traceCategories.isEmpty() ||
+ traceCategories.contains(msg.traceCategory))
+ {
+ keepIt = true;
+ }
+ }
+
+ if(keepIt)
+ {
+ ++count;
+ if(messageMax > 0 && count >= messageMax)
+ {
+ if(p.hasPrevious())
+ {
+ int removeCount = p.previousIndex() + 1;
+ for(int i = 0; i < removeCount; ++i)
+ {
+ logMessages.remove(0);
+ }
+ }
+ break; // while
+ }
+ }
+ else
+ {
+ p.remove();
+ }
+ }
+ }
+ // else, don't need any filtering
+ }
+
+ //
+ // Change this proxy's communicator, while keeping its invocation timeout
+ //
+ private static Ice.RemoteLoggerPrx changeCommunicator(Ice.RemoteLoggerPrx prx, Ice.Communicator communicator)
+ {
+ if(prx == null)
+ {
+ return null;
+ }
+
+ Ice.ObjectPrx result = communicator.stringToProxy(prx.toString());
+ return Ice.RemoteLoggerPrxHelper.uncheckedCast(result.ice_invocationTimeout(prx.ice_getInvocationTimeout()));
+ }
+
+ private static void copyProperties(String prefix, Ice.Properties from, Ice.Properties to)
+ {
+ for(java.util.Map.Entry<String, String> p : from.getPropertiesForPrefix(prefix).entrySet())
+ {
+ to.setProperty(p.getKey(), p.getValue());
+ }
+ }
+
+ private static Ice.Communicator createSendLogCommunicator(Ice.Communicator communicator, Ice.Logger logger)
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.logger = logger;
+ initData.properties = Ice.Util.createProperties();
+
+ Ice.Properties mainProps = communicator.getProperties();
+
+ copyProperties("Ice.Default.Locator", mainProps, initData.properties);
+ copyProperties("Ice.Plugin.IceSSL", mainProps, initData.properties);
+ copyProperties("IceSSL.", mainProps, initData.properties);
+
+ String[] extraProps = mainProps.getPropertyAsList("Ice.Admin.Logger.Properties");
+
+ if(extraProps.length > 0)
+ {
+ for(int i = 0; i < extraProps.length; ++i)
+ {
+ String p = extraProps[i];
+ if(!p.startsWith("--"))
+ {
+ extraProps[i] = "--" + p;
+ }
+ }
+ initData.properties.parseCommandLineOptions("", extraProps);
+ }
+ return Ice.Util.initialize(initData);
+ }
+
+
+ private final java.util.List<Ice.LogMessage> _queue = new java.util.LinkedList<Ice.LogMessage>();
+ private int _logCount = 0; // non-trace messages
+ private final int _maxLogCount;
+ private int _traceCount = 0;
+ private final int _maxTraceCount;
+ private final int _traceLevel;
+
+ private int _oldestTrace = -1;
+ private int _oldestLog = -1;
+
+ private static class Filters
+ {
+ Filters(Ice.LogMessageType[] m, String[] c)
+ {
+ messageTypes = new java.util.HashSet<Ice.LogMessageType>(java.util.Arrays.asList(m));
+ traceCategories = new java.util.HashSet<String>(java.util.Arrays.asList(c));
+ }
+
+ final java.util.Set<Ice.LogMessageType> messageTypes;
+ final java.util.Set<String> traceCategories;
+ }
+
+ private static class RemoteLoggerData
+ {
+ RemoteLoggerData(Ice.RemoteLoggerPrx prx, Filters f)
+ {
+ remoteLogger = prx;
+ filters = f;
+ }
+
+ final Ice.RemoteLoggerPrx remoteLogger;
+ final Filters filters;
+ }
+
+ private final java.util.Map<Ice.Identity, RemoteLoggerData> _remoteLoggerMap
+ = new java.util.HashMap<Ice.Identity, RemoteLoggerData>();
+
+ private final LoggerAdminLoggerI _logger;
+ private Ice.Communicator _sendLogCommunicator = null;
+ private boolean _destroyed = false;
+ static private final String _traceCategory = "Admin.Logger";
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminLogger.java b/java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminLogger.java
new file mode 100644
index 00000000000..1ae9f52faf1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminLogger.java
@@ -0,0 +1,16 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+interface LoggerAdminLogger extends Ice.Logger
+{
+ Ice.Object getFacet();
+ void destroy();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminLoggerI.java b/java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminLoggerI.java
new file mode 100644
index 00000000000..b5743d72873
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/LoggerAdminLoggerI.java
@@ -0,0 +1,254 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class LoggerAdminLoggerI implements LoggerAdminLogger, Runnable
+{
+ @Override
+ public void print(String message)
+ {
+ Ice.LogMessage logMessage = new Ice.LogMessage(Ice.LogMessageType.PrintMessage, now(), "", message);
+ _localLogger.print(message);
+ log(logMessage);
+ }
+
+ @Override
+ public void trace(String category, String message)
+ {
+ Ice.LogMessage logMessage = new Ice.LogMessage(Ice.LogMessageType.TraceMessage, now(), category, message);
+ _localLogger.trace(category, message);
+ log(logMessage);
+ }
+
+ @Override
+ public void warning(String message)
+ {
+ Ice.LogMessage logMessage = new Ice.LogMessage(Ice.LogMessageType.WarningMessage, now(), "", message);
+ _localLogger.warning(message);
+ log(logMessage);
+ }
+
+ @Override
+ public void error(String message)
+ {
+ Ice.LogMessage logMessage = new Ice.LogMessage(Ice.LogMessageType.ErrorMessage, now(), "", message);
+ _localLogger.error(message);
+ log(logMessage);
+ }
+
+ @Override
+ public String getPrefix()
+ {
+ return _localLogger.getPrefix();
+ }
+
+ @Override
+ public Ice.Logger cloneWithPrefix(String prefix)
+ {
+ return _localLogger.cloneWithPrefix(prefix);
+ }
+
+ @Override
+ public Ice.Object getFacet()
+ {
+ return _loggerAdmin;
+ }
+
+ @Override
+ public void destroy()
+ {
+ Thread thread = null;
+ synchronized(this)
+ {
+ if(_sendLogThread != null)
+ {
+ thread = _sendLogThread;
+ _sendLogThread = null;
+ _destroyed = true;
+ notifyAll();
+ }
+ }
+
+ if(thread != null)
+ {
+ try
+ {
+ thread.join();
+ }
+ catch(InterruptedException e)
+ {
+ synchronized(this)
+ {
+ _sendLogThread = thread;
+ }
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+
+ _loggerAdmin.destroy();
+ }
+
+ @Override
+ public void run()
+ {
+ if(_loggerAdmin.getTraceLevel() > 1)
+ {
+ _localLogger.trace(_traceCategory, "send log thread started");
+ }
+
+ final Ice.Callback logCompletedCb = new Ice.Callback()
+ {
+
+ @Override
+ public void completed(Ice.AsyncResult r)
+ {
+ Ice.RemoteLoggerPrx remoteLogger = Ice.RemoteLoggerPrxHelper.uncheckedCast(r.getProxy());
+
+ try
+ {
+ remoteLogger.end_log(r);
+
+ if(_loggerAdmin.getTraceLevel() > 1)
+ {
+ _localLogger.trace(_traceCategory, r.getOperation() + " on `" + remoteLogger.toString() +
+ "' completed successfully");
+ }
+ }
+ catch(Ice.CommunicatorDestroyedException ex)
+ {
+ // expected if there are outstanding calls during
+ // communicator destruction
+ }
+ catch(Ice.LocalException ex)
+ {
+ _loggerAdmin.deadRemoteLogger(remoteLogger, _localLogger, ex, r.getOperation());
+ }
+ }
+ };
+
+ for(;;)
+ {
+ Job job = null;
+ synchronized(this)
+ {
+ while(!_destroyed && _jobQueue.isEmpty())
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException e)
+ {
+ // Ignored, this should never occur
+ }
+ }
+
+ if(_destroyed)
+ {
+ break; // for(;;)
+ }
+
+ assert(!_jobQueue.isEmpty());
+ job = _jobQueue.removeFirst();
+ }
+
+ for(Ice.RemoteLoggerPrx p : job.remoteLoggers)
+ {
+ if(_loggerAdmin.getTraceLevel() > 1)
+ {
+ _localLogger.trace(_traceCategory, "sending log message to `" + p.toString() + "'");
+ }
+
+ try
+ {
+ //
+ // p is a proxy associated with the _sendLogCommunicator
+ //
+ p.begin_log(job.logMessage, logCompletedCb);
+ }
+ catch(Ice.LocalException ex)
+ {
+ _loggerAdmin.deadRemoteLogger(p, _localLogger, ex, "log");
+ }
+ }
+ }
+
+ if(_loggerAdmin.getTraceLevel() > 1)
+ {
+ _localLogger.trace(_traceCategory, "send log thread completed");
+ }
+ }
+
+ LoggerAdminLoggerI(Ice.Properties props, Ice.Logger localLogger)
+ {
+ if(localLogger instanceof LoggerAdminLoggerI)
+ {
+ _localLogger = ((LoggerAdminLoggerI)localLogger).getLocalLogger();
+ }
+ else
+ {
+ _localLogger = localLogger;
+ }
+
+ _loggerAdmin = new LoggerAdminI(props, this);
+ }
+
+ Ice.Logger getLocalLogger()
+ {
+ return _localLogger;
+ }
+
+ void log(Ice.LogMessage logMessage)
+ {
+ java.util.List<Ice.RemoteLoggerPrx> remoteLoggers = _loggerAdmin.log(logMessage);
+
+ if(remoteLoggers != null)
+ {
+ assert(!remoteLoggers.isEmpty());
+
+ synchronized(this)
+ {
+ if(_sendLogThread == null)
+ {
+ _sendLogThread = new Thread(this, "Ice.SendLogThread");
+ _sendLogThread.start();
+ }
+
+ _jobQueue.addLast(new Job(remoteLoggers, logMessage));
+ notifyAll();
+ }
+ }
+ }
+
+ static private long now()
+ {
+ return java.util.Calendar.getInstance().getTimeInMillis() * 1000;
+ }
+
+ private static class Job
+ {
+ Job(java.util.List<Ice.RemoteLoggerPrx> r, Ice.LogMessage l)
+ {
+ remoteLoggers = r;
+ logMessage = l;
+ }
+
+ final java.util.List<Ice.RemoteLoggerPrx> remoteLoggers;
+ final Ice.LogMessage logMessage;
+ }
+
+ private final Ice.Logger _localLogger;
+ private final LoggerAdminI _loggerAdmin;
+ private boolean _destroyed = false;
+ private Thread _sendLogThread;
+ private final java.util.Deque<Job> _jobQueue = new java.util.ArrayDeque<Job>();
+
+ static private final String _traceCategory = "Admin.Logger";
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/MetricsAdminI.java b/java-compat/src/Ice/src/main/java/IceInternal/MetricsAdminI.java
new file mode 100644
index 00000000000..92b0cb139a6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/MetricsAdminI.java
@@ -0,0 +1,400 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class MetricsAdminI extends IceMX._MetricsAdminDisp implements Ice.PropertiesAdminUpdateCallback
+{
+ final static private String[] suffixes =
+ {
+ "Disabled",
+ "GroupBy",
+ "Accept.*",
+ "Reject.*",
+ "RetainDetached",
+ "Map.*",
+ };
+
+ static void
+ validateProperties(String prefix, Ice.Properties properties)
+ {
+ java.util.Map<String, String> props = properties.getPropertiesForPrefix(prefix);
+ java.util.List<String> unknownProps = new java.util.ArrayList<String>();
+ for(String prop : props.keySet())
+ {
+ boolean valid = false;
+ for(String suffix : suffixes)
+ {
+ if(IceUtilInternal.StringUtil.match(prop, prefix + suffix, false))
+ {
+ valid = true;
+ break;
+ }
+ }
+
+ if(!valid)
+ {
+ unknownProps.add(prop);
+ }
+ }
+
+ if(unknownProps.size() != 0 && properties.getPropertyAsIntWithDefault("Ice.Warn.UnknownProperties", 1) > 0)
+ {
+ StringBuffer message = new StringBuffer("found unknown IceMX properties for `");
+ message.append(prefix.substring(0, prefix.length() - 1));
+ message.append("':");
+ for(String p : unknownProps)
+ {
+ message.append("\n ");
+ message.append(p);
+ }
+ Ice.Util.getProcessLogger().warning(message.toString());
+ }
+ }
+
+ static class MetricsMapFactory<T extends IceMX.Metrics>
+ {
+ public MetricsMapFactory(Runnable updater, Class<T> cl)
+ {
+ _updater = updater;
+ _class = cl;
+ }
+
+ public void
+ update()
+ {
+ assert(_updater != null);
+ _updater.run();
+ }
+
+ public MetricsMap<T>
+ create(String mapPrefix, Ice.Properties properties)
+ {
+ return new MetricsMap<T>(mapPrefix, _class, properties, _subMaps);
+ }
+
+ public <S extends IceMX.Metrics> void
+ registerSubMap(String subMap, Class<S> cl, java.lang.reflect.Field field)
+ {
+ _subMaps.put(subMap, new MetricsMap.SubMapFactory<S>(cl, field));
+ }
+
+ final private Runnable _updater;
+ final private Class<T> _class;
+ final private java.util.Map<String, MetricsMap.SubMapFactory<?>> _subMaps =
+ new java.util.HashMap<String, MetricsMap.SubMapFactory<?>>();
+ }
+
+ public MetricsAdminI(Ice.Properties properties, Ice.Logger logger)
+ {
+ _logger = logger;
+ _properties = properties;
+ updateViews();
+ }
+
+ public void updateViews()
+ {
+ java.util.Set<MetricsMapFactory<?> > updatedMaps = new java.util.HashSet<MetricsMapFactory<?> >();
+ synchronized(this)
+ {
+ String viewsPrefix = "IceMX.Metrics.";
+ java.util.Map<String, String> viewsProps = _properties.getPropertiesForPrefix(viewsPrefix);
+ java.util.Map<String, MetricsViewI> views = new java.util.HashMap<String, MetricsViewI>();
+ _disabledViews.clear();
+ for(java.util.Map.Entry<String, String> e : viewsProps.entrySet())
+ {
+ String viewName = e.getKey().substring(viewsPrefix.length());
+ int dotPos = viewName.indexOf('.');
+ if(dotPos > 0)
+ {
+ viewName = viewName.substring(0, dotPos);
+ }
+
+ if(views.containsKey(viewName) || _disabledViews.contains(viewName))
+ {
+ continue; // View already configured.
+ }
+
+ validateProperties(viewsPrefix + viewName + ".", _properties);
+
+ if(_properties.getPropertyAsIntWithDefault(viewsPrefix + viewName + ".Disabled", 0) > 0)
+ {
+ _disabledViews.add(viewName);
+ continue; // The view is disabled
+ }
+
+ //
+ // Create the view or update it.
+ //
+ MetricsViewI v = _views.get(viewName);
+ if(v == null)
+ {
+ v = new MetricsViewI(viewName);
+ }
+ views.put(viewName, v);
+
+ for(java.util.Map.Entry<String, MetricsMapFactory<?>> f : _factories.entrySet())
+ {
+ if(v.addOrUpdateMap(_properties, f.getKey(), f.getValue(), _logger))
+ {
+ updatedMaps.add(f.getValue());
+ }
+ }
+ }
+ java.util.Map<String, MetricsViewI> tmp = _views;
+ _views = views;
+ views = tmp;
+
+ //
+ // Go through removed views to collect maps to update.
+ //
+ for(java.util.Map.Entry<String, MetricsViewI> v : views.entrySet())
+ {
+ if(!_views.containsKey(v.getKey()))
+ {
+ for(String n : v.getValue().getMaps())
+ {
+ updatedMaps.add(_factories.get(n));
+ }
+ }
+ }
+ }
+
+ //
+ // Call the updaters to update the maps.
+ //
+ for(MetricsMapFactory<?> f : updatedMaps)
+ {
+ f.update();
+ }
+ }
+
+ @Override
+ synchronized public String[]
+ getMetricsViewNames(Ice.StringSeqHolder holder, Ice.Current current)
+ {
+ holder.value = _disabledViews.toArray(new String[_disabledViews.size()]);
+ return _views.keySet().toArray(new String[_views.size()]);
+ }
+
+ @Override
+ public void
+ enableMetricsView(String name, Ice.Current current)
+ throws IceMX.UnknownMetricsView
+ {
+ synchronized(this)
+ {
+ getMetricsView(name); // Throws if unknown view.
+ _properties.setProperty("IceMX.Metrics." + name + ".Disabled", "0");
+ }
+ updateViews();
+ }
+
+ @Override
+ public void
+ disableMetricsView(String name, Ice.Current current)
+ throws IceMX.UnknownMetricsView
+ {
+ synchronized(this)
+ {
+ getMetricsView(name); // Throws if unknown view.
+ _properties.setProperty("IceMX.Metrics." + name + ".Disabled", "1");
+ }
+ updateViews();
+ }
+
+ @Override
+ synchronized public java.util.Map<String, IceMX.Metrics[]>
+ getMetricsView(String viewName, Ice.LongHolder holder, Ice.Current current)
+ throws IceMX.UnknownMetricsView
+ {
+ MetricsViewI view = getMetricsView(viewName);
+ holder.value = IceInternal.Time.currentMonotonicTimeMillis();
+ if(view != null)
+ {
+ return view.getMetrics();
+ }
+ return new java.util.HashMap<String, IceMX.Metrics[]>();
+ }
+
+ @Override
+ synchronized public IceMX.MetricsFailures[]
+ getMapMetricsFailures(String viewName, String mapName, Ice.Current current)
+ throws IceMX.UnknownMetricsView
+ {
+ MetricsViewI view = getMetricsView(viewName);
+ if(view != null)
+ {
+ return view.getFailures(mapName);
+ }
+ return new IceMX.MetricsFailures[0];
+ }
+
+ @Override
+ synchronized public IceMX.MetricsFailures
+ getMetricsFailures(String viewName, String mapName, String id, Ice.Current current)
+ throws IceMX.UnknownMetricsView
+ {
+ MetricsViewI view = getMetricsView(viewName);
+ if(view != null)
+ {
+ return view.getFailures(mapName, id);
+ }
+ return new IceMX.MetricsFailures();
+ }
+
+ public <T extends IceMX.Metrics> void
+ registerMap(String map, Class<T> cl, Runnable updater)
+ {
+ boolean updated;
+ MetricsMapFactory<T> factory;
+ synchronized(this)
+ {
+ factory = new MetricsMapFactory<T>(updater, cl);
+ _factories.put(map, factory);
+ updated = addOrUpdateMap(map, factory);
+ }
+ if(updated)
+ {
+ factory.update();
+ }
+ }
+
+ synchronized public <S extends IceMX.Metrics> void
+ registerSubMap(String map, String subMap, Class<S> cl, java.lang.reflect.Field field)
+ {
+ boolean updated;
+ MetricsMapFactory<?> factory;
+ synchronized(this)
+ {
+ factory = _factories.get(map);
+ if(factory == null)
+ {
+ return;
+ }
+ factory.registerSubMap(subMap, cl, field);
+ removeMap(map);
+ updated = addOrUpdateMap(map, factory);
+ }
+ if(updated)
+ {
+ factory.update();
+ }
+ }
+
+ public void
+ unregisterMap(String mapName)
+ {
+ boolean updated;
+ MetricsMapFactory<?> factory;
+ synchronized(this)
+ {
+ factory = _factories.remove(mapName);
+ if(factory == null)
+ {
+ return;
+ }
+ updated = removeMap(mapName);
+ }
+ if(updated)
+ {
+ factory.update();
+ }
+ }
+
+ public <T extends IceMX.Metrics> java.util.List<MetricsMap<T>>
+ getMaps(String mapName, Class<T> cl)
+ {
+ java.util.List<MetricsMap<T>> maps = new java.util.ArrayList<MetricsMap<T>>();
+ for(MetricsViewI v : _views.values())
+ {
+ MetricsMap<T> map = v.getMap(mapName, cl);
+ if(map != null)
+ {
+ maps.add(map);
+ }
+ }
+ return maps;
+ }
+
+ public Ice.Logger
+ getLogger()
+ {
+ return _logger;
+ }
+
+ @Override
+ public void
+ updated(java.util.Map<String, String> props)
+ {
+ for(java.util.Map.Entry<String, String> e : props.entrySet())
+ {
+ if(e.getKey().indexOf("IceMX.") == 0)
+ {
+ // Udpate the metrics views using the new configuration.
+ try
+ {
+ updateViews();
+ }
+ catch(Exception ex)
+ {
+ _logger.warning("unexpected exception while updating metrics view configuration:\n" +
+ ex.toString());
+ }
+ return;
+ }
+ }
+ }
+
+ private MetricsViewI
+ getMetricsView(String name)
+ throws IceMX.UnknownMetricsView
+ {
+ MetricsViewI view = _views.get(name);
+ if(view == null)
+ {
+ if(!_disabledViews.contains(name))
+ {
+ throw new IceMX.UnknownMetricsView();
+ }
+ return null;
+ }
+ return view;
+ }
+
+ private boolean
+ addOrUpdateMap(String mapName, MetricsMapFactory<?> factory)
+ {
+ boolean updated = false;
+ for(MetricsViewI v : _views.values())
+ {
+ updated |= v.addOrUpdateMap(_properties, mapName, factory, _logger);
+ }
+ return updated;
+ }
+
+ private boolean
+ removeMap(String mapName)
+ {
+ boolean updated = false;
+ for(MetricsViewI v : _views.values())
+ {
+ updated |= v.removeMap(mapName);
+ }
+ return updated;
+ }
+
+ private Ice.Properties _properties;
+ final private Ice.Logger _logger;
+ final private java.util.Map<String, MetricsMapFactory<?>> _factories =
+ new java.util.HashMap<String, MetricsMapFactory<?>>();
+
+ private java.util.Map<String, MetricsViewI> _views = new java.util.HashMap<String, MetricsViewI>();
+ private java.util.Set<String> _disabledViews = new java.util.HashSet<String>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/MetricsMap.java b/java-compat/src/Ice/src/main/java/IceInternal/MetricsMap.java
new file mode 100644
index 00000000000..b4d6dfb10c2
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/MetricsMap.java
@@ -0,0 +1,517 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class MetricsMap<T extends IceMX.Metrics>
+{
+ public class Entry
+ {
+ Entry(T obj)
+ {
+ _object = obj;
+ }
+
+ public void
+ failed(String exceptionName)
+ {
+ synchronized(MetricsMap.this)
+ {
+ ++_object.failures;
+ if(_failures == null)
+ {
+ _failures = new java.util.HashMap<String, Integer>();
+ }
+ Integer count = _failures.get(exceptionName);
+ _failures.put(exceptionName, new Integer(count == null ? 1 : count + 1));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <S extends IceMX.Metrics> MetricsMap<S>.Entry
+ getMatching(String mapName, IceMX.MetricsHelper<S> helper, Class<S> cl)
+ {
+ SubMap<S> m;
+ synchronized(MetricsMap.this)
+ {
+ m = _subMaps != null ? (SubMap<S>)_subMaps.get(mapName) : null;
+ if(m == null)
+ {
+ m = createSubMap(mapName, cl);
+ if(m == null)
+ {
+ return null;
+ }
+ if(_subMaps == null)
+ {
+ _subMaps = new java.util.HashMap<String, SubMap<?>>();
+ }
+ _subMaps.put(mapName, m);
+ }
+ }
+ return m.getMatching(helper);
+ }
+
+ public void
+ detach(long lifetime)
+ {
+ synchronized(MetricsMap.this)
+ {
+ _object.totalLifetime += lifetime;
+ if(--_object.current == 0)
+ {
+ detached(this);
+ }
+ }
+ }
+
+ public void
+ execute(IceMX.Observer.MetricsUpdate<T> func)
+ {
+ synchronized(MetricsMap.this)
+ {
+ func.update(_object);
+ }
+ }
+
+ public MetricsMap<?>
+ getMap()
+ {
+ return MetricsMap.this;
+ }
+
+ private IceMX.MetricsFailures
+ getFailures()
+ {
+ if(_failures == null)
+ {
+ return null;
+ }
+ IceMX.MetricsFailures f = new IceMX.MetricsFailures();
+ f.id = _object.id;
+ f.failures = new java.util.HashMap<String, Integer>(_failures);
+ return f;
+ }
+
+ private void
+ attach(IceMX.MetricsHelper<T> helper)
+ {
+ ++_object.total;
+ ++_object.current;
+ helper.initMetrics(_object);
+ }
+
+ private boolean
+ isDetached()
+ {
+ return _object.current == 0;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public IceMX.Metrics
+ clone()
+ {
+ T metrics = (T)_object.clone();
+ if(_subMaps != null)
+ {
+ for(SubMap<?> s : _subMaps.values())
+ {
+ s.addSubMapToMetrics(metrics);
+ }
+ }
+ return metrics;
+ }
+
+ private T _object;
+ private java.util.Map<String, Integer> _failures;
+ private java.util.Map<String, SubMap<?>> _subMaps;
+ }
+
+ static class SubMap<S extends IceMX.Metrics>
+ {
+ public
+ SubMap(MetricsMap<S> map, java.lang.reflect.Field field)
+ {
+ _map = map;
+ _field = field;
+ }
+
+ public MetricsMap<S>.Entry
+ getMatching(IceMX.MetricsHelper<S> helper)
+ {
+ return _map.getMatching(helper, null);
+ }
+
+ public void
+ addSubMapToMetrics(IceMX.Metrics metrics)
+ {
+ try
+ {
+ _field.set(metrics, _map.getMetrics());
+ }
+ catch(Exception ex)
+ {
+ assert(false);
+ }
+ }
+
+ final private MetricsMap<S> _map;
+ final private java.lang.reflect.Field _field;
+ }
+
+ static class SubMapCloneFactory<S extends IceMX.Metrics>
+ {
+ public SubMapCloneFactory(MetricsMap<S> map, java.lang.reflect.Field field)
+ {
+ _map = map;
+ _field = field;
+ }
+
+ public SubMap<S>
+ create()
+ {
+ return new SubMap<S>(new MetricsMap<S>(_map), _field);
+ }
+
+ final private MetricsMap<S> _map;
+ final private java.lang.reflect.Field _field;
+ }
+
+ static class SubMapFactory<S extends IceMX.Metrics>
+ {
+ SubMapFactory(Class<S> cl, java.lang.reflect.Field field)
+ {
+ _class = cl;
+ _field = field;
+ }
+
+ SubMapCloneFactory<S>
+ createCloneFactory(String subMapPrefix, Ice.Properties properties)
+ {
+ return new SubMapCloneFactory<S>(new MetricsMap<S>(subMapPrefix, _class, properties, null), _field);
+ }
+
+ final private Class<S> _class;
+ final private java.lang.reflect.Field _field;
+ }
+
+ MetricsMap(String mapPrefix, Class<T> cl, Ice.Properties props, java.util.Map<String, SubMapFactory<?>> subMaps)
+ {
+ MetricsAdminI.validateProperties(mapPrefix, props);
+ _properties = props.getPropertiesForPrefix(mapPrefix);
+
+ _retain = props.getPropertyAsIntWithDefault(mapPrefix + "RetainDetached", 10);
+ _accept = parseRule(props, mapPrefix + "Accept");
+ _reject = parseRule(props, mapPrefix + "Reject");
+ _groupByAttributes = new java.util.ArrayList<String>();
+ _groupBySeparators = new java.util.ArrayList<String>();
+ _class = cl;
+
+ String groupBy = props.getPropertyWithDefault(mapPrefix + "GroupBy", "id");
+ if(!groupBy.isEmpty())
+ {
+ String v = "";
+ boolean attribute = Character.isLetter(groupBy.charAt(0)) || Character.isDigit(groupBy.charAt(0));
+ if(!attribute)
+ {
+ _groupByAttributes.add("");
+ }
+
+ for(char p : groupBy.toCharArray())
+ {
+ boolean isAlphaNum = Character.isLetter(p) || Character.isDigit(p) || p == '.';
+ if(attribute && !isAlphaNum)
+ {
+ _groupByAttributes.add(v);
+ v = "" + p;
+ attribute = false;
+ }
+ else if(!attribute && isAlphaNum)
+ {
+ _groupBySeparators.add(v);
+ v = "" + p;
+ attribute = true;
+ }
+ else
+ {
+ v += p;
+ }
+ }
+
+ if(attribute)
+ {
+ _groupByAttributes.add(v);
+ }
+ else
+ {
+ _groupBySeparators.add(v);
+ }
+ }
+
+ if(subMaps != null && !subMaps.isEmpty())
+ {
+ _subMaps = new java.util.HashMap<String, SubMapCloneFactory<?>>();
+
+ java.util.List<String> subMapNames = new java.util.ArrayList<String>();
+ for(java.util.Map.Entry<String, SubMapFactory<?>> e : subMaps.entrySet())
+ {
+ subMapNames.add(e.getKey());
+ String subMapsPrefix = mapPrefix + "Map.";
+ String subMapPrefix = subMapsPrefix + e.getKey() + '.';
+ if(props.getPropertiesForPrefix(subMapPrefix).isEmpty())
+ {
+ if(props.getPropertiesForPrefix(subMapsPrefix).isEmpty())
+ {
+ subMapPrefix = mapPrefix;
+ }
+ else
+ {
+ continue; // This sub-map isn't configured.
+ }
+ }
+
+ _subMaps.put(e.getKey(), e.getValue().createCloneFactory(subMapPrefix, props));
+ }
+ }
+ else
+ {
+ _subMaps = null;
+ }
+ }
+
+ MetricsMap(MetricsMap<T> map)
+ {
+ _properties = map._properties;
+ _groupByAttributes = map._groupByAttributes;
+ _groupBySeparators = map._groupBySeparators;
+ _retain = map._retain;
+ _accept = map._accept;
+ _reject = map._reject;
+ _class = map._class;
+ _subMaps = map._subMaps;
+ }
+
+ java.util.Map<String, String>
+ getProperties()
+ {
+ return _properties;
+ }
+
+ synchronized IceMX.Metrics[]
+ getMetrics()
+ {
+ IceMX.Metrics[] metrics = new IceMX.Metrics[_objects.size()];
+ int i = 0;
+ for(Entry e : _objects.values())
+ {
+ metrics[i++] = e.clone();
+ }
+ return metrics;
+ }
+
+ synchronized IceMX.MetricsFailures[]
+ getFailures()
+ {
+ java.util.List<IceMX.MetricsFailures> failures = new java.util.ArrayList<IceMX.MetricsFailures>();
+ for(Entry e : _objects.values())
+ {
+ IceMX.MetricsFailures f = e.getFailures();
+ if(f != null)
+ {
+ failures.add(f);
+ }
+ }
+ return failures.toArray(new IceMX.MetricsFailures[failures.size()]);
+ }
+
+ synchronized IceMX.MetricsFailures
+ getFailures(String id)
+ {
+ Entry e = _objects.get(id);
+ if(e != null)
+ {
+ return e.getFailures();
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <S extends IceMX.Metrics> SubMap<S>
+ createSubMap(String subMapName, Class<S> cl)
+ {
+ if(_subMaps == null)
+ {
+ return null;
+ }
+ SubMapCloneFactory<S> factory = (SubMapCloneFactory<S>)_subMaps.get(subMapName);
+ if(factory != null)
+ {
+ return factory.create();
+ }
+ return null;
+ }
+
+ public Entry
+ getMatching(IceMX.MetricsHelper<T> helper, Entry previous)
+ {
+ //
+ // Check the accept and reject filters.
+ //
+ for(java.util.Map.Entry<String, java.util.regex.Pattern> e : _accept.entrySet())
+ {
+ if(!match(e.getKey(), e.getValue(), helper, false))
+ {
+ return null;
+ }
+ }
+
+ for(java.util.Map.Entry<String, java.util.regex.Pattern> e : _reject.entrySet())
+ {
+ if(match(e.getKey(), e.getValue(), helper, true))
+ {
+ return null;
+ }
+ }
+
+ //
+ // Compute the key from the GroupBy property.
+ //
+ String key;
+ try
+ {
+ if(_groupByAttributes.size() == 1)
+ {
+ key = helper.resolve(_groupByAttributes.get(0));
+ }
+ else
+ {
+ StringBuilder os = new StringBuilder();
+ java.util.Iterator<String> q = _groupBySeparators.iterator();
+ for(String p : _groupByAttributes)
+ {
+ os.append(helper.resolve(p));
+ if(q.hasNext())
+ {
+ os.append(q.next());
+ }
+ }
+ key = os.toString();
+ }
+ }
+ catch(Exception ex)
+ {
+ return null;
+ }
+
+ //
+ // Lookup the metrics object.
+ //
+ synchronized(this)
+ {
+ if(previous != null && previous._object.id.equals(key))
+ {
+ assert(_objects.get(key) == previous);
+ return previous;
+ }
+
+ Entry e = _objects.get(key);
+ if(e == null)
+ {
+ try
+ {
+ T t = _class.newInstance();
+ t.id = key;
+ e = new Entry(t);
+ _objects.put(key, e);
+ }
+ catch(Exception ex)
+ {
+ assert(false);
+ }
+ }
+ e.attach(helper);
+ return e;
+ }
+ }
+
+ private void
+ detached(Entry entry)
+ {
+ if(_retain == 0)
+ {
+ return;
+ }
+
+ if(_detachedQueue == null)
+ {
+ _detachedQueue = new java.util.LinkedList<Entry>();
+ }
+ assert(_detachedQueue.size() <= _retain);
+
+ // Compress the queue by removing entries which are no longer detached.
+ java.util.Iterator<Entry> p = _detachedQueue.iterator();
+ while(p.hasNext())
+ {
+ Entry e = p.next();
+ if(e == entry || !e.isDetached())
+ {
+ p.remove();
+ }
+ }
+
+ // If there's still no room, remove the oldest entry (at the front).
+ if(_detachedQueue.size() == _retain)
+ {
+ _objects.remove(_detachedQueue.pollFirst()._object.id);
+ }
+
+ // Add the entry at the back of the queue.
+ _detachedQueue.add(entry);
+ }
+
+ private java.util.Map<String, java.util.regex.Pattern>
+ parseRule(Ice.Properties properties, String name)
+ {
+ java.util.Map<String, java.util.regex.Pattern> pats = new java.util.HashMap<String, java.util.regex.Pattern>();
+ java.util.Map<String, String> rules = properties.getPropertiesForPrefix(name + '.');
+ for(java.util.Map.Entry<String,String> e : rules.entrySet())
+ {
+ pats.put(e.getKey().substring(name.length() + 1), java.util.regex.Pattern.compile(e.getValue()));
+ }
+ return pats;
+ }
+
+ private boolean
+ match(String attribute, java.util.regex.Pattern regex, IceMX.MetricsHelper<T> helper, boolean reject)
+ {
+ String value;
+ try
+ {
+ value = helper.resolve(attribute);
+ }
+ catch(Exception ex)
+ {
+ return !reject;
+ }
+ return regex.matcher(value).matches();
+ }
+
+ final private java.util.Map<String, String> _properties;
+ final private java.util.List<String> _groupByAttributes;
+ final private java.util.List<String> _groupBySeparators;
+ final private int _retain;
+ final private java.util.Map<String, java.util.regex.Pattern> _accept;
+ final private java.util.Map<String, java.util.regex.Pattern> _reject;
+ final private Class<T> _class;
+
+ final private java.util.Map<String, Entry> _objects = new java.util.HashMap<String, Entry>();
+ final private java.util.Map<String, SubMapCloneFactory<?>> _subMaps;
+ private java.util.Deque<Entry> _detachedQueue;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/MetricsViewI.java b/java-compat/src/Ice/src/main/java/IceInternal/MetricsViewI.java
new file mode 100644
index 00000000000..c45aedff457
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/MetricsViewI.java
@@ -0,0 +1,126 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class MetricsViewI
+{
+ MetricsViewI(String name)
+ {
+ _name = name;
+ }
+
+ public boolean
+ addOrUpdateMap(Ice.Properties properties, String mapName, MetricsAdminI.MetricsMapFactory<?> factory,
+ Ice.Logger logger)
+ {
+ //
+ // Add maps to views configured with the given map.
+ //
+ String viewPrefix = "IceMX.Metrics." + _name + ".";
+ String mapsPrefix = viewPrefix + "Map.";
+ java.util.Map<String, String> mapsProps = properties.getPropertiesForPrefix(mapsPrefix);
+
+ String mapPrefix;
+ java.util.Map<String, String> mapProps = new java.util.HashMap<String, String>();
+ if(!mapsProps.isEmpty())
+ {
+ mapPrefix = mapsPrefix + mapName + ".";
+ mapProps = properties.getPropertiesForPrefix(mapPrefix);
+ if(mapProps.isEmpty())
+ {
+ // This map isn't configured for this view.
+ return _maps.remove(mapName) != null;
+ }
+ }
+ else
+ {
+ mapPrefix = viewPrefix;
+ mapProps = properties.getPropertiesForPrefix(mapPrefix);
+ }
+
+ if(properties.getPropertyAsInt(mapPrefix + "Disabled") > 0)
+ {
+ // This map is disabled for this view.
+ return _maps.remove(mapName) != null;
+ }
+
+ MetricsMap<?> m = _maps.get(mapName);
+ if(m != null && m.getProperties().equals(mapProps))
+ {
+ return false; // The map configuration didn't change, no need to re-create.
+ }
+
+ try
+ {
+ _maps.put(mapName, factory.create(mapPrefix, properties));
+ }
+ catch(Exception ex)
+ {
+ logger.warning("unexpected exception while creating metrics map:\n" + ex);
+ _maps.remove(mapName);
+ }
+ return true;
+ }
+
+ public boolean
+ removeMap(String mapName)
+ {
+ return _maps.remove(mapName) != null;
+ }
+
+ public java.util.Map<String, IceMX.Metrics[]>
+ getMetrics()
+ {
+ java.util.Map<String, IceMX.Metrics[]> metrics = new java.util.HashMap<String, IceMX.Metrics[]>();
+ for(java.util.Map.Entry<String, MetricsMap<?>> e : _maps.entrySet())
+ {
+ metrics.put(e.getKey(), e.getValue().getMetrics());
+ }
+ return metrics;
+ }
+
+ public IceMX.MetricsFailures[]
+ getFailures(String mapName)
+ {
+ MetricsMap<?> m = _maps.get(mapName);
+ if(m != null)
+ {
+ return m.getFailures();
+ }
+ return null;
+ }
+
+ public IceMX.MetricsFailures
+ getFailures(String mapName, String id)
+ {
+ MetricsMap<?> m = _maps.get(mapName);
+ if(m != null)
+ {
+ return m.getFailures(id);
+ }
+ return null;
+ }
+
+ public java.util.Collection<String>
+ getMaps()
+ {
+ return _maps.keySet();
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends IceMX.Metrics> MetricsMap<T>
+ getMap(String mapName, Class<T> cl)
+ {
+ return (MetricsMap<T>)_maps.get(mapName);
+ }
+
+ final private String _name;
+ final private java.util.Map<String, MetricsMap<?>> _maps = new java.util.HashMap<String, MetricsMap<?>>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Network.java b/java-compat/src/Ice/src/main/java/IceInternal/Network.java
new file mode 100644
index 00000000000..0e19cf0e0b0
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Network.java
@@ -0,0 +1,1353 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class Network
+{
+ // ProtocolSupport
+ public final static int EnableIPv4 = 0;
+ public final static int EnableIPv6 = 1;
+ public final static int EnableBoth = 2;
+
+ private static java.util.regex.Pattern IPV4_PATTERN = null;
+ private static java.util.regex.Pattern IPV6_PATTERN = null;
+ private final static String ipv4Pattern =
+ "(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])";
+ private final static String ipv6Pattern =
+ "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-" +
+ "fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1" +
+ ",4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1," +
+ "4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-" +
+ "F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])" +
+ "\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}" +
+ "[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))";
+
+ static
+ {
+ try
+ {
+ IPV4_PATTERN =
+ java.util.regex.Pattern.compile(ipv4Pattern, java.util.regex.Pattern.CASE_INSENSITIVE);
+ IPV6_PATTERN =
+ java.util.regex.Pattern.compile(ipv6Pattern, java.util.regex.Pattern.CASE_INSENSITIVE);
+ }
+ catch (java.util.regex.PatternSyntaxException ex)
+ {
+ assert(false);
+ }
+ }
+
+ public static boolean
+ isNumericAddress(String ipAddress)
+ {
+ java.util.regex.Matcher ipv4 = IPV4_PATTERN.matcher(ipAddress);
+ if(ipv4.matches())
+ {
+ return true;
+ }
+ java.util.regex.Matcher ipv6 = IPV6_PATTERN.matcher(ipAddress);
+ return ipv6.matches();
+ }
+
+ public static boolean
+ connectionRefused(java.net.ConnectException ex)
+ {
+ //
+ // The JDK raises a generic ConnectException when the server
+ // actively refuses a connection. Unfortunately, our only
+ // choice is to search the exception message for
+ // distinguishing phrases.
+ //
+
+ String msg = ex.getMessage();
+
+ if(msg != null)
+ {
+ msg = msg.toLowerCase();
+
+ final String[] msgs =
+ {
+ "connection refused", // ECONNREFUSED
+ "remote host refused an attempted connect operation" // ECONNREFUSED (AIX JDK 1.4.2)
+ };
+
+ for(String m : msgs)
+ {
+ if(msg.indexOf(m) != -1)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static boolean
+ noMoreFds(java.lang.Throwable ex)
+ {
+ String msg = ex.getMessage();
+ if(msg != null)
+ {
+ msg = msg.toLowerCase();
+
+ final String[] msgs =
+ {
+ "too many open files", // EMFILE
+ "file table overflow", // ENFILE
+ "too many open files in system" // ENFILE
+ };
+
+ for(String m : msgs)
+ {
+ if(msg.indexOf(m) != -1)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static boolean
+ isIPv6Supported()
+ {
+ try
+ {
+ java.net.Socket socket = new java.net.Socket();
+ socket.bind(new java.net.InetSocketAddress(java.net.InetAddress.getByName("::1"), 0));
+ socket.close();
+ return true;
+ }
+ catch(java.io.IOException ex)
+ {
+ return false;
+ }
+ }
+
+ public static java.nio.channels.SocketChannel
+ createTcpSocket()
+ {
+ try
+ {
+ java.nio.channels.SocketChannel fd = java.nio.channels.SocketChannel.open();
+ java.net.Socket socket = fd.socket();
+ socket.setTcpNoDelay(true);
+ socket.setKeepAlive(true);
+ return fd;
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static java.nio.channels.ServerSocketChannel
+ createTcpServerSocket()
+ {
+ try
+ {
+ java.nio.channels.ServerSocketChannel fd = java.nio.channels.ServerSocketChannel.open();
+ //
+ // It's not possible to set TCP_NODELAY or KEEP_ALIVE
+ // on a server socket in Java
+ //
+ //java.net.Socket socket = fd.socket();
+ //socket.setTcpNoDelay(true);
+ //socket.setKeepAlive(true);
+ return fd;
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static java.nio.channels.DatagramChannel
+ createUdpSocket(java.net.InetSocketAddress addr)
+ {
+ try
+ {
+ //
+ // Use reflection so this code still compiles with older JDK versions.
+ // java.net.StandardProtocolFamily is new in JDK 1.7
+ //
+ Class<?> c = Util.findClass("java.net.StandardProtocolFamily", null);
+ if(addr.getAddress().isMulticastAddress() && c != null)
+ {
+ //
+ // For multicast sockets with JDK 7 we must use the open overload that accepts
+ // ProtocolFamily and specify the ProtocolFamily that corresponds to the address
+ // type of the multicast groups that the channel will join.
+ //
+ String family = "INET";
+ if(addr.getAddress() instanceof java.net.Inet6Address)
+ {
+ family = "INET6";
+ }
+ java.lang.reflect.Method valueOf = c.getDeclaredMethod("valueOf", new Class<?>[]{String.class});
+
+ Object[] args = new Object[]{valueOf.invoke(null, new Object[]{family})};
+
+ java.lang.reflect.Method open = java.nio.channels.DatagramChannel.class.getDeclaredMethod(
+ "open", new Class<?>[]{Util.findClass("java.net.ProtocolFamily", null)});
+ return (java.nio.channels.DatagramChannel)open.invoke(null, args);
+ }
+ else
+ {
+ return java.nio.channels.DatagramChannel.open();
+ }
+ }
+ catch(IllegalAccessException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ catch(java.lang.reflect.InvocationTargetException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ catch(NoSuchMethodException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static void
+ closeSocketNoThrow(java.nio.channels.SelectableChannel fd)
+ {
+ try
+ {
+ fd.close();
+ }
+ catch(java.io.IOException ex)
+ {
+ // Ignore
+ }
+ }
+
+ public static void
+ closeSocket(java.nio.channels.SelectableChannel fd)
+ {
+ try
+ {
+ fd.close();
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static void
+ setBlock(java.nio.channels.SelectableChannel fd, boolean block)
+ {
+ try
+ {
+ fd.configureBlocking(block);
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static void
+ setReuseAddress(java.nio.channels.DatagramChannel fd, boolean reuse)
+ {
+ try
+ {
+ fd.socket().setReuseAddress(reuse);
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static void
+ setReuseAddress(java.nio.channels.ServerSocketChannel fd, boolean reuse)
+ {
+ try
+ {
+ fd.socket().setReuseAddress(reuse);
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static java.net.InetSocketAddress
+ doBind(java.nio.channels.ServerSocketChannel fd, java.net.InetSocketAddress addr, int backlog)
+ {
+ try
+ {
+ java.net.ServerSocket sock = fd.socket();
+ sock.bind(addr, backlog);
+ return (java.net.InetSocketAddress)sock.getLocalSocketAddress();
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static java.net.InetSocketAddress
+ doBind(java.nio.channels.DatagramChannel fd, java.net.InetSocketAddress addr)
+ {
+ try
+ {
+ java.net.DatagramSocket sock = fd.socket();
+ sock.bind(addr);
+ return (java.net.InetSocketAddress)sock.getLocalSocketAddress();
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static java.nio.channels.SocketChannel
+ doAccept(java.nio.channels.ServerSocketChannel afd)
+ {
+ java.nio.channels.SocketChannel fd = null;
+ while(true)
+ {
+ try
+ {
+ fd = afd.accept();
+ break;
+ }
+ catch(java.io.IOException ex)
+ {
+ if(interrupted(ex))
+ {
+ continue;
+ }
+
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ try
+ {
+ java.net.Socket socket = fd.socket();
+ socket.setTcpNoDelay(true);
+ socket.setKeepAlive(true);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+
+ return fd;
+ }
+
+ public static boolean
+ doConnect(java.nio.channels.SocketChannel fd, java.net.InetSocketAddress addr,
+ java.net.InetSocketAddress sourceAddr)
+ {
+ if(sourceAddr != null)
+ {
+ try
+ {
+ fd.bind(sourceAddr);
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ try
+ {
+ if(!fd.connect(addr))
+ {
+ return false;
+ }
+ }
+ catch(java.net.ConnectException ex)
+ {
+ closeSocketNoThrow(fd);
+
+ if(connectionRefused(ex))
+ {
+ throw new Ice.ConnectionRefusedException(ex);
+ }
+ else
+ {
+ throw new Ice.ConnectFailedException(ex);
+ }
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ catch(java.lang.SecurityException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+
+ if(System.getProperty("os.name").equals("Linux"))
+ {
+ //
+ // Prevent self connect (self connect happens on Linux when a client tries to connect to
+ // a server which was just deactivated if the client socket re-uses the same ephemeral
+ // port as the server).
+ //
+ if(addr.equals(fd.socket().getLocalSocketAddress()))
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.ConnectionRefusedException();
+ }
+ }
+ return true;
+ }
+
+ public static void
+ doFinishConnect(java.nio.channels.SocketChannel fd)
+ {
+ //
+ // Note: we don't close the socket if there's an exception. It's the responsibility
+ // of the caller to do so.
+ //
+
+ try
+ {
+ if(!fd.finishConnect())
+ {
+ throw new Ice.ConnectFailedException();
+ }
+
+ if(System.getProperty("os.name").equals("Linux"))
+ {
+ //
+ // Prevent self connect (self connect happens on Linux when a client tries to connect to
+ // a server which was just deactivated if the client socket re-uses the same ephemeral
+ // port as the server).
+ //
+ java.net.SocketAddress addr = fd.socket().getRemoteSocketAddress();
+ if(addr != null && addr.equals(fd.socket().getLocalSocketAddress()))
+ {
+ throw new Ice.ConnectionRefusedException();
+ }
+ }
+ }
+ catch(java.net.ConnectException ex)
+ {
+ if(connectionRefused(ex))
+ {
+ throw new Ice.ConnectionRefusedException(ex);
+ }
+ else
+ {
+ throw new Ice.ConnectFailedException(ex);
+ }
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static void
+ doConnect(java.nio.channels.DatagramChannel fd, java.net.InetSocketAddress addr,
+ java.net.InetSocketAddress sourceAddr)
+ {
+ if(sourceAddr != null)
+ {
+ doBind(fd, sourceAddr);
+ }
+
+ try
+ {
+ fd.connect(addr);
+ }
+ catch(java.net.ConnectException ex)
+ {
+ closeSocketNoThrow(fd);
+
+ if(connectionRefused(ex))
+ {
+ throw new Ice.ConnectionRefusedException(ex);
+ }
+ else
+ {
+ throw new Ice.ConnectFailedException(ex);
+ }
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static void
+ setSendBufferSize(java.nio.channels.SocketChannel fd, int size)
+ {
+ try
+ {
+ java.net.Socket socket = fd.socket();
+ socket.setSendBufferSize(size);
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static int
+ getSendBufferSize(java.nio.channels.SocketChannel fd)
+ {
+ int size;
+ try
+ {
+ java.net.Socket socket = fd.socket();
+ size = socket.getSendBufferSize();
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ return size;
+ }
+
+ public static void
+ setRecvBufferSize(java.nio.channels.SocketChannel fd, int size)
+ {
+ try
+ {
+ java.net.Socket socket = fd.socket();
+ socket.setReceiveBufferSize(size);
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static int
+ getRecvBufferSize(java.nio.channels.SocketChannel fd)
+ {
+ int size;
+ try
+ {
+ java.net.Socket socket = fd.socket();
+ size = socket.getReceiveBufferSize();
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ return size;
+ }
+
+ public static void
+ setRecvBufferSize(java.nio.channels.ServerSocketChannel fd, int size)
+ {
+ try
+ {
+ java.net.ServerSocket socket = fd.socket();
+ socket.setReceiveBufferSize(size);
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static int
+ getRecvBufferSize(java.nio.channels.ServerSocketChannel fd)
+ {
+ int size;
+ try
+ {
+ java.net.ServerSocket socket = fd.socket();
+ size = socket.getReceiveBufferSize();
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ return size;
+ }
+
+ public static void
+ setSendBufferSize(java.nio.channels.DatagramChannel fd, int size)
+ {
+ try
+ {
+ java.net.DatagramSocket socket = fd.socket();
+ socket.setSendBufferSize(size);
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static int
+ getSendBufferSize(java.nio.channels.DatagramChannel fd)
+ {
+ int size;
+ try
+ {
+ java.net.DatagramSocket socket = fd.socket();
+ size = socket.getSendBufferSize();
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ return size;
+ }
+
+ public static void
+ setRecvBufferSize(java.nio.channels.DatagramChannel fd, int size)
+ {
+ try
+ {
+ java.net.DatagramSocket socket = fd.socket();
+ socket.setReceiveBufferSize(size);
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static int
+ getRecvBufferSize(java.nio.channels.DatagramChannel fd)
+ {
+ int size;
+ try
+ {
+ java.net.DatagramSocket socket = fd.socket();
+ size = socket.getReceiveBufferSize();
+ }
+ catch(java.io.IOException ex)
+ {
+ closeSocketNoThrow(fd);
+ throw new Ice.SocketException(ex);
+ }
+ return size;
+ }
+
+ public static java.net.InetSocketAddress
+ getAddressForServer(String host, int port, int protocol, boolean preferIPv6)
+ {
+ if(host == null || host.length() == 0)
+ {
+ try
+ {
+ if(protocol != EnableIPv4)
+ {
+ return new java.net.InetSocketAddress(java.net.InetAddress.getByName("::0"), port);
+ }
+ else
+ {
+ return new java.net.InetSocketAddress(java.net.InetAddress.getByName("0.0.0.0"), port);
+ }
+ }
+ catch(java.net.UnknownHostException ex)
+ {
+ assert(false);
+ return null;
+ }
+ catch(java.lang.SecurityException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+ return getAddresses(host, port, protocol, Ice.EndpointSelectionType.Ordered, preferIPv6, true).get(0);
+ }
+
+ public static int
+ compareAddress(java.net.InetSocketAddress addr1, java.net.InetSocketAddress addr2)
+ {
+ if(addr1 == null)
+ {
+ if(addr2 == null)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else if(addr2 == null)
+ {
+ return 1;
+ }
+
+ if(addr1.getPort() < addr2.getPort())
+ {
+ return -1;
+ }
+ else if(addr2.getPort() < addr1.getPort())
+ {
+ return 1;
+ }
+
+ byte[] larr = addr1.getAddress().getAddress();
+ byte[] rarr = addr2.getAddress().getAddress();
+ if(larr.length < rarr.length)
+ {
+ return -1;
+ }
+ else if(rarr.length < larr.length)
+ {
+ return 1;
+ }
+ assert(larr.length == rarr.length);
+
+ for(int i = 0; i < larr.length; i++)
+ {
+ if(larr[i] < rarr[i])
+ {
+ return -1;
+ }
+ else if(rarr[i] < larr[i])
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ public static java.net.InetAddress
+ getLocalAddress(int protocol)
+ {
+ java.net.InetAddress addr = null;
+
+ try
+ {
+ addr = java.net.InetAddress.getLocalHost();
+ }
+ catch(java.net.UnknownHostException ex)
+ {
+ //
+ // May be raised on DHCP systems.
+ //
+ }
+ catch(NullPointerException ex)
+ {
+ //
+ // Workaround for bug in JDK.
+ //
+ }
+
+ if(addr == null || !isValidAddr(addr, protocol))
+ {
+ //
+ // Iterate over the network interfaces and pick an IP
+ // address (preferably not the loopback address).
+ //
+ java.util.ArrayList<java.net.InetAddress> addrs = getLocalAddresses(protocol);
+ java.util.Iterator<java.net.InetAddress> iter = addrs.iterator();
+ while(addr == null && iter.hasNext())
+ {
+ java.net.InetAddress a = iter.next();
+ if(protocol == EnableBoth || isValidAddr(a, protocol))
+ {
+ addr = a;
+ }
+ }
+
+ if(addr == null)
+ {
+ addr = getLoopbackAddresses(protocol)[0]; // Use the loopback address as the last resort.
+ }
+ }
+
+ assert(addr != null);
+ return addr;
+ }
+
+ public static java.util.List<java.net.InetSocketAddress>
+ getAddresses(String host, int port, int protocol, Ice.EndpointSelectionType selType, boolean preferIPv6,
+ boolean blocking)
+ {
+ if(!blocking)
+ {
+ if(!isNumericAddress(host))
+ {
+ return null; // Can't get the address without blocking.
+ }
+
+ java.util.List<java.net.InetSocketAddress> addrs = new java.util.ArrayList<java.net.InetSocketAddress>();
+ try
+ {
+ addrs.add(new java.net.InetSocketAddress(java.net.InetAddress.getByName(host), port));
+ }
+ catch(java.net.UnknownHostException ex)
+ {
+ assert(false);
+ }
+ return addrs;
+ }
+
+ java.util.List<java.net.InetSocketAddress> addresses = new java.util.ArrayList<java.net.InetSocketAddress>();
+ try
+ {
+ java.net.InetAddress[] addrs;
+ if(host == null || host.length() == 0)
+ {
+ addrs = getLoopbackAddresses(protocol);
+ }
+ else
+ {
+ addrs = java.net.InetAddress.getAllByName(host);
+ }
+
+ for(java.net.InetAddress addr : addrs)
+ {
+ if(protocol == EnableBoth || isValidAddr(addr, protocol))
+ {
+ addresses.add(new java.net.InetSocketAddress(addr, port));
+ }
+ }
+
+ if(selType == Ice.EndpointSelectionType.Random)
+ {
+ java.util.Collections.shuffle(addresses);
+ }
+
+ if(protocol == EnableBoth)
+ {
+ if(preferIPv6)
+ {
+ java.util.Collections.sort(addresses, _preferIPv6Comparator);
+ }
+ else
+ {
+ java.util.Collections.sort(addresses, _preferIPv4Comparator);
+ }
+ }
+ }
+ catch(java.net.UnknownHostException ex)
+ {
+ throw new Ice.DNSException(0, host, ex);
+ }
+ catch(java.lang.SecurityException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+
+ //
+ // No Inet4Address/Inet6Address available.
+ //
+ if(addresses.isEmpty())
+ {
+ throw new Ice.DNSException(0, host);
+ }
+
+ return addresses;
+ }
+
+ public static java.util.ArrayList<java.net.InetAddress>
+ getLocalAddresses(int protocol)
+ {
+ java.util.ArrayList<java.net.InetAddress> result = new java.util.ArrayList<java.net.InetAddress>();
+ try
+ {
+ java.util.Enumeration<java.net.NetworkInterface> ifaces = java.net.NetworkInterface.getNetworkInterfaces();
+ while(ifaces.hasMoreElements())
+ {
+ java.net.NetworkInterface iface = ifaces.nextElement();
+ java.util.Enumeration<java.net.InetAddress> addrs = iface.getInetAddresses();
+ while(addrs.hasMoreElements())
+ {
+ java.net.InetAddress addr = addrs.nextElement();
+ if(!addr.isLoopbackAddress())
+ {
+ if(protocol == EnableBoth || isValidAddr(addr, protocol))
+ {
+ result.add(addr);
+ }
+ }
+ }
+ }
+ }
+ catch(java.net.SocketException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ catch(java.lang.SecurityException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+
+ return result;
+ }
+
+ public static final class SocketPair
+ {
+ public java.nio.channels.spi.AbstractSelectableChannel source;
+ public java.nio.channels.WritableByteChannel sink;
+ }
+
+ public static SocketPair
+ createPipe()
+ {
+ SocketPair fds = new SocketPair();
+ try
+ {
+ java.nio.channels.Pipe pipe = java.nio.channels.Pipe.open();
+ fds.sink = pipe.sink();
+ fds.source = pipe.source();
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ return fds;
+ }
+
+ public static java.util.ArrayList<String>
+ getHostsForEndpointExpand(String host, int protocolSupport, boolean includeLoopback)
+ {
+ boolean wildcard = (host == null || host.length() == 0);
+ if(!wildcard)
+ {
+ try
+ {
+ wildcard = java.net.InetAddress.getByName(host).isAnyLocalAddress();
+ }
+ catch(java.net.UnknownHostException ex)
+ {
+ }
+ catch(java.lang.SecurityException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ java.util.ArrayList<String> hosts = new java.util.ArrayList<String>();
+ if(wildcard)
+ {
+ java.util.ArrayList<java.net.InetAddress> addrs = getLocalAddresses(protocolSupport);
+ for(java.net.InetAddress addr : addrs)
+ {
+ //
+ // NOTE: We don't publish link-local IPv6 addresses as these addresses can only
+ // be accessed in general with a scope-id.
+ //
+ if(!addr.isLinkLocalAddress())
+ {
+ hosts.add(addr.getHostAddress());
+ }
+ }
+
+ if(includeLoopback || hosts.isEmpty())
+ {
+ if(protocolSupport != EnableIPv6)
+ {
+ hosts.add("127.0.0.1");
+ }
+
+ if(protocolSupport != EnableIPv4)
+ {
+ hosts.add("0:0:0:0:0:0:0:1");
+ }
+ }
+ }
+ return hosts;
+ }
+
+ public static void
+ setTcpBufSize(java.nio.channels.SocketChannel socket, ProtocolInstance instance)
+ {
+ //
+ // By default, on Windows we use a 128KB buffer size. On Unix
+ // platforms, we use the system defaults.
+ //
+ int dfltBufSize = 0;
+ if(System.getProperty("os.name").startsWith("Windows"))
+ {
+ dfltBufSize = 128 * 1024;
+ }
+
+ int rcvSize = instance.properties().getPropertyAsIntWithDefault("Ice.TCP.RcvSize", dfltBufSize);
+ int sndSize = instance.properties().getPropertyAsIntWithDefault("Ice.TCP.SndSize", dfltBufSize);
+
+ setTcpBufSize(socket, rcvSize, sndSize, instance);
+ }
+
+ public static void
+ setTcpBufSize(java.nio.channels.SocketChannel socket, int rcvSize, int sndSize, ProtocolInstance instance)
+ {
+ if(rcvSize > 0)
+ {
+ //
+ // Try to set the buffer size. The kernel will silently adjust
+ // the size to an acceptable value. Then read the size back to
+ // get the size that was actually set.
+ //
+ setRecvBufferSize(socket, rcvSize);
+ int size = getRecvBufferSize(socket);
+ if(size < rcvSize)
+ {
+ // Warn if the size that was set is less than the requested size and
+ // we have not already warned.
+ BufSizeWarnInfo winfo = instance.getBufSizeWarn(Ice.TCPEndpointType.value);
+ if(!winfo.rcvWarn || rcvSize != winfo.rcvSize)
+ {
+ instance.logger().warning("TCP receive buffer size: requested size of " + rcvSize +
+ " adjusted to " + size);
+ instance.setRcvBufSizeWarn(Ice.TCPEndpointType.value, rcvSize);
+ }
+ }
+ }
+
+ if(sndSize > 0)
+ {
+ //
+ // Try to set the buffer size. The kernel will silently adjust
+ // the size to an acceptable value. Then read the size back to
+ // get the size that was actually set.
+ //
+ setSendBufferSize(socket, sndSize);
+ int size = getSendBufferSize(socket);
+ if(size < sndSize)
+ {
+ // Warn if the size that was set is less than the requested size and
+ // we have not already warned.
+ BufSizeWarnInfo winfo = instance.getBufSizeWarn(Ice.TCPEndpointType.value);
+ if(!winfo.sndWarn || sndSize != winfo.sndSize)
+ {
+ instance.logger().warning("TCP send buffer size: requested size of " + sndSize +
+ " adjusted to " + size);
+ instance.setSndBufSizeWarn(Ice.TCPEndpointType.value, sndSize);
+ }
+ }
+ }
+ }
+
+ public static void
+ setTcpBufSize(java.nio.channels.ServerSocketChannel socket, ProtocolInstance instance)
+ {
+ //
+ // By default, on Windows we use a 128KB buffer size. On Unix
+ // platforms, we use the system defaults.
+ //
+ int dfltBufSize = 0;
+ if(System.getProperty("os.name").startsWith("Windows"))
+ {
+ dfltBufSize = 128 * 1024;
+ }
+
+ //
+ // Get property for buffer size.
+ //
+ int sizeRequested = instance.properties().getPropertyAsIntWithDefault("Ice.TCP.RcvSize", dfltBufSize);
+ if(sizeRequested > 0)
+ {
+ //
+ // Try to set the buffer size. The kernel will silently adjust
+ // the size to an acceptable value. Then read the size back to
+ // get the size that was actually set.
+ //
+ setRecvBufferSize(socket, sizeRequested);
+ int size = getRecvBufferSize(socket);
+ if(size < sizeRequested)
+ {
+ // Warn if the size that was set is less than the requested size and
+ // we have not already warned.
+ BufSizeWarnInfo winfo = instance.getBufSizeWarn(Ice.TCPEndpointType.value);
+ if(!winfo.rcvWarn || sizeRequested != winfo.rcvSize)
+ {
+ instance.logger().warning("TCP receive buffer size: requested size of " + sizeRequested +
+ " adjusted to " + size);
+ instance.setRcvBufSizeWarn(Ice.TCPEndpointType.value, sizeRequested);
+ }
+ }
+ }
+ }
+
+ public static String
+ fdToString(java.nio.channels.SelectableChannel fd, NetworkProxy proxy, java.net.InetSocketAddress target)
+ {
+ if(fd == null)
+ {
+ return "<closed>";
+ }
+
+ java.net.InetAddress localAddr = null, remoteAddr = null;
+ int localPort = -1, remotePort = -1;
+
+ if(fd instanceof java.nio.channels.SocketChannel)
+ {
+ java.net.Socket socket = ((java.nio.channels.SocketChannel)fd).socket();
+ localAddr = socket.getLocalAddress();
+ localPort = socket.getLocalPort();
+ remoteAddr = socket.getInetAddress();
+ remotePort = socket.getPort();
+ }
+ else if(fd instanceof java.nio.channels.DatagramChannel)
+ {
+ java.net.DatagramSocket socket = ((java.nio.channels.DatagramChannel)fd).socket();
+ localAddr = socket.getLocalAddress();
+ localPort = socket.getLocalPort();
+ remoteAddr = socket.getInetAddress();
+ remotePort = socket.getPort();
+ }
+ else
+ {
+ assert(false);
+ }
+
+ return addressesToString(localAddr, localPort, remoteAddr, remotePort, proxy, target);
+ }
+
+ public static String
+ fdToString(java.nio.channels.SelectableChannel fd)
+ {
+ if(fd == null)
+ {
+ return "<closed>";
+ }
+
+ java.net.InetAddress localAddr = null, remoteAddr = null;
+ int localPort = -1, remotePort = -1;
+
+ if(fd instanceof java.nio.channels.SocketChannel)
+ {
+ java.net.Socket socket = ((java.nio.channels.SocketChannel)fd).socket();
+ localAddr = socket.getLocalAddress();
+ localPort = socket.getLocalPort();
+ remoteAddr = socket.getInetAddress();
+ remotePort = socket.getPort();
+ }
+ else if(fd instanceof java.nio.channels.DatagramChannel)
+ {
+ java.net.DatagramSocket socket = ((java.nio.channels.DatagramChannel)fd).socket();
+ localAddr = socket.getLocalAddress();
+ localPort = socket.getLocalPort();
+ remoteAddr = socket.getInetAddress();
+ remotePort = socket.getPort();
+ }
+ else
+ {
+ assert(false);
+ }
+
+ return addressesToString(localAddr, localPort, remoteAddr, remotePort);
+ }
+
+ public static String
+ addressesToString(java.net.InetAddress localAddr, int localPort, java.net.InetAddress remoteAddr, int remotePort,
+ NetworkProxy proxy, java.net.InetSocketAddress target)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("local address = ");
+ s.append(addrToString(localAddr, localPort));
+
+ if(proxy != null)
+ {
+ if(remoteAddr == null)
+ {
+ java.net.InetSocketAddress addr = proxy.getAddress();
+ remoteAddr = addr.getAddress();
+ remotePort = addr.getPort();
+ }
+ s.append("\n");
+ s.append(proxy.getName());
+ s.append(" proxy address = ");
+ s.append(addrToString(remoteAddr, remotePort));
+ s.append("\nremote address = ");
+ s.append(addrToString(target.getAddress(), target.getPort()));
+ }
+ else
+ {
+ if(remoteAddr == null && target != null)
+ {
+ remoteAddr = target.getAddress();
+ remotePort = target.getPort();
+ }
+
+ if(remoteAddr == null)
+ {
+ s.append("\nremote address = <not connected>");
+ }
+ else
+ {
+ s.append("\nremote address = ");
+ s.append(addrToString(remoteAddr, remotePort));
+ }
+ }
+
+ return s.toString();
+ }
+
+ public static String
+ addressesToString(java.net.InetAddress localAddr, int localPort, java.net.InetAddress remoteAddr, int remotePort)
+ {
+ return addressesToString(localAddr, localPort, remoteAddr, remotePort, null, null);
+ }
+
+ public static String
+ addrToString(java.net.InetSocketAddress addr)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append(addr.getAddress().getHostAddress());
+ s.append(':');
+ s.append(addr.getPort());
+ return s.toString();
+ }
+
+ public static boolean
+ interrupted(java.io.IOException ex)
+ {
+ return ex instanceof java.io.InterruptedIOException;
+ }
+
+ private static boolean
+ isValidAddr(java.net.InetAddress addr, int protocol)
+ {
+ byte[] bytes = null;
+ if(addr != null)
+ {
+ bytes = addr.getAddress();
+ }
+ return bytes != null &&
+ ((bytes.length == 16 && protocol == EnableIPv6) ||
+ (bytes.length == 4 && protocol == EnableIPv4));
+ }
+
+ public static String
+ addrToString(java.net.InetAddress addr, int port)
+ {
+ StringBuffer s = new StringBuffer();
+
+ //
+ // In early Android releases, sockets don't correctly report their address and
+ // port information.
+ //
+
+ if(addr == null || addr.isAnyLocalAddress())
+ {
+ s.append("<not available>");
+ }
+ else
+ {
+ s.append(addr.getHostAddress());
+ }
+
+ if(port > 0)
+ {
+ s.append(':');
+ s.append(port);
+ }
+
+ return s.toString();
+ }
+
+ private static java.net.InetAddress[]
+ getLoopbackAddresses(int protocol)
+ {
+ try
+ {
+ java.net.InetAddress[] addrs = new java.net.InetAddress[protocol == EnableBoth ? 2 : 1];
+ int i = 0;
+ if(protocol != EnableIPv6)
+ {
+ addrs[i++] = java.net.InetAddress.getByName("127.0.0.1");
+ }
+ if(protocol != EnableIPv4)
+ {
+ addrs[i++] = java.net.InetAddress.getByName("::1");
+ }
+ return addrs;
+ }
+ catch(java.net.UnknownHostException ex)
+ {
+ assert(false);
+ return null;
+ }
+ catch(java.lang.SecurityException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ public static java.net.InetSocketAddress
+ getNumericAddress(String address)
+ {
+ java.net.InetSocketAddress addr = null;
+ if(!address.isEmpty() && isNumericAddress(address))
+ {
+ try
+ {
+ addr = new java.net.InetSocketAddress(java.net.InetAddress.getByName(address), 0);
+ }
+ catch(java.net.UnknownHostException ex)
+ {
+ }
+ }
+ return addr;
+ }
+
+ static class IPAddressComparator implements java.util.Comparator<java.net.InetSocketAddress>
+ {
+ IPAddressComparator(boolean ipv6)
+ {
+ _ipv6 = ipv6;
+ }
+
+ @Override
+ public int
+ compare(java.net.InetSocketAddress lhs, java.net.InetSocketAddress rhs)
+ {
+ if(lhs.getAddress().getAddress().length < rhs.getAddress().getAddress().length)
+ {
+ return _ipv6 ? 1 : -1;
+ }
+ else if(lhs.getAddress().getAddress().length > rhs.getAddress().getAddress().length)
+ {
+ return _ipv6 ? -1 : 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ final private boolean _ipv6;
+ }
+
+ private static IPAddressComparator _preferIPv4Comparator = new IPAddressComparator(false);
+ private static IPAddressComparator _preferIPv6Comparator = new IPAddressComparator(true);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/NetworkProxy.java b/java-compat/src/Ice/src/main/java/IceInternal/NetworkProxy.java
new file mode 100644
index 00000000000..80dcce87d3e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/NetworkProxy.java
@@ -0,0 +1,60 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface NetworkProxy
+{
+ //
+ // Write the connection request on the connection established
+ // with the network proxy server. This is called right after
+ // the connection establishment succeeds.
+ //
+ void beginWrite(java.net.InetSocketAddress endpoint, Buffer buf);
+ int endWrite(Buffer buf);
+
+ //
+ // Once the connection request has been sent, this is called
+ // to prepare and read the response from the proxy server.
+ //
+ void beginRead(Buffer buf);
+ int endRead(Buffer buf);
+
+ //
+ // This is called when the response from the proxy has been
+ // read. The proxy should copy the extra read data (if any) in the
+ // given byte vector.
+ //
+ void finish(Buffer readBuffer, Buffer writeBuffer);
+
+ //
+ // If the proxy host needs to be resolved, this should return
+ // a new NetworkProxy containing the IP address of the proxy.
+ // This is called from the endpoint host resolver thread, so
+ // it's safe if this this method blocks.
+ //
+ NetworkProxy resolveHost(int protocolSupport);
+
+ //
+ // Returns the IP address of the network proxy. This method
+ // must not block. It's only called on a network proxy object
+ // returned by resolveHost().
+ //
+ java.net.InetSocketAddress getAddress();
+
+ //
+ // Returns the name of the proxy, used for tracing purposes.
+ //
+ String getName();
+
+ //
+ // Returns the protocols supported by the proxy.
+ //
+ int getProtocolSupport();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ObjectAdapterFactory.java b/java-compat/src/Ice/src/main/java/IceInternal/ObjectAdapterFactory.java
new file mode 100644
index 00000000000..bfec67de6a6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ObjectAdapterFactory.java
@@ -0,0 +1,268 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class ObjectAdapterFactory
+{
+ public void
+ shutdown()
+ {
+ java.util.List<Ice.ObjectAdapterI> adapters;
+ synchronized(this)
+ {
+ //
+ // Ignore shutdown requests if the object adapter factory has
+ // already been shut down.
+ //
+ if(_instance == null)
+ {
+ return;
+ }
+
+ adapters = new java.util.LinkedList<Ice.ObjectAdapterI>(_adapters);
+ }
+
+ //
+ // Deactivate outside the thread synchronization, to avoid
+ // deadlocks.
+ //
+ for(Ice.ObjectAdapterI adapter : adapters)
+ {
+ adapter.deactivate();
+ }
+
+ synchronized(this)
+ {
+ _instance = null;
+ _communicator = null;
+ notifyAll();
+ }
+ }
+
+
+ public void
+ waitForShutdown()
+ {
+ java.util.List<Ice.ObjectAdapterI> adapters;
+ synchronized(this)
+ {
+ //
+ // First we wait for the shutdown of the factory itself.
+ //
+ while(_instance != null)
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+
+ adapters = new java.util.LinkedList<Ice.ObjectAdapterI>(_adapters);
+ }
+
+ //
+ // Now we wait for deactivation of each object adapter.
+ //
+ for(Ice.ObjectAdapterI adapter : adapters)
+ {
+ adapter.waitForDeactivate();
+ }
+ }
+
+ public synchronized boolean
+ isShutdown()
+ {
+ return _instance == null;
+ }
+
+ public void
+ destroy()
+ {
+ //
+ // First wait for shutdown to finish.
+ //
+ waitForShutdown();
+
+ java.util.List<Ice.ObjectAdapterI> adapters;
+ synchronized(this)
+ {
+ adapters = new java.util.LinkedList<Ice.ObjectAdapterI>(_adapters);
+ }
+
+ for(Ice.ObjectAdapterI adapter : adapters)
+ {
+ adapter.destroy();
+ }
+
+ synchronized(this)
+ {
+ _adapters.clear();
+ }
+ }
+
+ public void
+ updateConnectionObservers()
+ {
+ java.util.List<Ice.ObjectAdapterI> adapters;
+ synchronized(this)
+ {
+ adapters = new java.util.LinkedList<Ice.ObjectAdapterI>(_adapters);
+ }
+
+ for(Ice.ObjectAdapterI adapter : adapters)
+ {
+ adapter.updateConnectionObservers();
+ }
+ }
+
+ public void
+ updateThreadObservers()
+ {
+ java.util.List<Ice.ObjectAdapterI> adapters;
+ synchronized(this)
+ {
+ adapters = new java.util.LinkedList<Ice.ObjectAdapterI>(_adapters);
+ }
+
+ for(Ice.ObjectAdapterI adapter : adapters)
+ {
+ adapter.updateThreadObservers();
+ }
+ }
+
+ public synchronized Ice.ObjectAdapter
+ createObjectAdapter(String name, Ice.RouterPrx router)
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+
+ if(_instance == null)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ Ice.ObjectAdapterI adapter = null;
+ if(name.length() == 0)
+ {
+ String uuid = java.util.UUID.randomUUID().toString();
+ adapter = new Ice.ObjectAdapterI(_instance, _communicator, this, uuid, null, true);
+ }
+ else
+ {
+ if(_adapterNamesInUse.contains(name))
+ {
+ throw new Ice.AlreadyRegisteredException("object adapter", name);
+ }
+ adapter = new Ice.ObjectAdapterI(_instance, _communicator, this, name, router, false);
+ _adapterNamesInUse.add(name);
+ }
+ _adapters.add(adapter);
+ return adapter;
+ }
+
+ public Ice.ObjectAdapter
+ findObjectAdapter(Ice.ObjectPrx proxy)
+ {
+ java.util.List<Ice.ObjectAdapterI> adapters;
+ synchronized(this)
+ {
+ if(_instance == null)
+ {
+ return null;
+ }
+
+ adapters = new java.util.LinkedList<Ice.ObjectAdapterI>(_adapters);
+ }
+
+ for(Ice.ObjectAdapterI adapter : adapters)
+ {
+ try
+ {
+ if(adapter.isLocal(proxy))
+ {
+ return adapter;
+ }
+ }
+ catch(Ice.ObjectAdapterDeactivatedException ex)
+ {
+ // Ignore.
+ }
+ }
+
+ return null;
+ }
+
+ public synchronized void
+ removeObjectAdapter(Ice.ObjectAdapter adapter)
+ {
+ if(_instance == null)
+ {
+ return;
+ }
+
+ _adapters.remove(adapter);
+ _adapterNamesInUse.remove(adapter.getName());
+ }
+
+ public void
+ flushAsyncBatchRequests(CommunicatorFlushBatch outAsync)
+ {
+ java.util.List<Ice.ObjectAdapterI> adapters;
+ synchronized(this)
+ {
+ adapters = new java.util.LinkedList<Ice.ObjectAdapterI>(_adapters);
+ }
+
+ for(Ice.ObjectAdapterI adapter : adapters)
+ {
+ adapter.flushAsyncBatchRequests(outAsync);
+ }
+ }
+
+ //
+ // Only for use by Instance.
+ //
+ ObjectAdapterFactory(Instance instance, Ice.Communicator communicator)
+ {
+ _instance = instance;
+ _communicator = communicator;
+ }
+
+ @Override
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_instance == null);
+ IceUtilInternal.Assert.FinalizerAssert(_communicator == null);
+ IceUtilInternal.Assert.FinalizerAssert(_adapters.isEmpty());
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ private Instance _instance;
+ private Ice.Communicator _communicator;
+ private java.util.Set<String> _adapterNamesInUse = new java.util.HashSet<String>();
+ private java.util.List<Ice.ObjectAdapterI> _adapters = new java.util.LinkedList<Ice.ObjectAdapterI>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ObjectInputStream.java b/java-compat/src/Ice/src/main/java/IceInternal/ObjectInputStream.java
new file mode 100644
index 00000000000..ea1e7167f4c
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ObjectInputStream.java
@@ -0,0 +1,52 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+//
+// We need to override the resolveClass method of ObjectInputStream so
+// that we can use the same class-lookup mechanism as elsewhere in the
+// Ice run time.
+//
+
+public class ObjectInputStream extends java.io.ObjectInputStream
+{
+ public ObjectInputStream(Instance instance, java.io.InputStream in)
+ throws java.io.IOException
+ {
+ super(in);
+ _instance = instance;
+ }
+
+ @Override
+ protected Class<?> resolveClass(java.io.ObjectStreamClass cls)
+ throws java.io.IOException, ClassNotFoundException
+ {
+ if(_instance == null)
+ {
+ throw new Ice.MarshalException("cannot unmarshal a serializable without a communicator");
+ }
+
+ try
+ {
+ Class<?> c = _instance.findClass(cls.getName());
+ if(c != null)
+ {
+ return c;
+ }
+ throw new ClassNotFoundException("unable to resolve class" + cls.getName());
+ }
+ catch(Exception ex)
+ {
+ throw new ClassNotFoundException("unable to resolve class " + cls.getName(), ex);
+ }
+ }
+
+ private Instance _instance;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ObserverHelper.java b/java-compat/src/Ice/src/main/java/IceInternal/ObserverHelper.java
new file mode 100644
index 00000000000..290be728304
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ObserverHelper.java
@@ -0,0 +1,65 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import Ice.Instrumentation.CommunicatorObserver;
+import Ice.Instrumentation.InvocationObserver;
+
+public final class ObserverHelper
+{
+ static public InvocationObserver
+ get(Instance instance, String op)
+ {
+ CommunicatorObserver obsv = instance.initializationData().observer;
+ if(obsv != null)
+ {
+ InvocationObserver observer = obsv.getInvocationObserver(null, op, _emptyContext);
+ if(observer != null)
+ {
+ observer.attach();
+ }
+ return observer;
+ }
+ return null;
+ }
+
+ static public InvocationObserver
+ get(Ice.ObjectPrx proxy, String op)
+ {
+ return get(proxy, op, null);
+ }
+
+ static public InvocationObserver
+ get(Ice.ObjectPrx proxy, String op, java.util.Map<String, String> context)
+ {
+ CommunicatorObserver obsv =
+ ((Ice.ObjectPrxHelperBase)proxy).__reference().getInstance().initializationData().observer;
+ if(obsv != null)
+ {
+ InvocationObserver observer;
+ if(context == null)
+ {
+ observer = obsv.getInvocationObserver(proxy, op, _emptyContext);
+ }
+ else
+ {
+ observer = obsv.getInvocationObserver(proxy, op, context);
+ }
+ if(observer != null)
+ {
+ observer.attach();
+ }
+ return observer;
+ }
+ return null;
+ }
+
+ private static final java.util.Map<String, String> _emptyContext = new java.util.HashMap<String, String>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/OpaqueEndpointI.java b/java-compat/src/Ice/src/main/java/IceInternal/OpaqueEndpointI.java
new file mode 100644
index 00000000000..c6c6b849ba5
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/OpaqueEndpointI.java
@@ -0,0 +1,422 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class OpaqueEndpointI extends EndpointI
+{
+ public OpaqueEndpointI(java.util.ArrayList<String> args)
+ {
+ _type = -1;
+ _rawEncoding = Ice.Util.Encoding_1_0;
+ _rawBytes = new byte[0];
+
+ initWithOptions(args);
+
+ if(_type < 0)
+ {
+ throw new Ice.EndpointParseException("no -t option in endpoint " + toString());
+ }
+ if(_rawBytes.length == 0)
+ {
+ throw new Ice.EndpointParseException("no -v option in endpoint " + toString());
+ }
+
+ calcHashValue();
+ }
+
+ public OpaqueEndpointI(short type, Ice.InputStream s)
+ {
+ _type = type;
+ _rawEncoding = s.getEncoding();
+ int sz = s.getEncapsulationSize();
+ _rawBytes = s.readBlob(sz);
+
+ calcHashValue();
+ }
+
+ //
+ // Marshal the endpoint
+ //
+ @Override
+ public void streamWrite(Ice.OutputStream s)
+ {
+ s.startEncapsulation(_rawEncoding, Ice.FormatType.DefaultFormat);
+ s.writeBlob(_rawBytes);
+ s.endEncapsulation();
+ }
+
+ @Override
+ public void streamWriteImpl(Ice.OutputStream s)
+ {
+ assert(false);
+ }
+
+ //
+ // Return the endpoint information.
+ //
+ @Override
+ public Ice.EndpointInfo getInfo()
+ {
+ return new Ice.OpaqueEndpointInfo(null, -1, false, _rawEncoding, _rawBytes)
+ {
+ @Override
+ public short type()
+ {
+ return _type;
+ }
+
+ @Override
+ public boolean datagram()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return false;
+ }
+ };
+ }
+
+ //
+ // Return the endpoint type
+ //
+ @Override
+ public short type()
+ {
+ return _type;
+ }
+
+ //
+ // Return the protocol name
+ //
+ @Override
+ public String protocol()
+ {
+ return "opaque";
+ }
+
+ //
+ // Return the timeout for the endpoint in milliseconds. 0 means
+ // non-blocking, -1 means no timeout.
+ //
+ @Override
+ public int timeout()
+ {
+ 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.
+ //
+ @Override
+ public EndpointI timeout(int t)
+ {
+ return this;
+ }
+
+ @Override
+ public String connectionId()
+ {
+ return "";
+ }
+
+ //
+ // Return a new endpoint with a different connection id.
+ //
+ @Override
+ public EndpointI connectionId(String connectionId)
+ {
+ return this;
+ }
+
+ //
+ // Return true if the endpoints support bzip2 compress, or false
+ // otherwise.
+ //
+ @Override
+ public boolean compress()
+ {
+ 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.
+ //
+ @Override
+ public EndpointI compress(boolean compress)
+ {
+ return this;
+ }
+
+ //
+ // Return true if the endpoint is datagram-based.
+ //
+ @Override
+ public boolean datagram()
+ {
+ return false;
+ }
+
+ //
+ // Return true if the endpoint is secure.
+ //
+ @Override
+ public boolean secure()
+ {
+ return false;
+ }
+
+ //
+ // Return a server side transceiver for this endpoint, or null if a
+ // transceiver can only be created by an acceptor.d.
+ //
+ @Override
+ public Transceiver transceiver()
+ {
+ return null;
+ }
+
+ //
+ // Return connectors for this endpoint, or empty list if no connector
+ // is available.
+ //
+ @Override
+ public void connectors_async(Ice.EndpointSelectionType selType, EndpointI_connectors callback)
+ {
+ callback.connectors(new java.util.ArrayList<Connector>());
+ }
+
+ //
+ // Return an acceptor for this endpoint, or null if no acceptors
+ // is available.
+ //
+ @Override
+ public Acceptor acceptor(String adapterName)
+ {
+ return null;
+ }
+
+ //
+ // Expand endpoint out in to separate endpoints for each local
+ // host if listening on INADDR_ANY on server side or if no host
+ // was specified on client side.
+ //
+ @Override
+ public java.util.List<EndpointI> expand()
+ {
+ java.util.List<EndpointI> endps = new java.util.ArrayList<EndpointI>();
+ endps.add(this);
+ return endps;
+ }
+
+ //
+ // Check whether the endpoint is equivalent to another one.
+ //
+ @Override
+ public boolean equivalent(EndpointI endpoint)
+ {
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return _hashCode;
+ }
+
+ @Override
+ public String options()
+ {
+ String s = "";
+ if(_type > -1)
+ {
+ s += " -t " + _type;
+ }
+ s += " -e " + Ice.Util.encodingVersionToString(_rawEncoding);
+ if(_rawBytes.length > 0)
+ {
+ s += " -v " + IceUtilInternal.Base64.encode(_rawBytes);
+ }
+ return s;
+ }
+
+ //
+ // Compare endpoints for sorting purposes
+ //
+ @Override
+ public int compareTo(EndpointI obj) // From java.lang.Comparable
+ {
+ if(!(obj instanceof OpaqueEndpointI))
+ {
+ return type() < obj.type() ? -1 : 1;
+ }
+
+ OpaqueEndpointI p = (OpaqueEndpointI)obj;
+ if(this == p)
+ {
+ return 0;
+ }
+
+ if(_type < p._type)
+ {
+ return -1;
+ }
+ else if(p._type < _type)
+ {
+ return 1;
+ }
+
+ if(_rawEncoding.major < p._rawEncoding.major)
+ {
+ return -1;
+ }
+ else if(p._rawEncoding.major < _rawEncoding.major)
+ {
+ return 1;
+ }
+
+ if(_rawEncoding.minor < p._rawEncoding.minor)
+ {
+ return -1;
+ }
+ else if(p._rawEncoding.minor < _rawEncoding.minor)
+ {
+ return 1;
+ }
+
+ if(_rawBytes.length < p._rawBytes.length)
+ {
+ return -1;
+ }
+ else if(p._rawBytes.length < _rawBytes.length)
+ {
+ return 1;
+ }
+ for(int i = 0; i < _rawBytes.length; i++)
+ {
+ if(_rawBytes[i] < p._rawBytes[i])
+ {
+ return -1;
+ }
+ else if(p._rawBytes[i] < _rawBytes[i])
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ @Override
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ switch(option.charAt(1))
+ {
+ case 't':
+ {
+ if(_type > -1)
+ {
+ throw new Ice.EndpointParseException("multiple -t options in endpoint " + endpoint);
+ }
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -t option in endpoint " + endpoint);
+ }
+
+ int t;
+ try
+ {
+ t = Integer.parseInt(argument);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid type value `" + argument + "' in endpoint " + endpoint);
+ }
+
+ if(t < 0 || t > 65535)
+ {
+ throw new Ice.EndpointParseException("type value `" + argument + "' out of range in endpoint " +
+ endpoint);
+ }
+
+ _type = (short)t;
+ return true;
+ }
+
+ case 'v':
+ {
+ if(_rawBytes.length > 0)
+ {
+ throw new Ice.EndpointParseException("multiple -v options in endpoint " + endpoint);
+ }
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -v option in endpoint " + endpoint);
+ }
+
+ for(int j = 0; j < argument.length(); ++j)
+ {
+ if(!IceUtilInternal.Base64.isBase64(argument.charAt(j)))
+ {
+ throw new Ice.EndpointParseException("invalid base64 character `" + argument.charAt(j) +
+ "' (ordinal " + ((int)argument.charAt(j)) +
+ ") in endpoint " + endpoint);
+ }
+ }
+ _rawBytes = IceUtilInternal.Base64.decode(argument);
+ return true;
+ }
+
+ case 'e':
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -e option in endpoint " + endpoint);
+ }
+
+ try
+ {
+ _rawEncoding = Ice.Util.stringToEncodingVersion(argument);
+ }
+ catch(Ice.VersionParseException e)
+ {
+ throw new Ice.EndpointParseException("invalid encoding version `" + argument +
+ "' in endpoint " + endpoint + ":\n" + e.str);
+ }
+ return true;
+ }
+
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+ private void calcHashValue()
+ {
+ int h = 5381;
+ h = IceInternal.HashUtil.hashAdd(h, _type);
+ h = IceInternal.HashUtil.hashAdd(h, _rawEncoding);
+ h = IceInternal.HashUtil.hashAdd(h, _rawBytes);
+ _hashCode = h;
+ }
+
+ private short _type;
+ private Ice.EncodingVersion _rawEncoding;
+ private byte[] _rawBytes;
+ private int _hashCode;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/OutgoingAsync.java b/java-compat/src/Ice/src/main/java/IceInternal/OutgoingAsync.java
new file mode 100644
index 00000000000..85e5522be77
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/OutgoingAsync.java
@@ -0,0 +1,444 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class OutgoingAsync extends ProxyOutgoingAsyncBase
+{
+ public static OutgoingAsync check(Ice.AsyncResult r, Ice.ObjectPrx prx, String operation)
+ {
+ ProxyOutgoingAsyncBase.checkImpl(r, prx, operation);
+ try
+ {
+ return (OutgoingAsync)r;
+ }
+ catch(ClassCastException ex)
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ }
+
+ public OutgoingAsync(Ice.ObjectPrx prx, String operation, CallbackBase cb)
+ {
+ super((Ice.ObjectPrxHelperBase)prx, operation, cb);
+ _encoding = Protocol.getCompatibleEncoding(_proxy.__reference().getEncoding());
+ _is = null;
+ }
+
+ public OutgoingAsync(Ice.ObjectPrx prx, String operation, CallbackBase cb, Ice.InputStream is, Ice.OutputStream os)
+ {
+ super((Ice.ObjectPrxHelperBase)prx, operation, cb, os);
+ _encoding = Protocol.getCompatibleEncoding(_proxy.__reference().getEncoding());
+ _is = is;
+ }
+
+ public void prepare(String operation, Ice.OperationMode mode, java.util.Map<String, String> ctx,
+ boolean explicitCtx, boolean synchronous)
+ {
+ Protocol.checkSupportedProtocol(Protocol.getCompatibleProtocol(_proxy.__reference().getProtocol()));
+
+ _mode = mode;
+ _synchronous = synchronous;
+
+ if(explicitCtx && ctx == null)
+ {
+ ctx = _emptyContext;
+ }
+ _observer = ObserverHelper.get(_proxy, operation, ctx);
+
+ switch(_proxy.__reference().getMode())
+ {
+ case Reference.ModeTwoway:
+ case Reference.ModeOneway:
+ case Reference.ModeDatagram:
+ {
+ _os.writeBlob(IceInternal.Protocol.requestHdr);
+ break;
+ }
+
+ case Reference.ModeBatchOneway:
+ case Reference.ModeBatchDatagram:
+ {
+ _proxy.__getBatchRequestQueue().prepareBatchRequest(_os);
+ break;
+ }
+ }
+
+ Reference ref = _proxy.__reference();
+
+ ref.getIdentity().__write(_os);
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ String facet = ref.getFacet();
+ if(facet == null || facet.length() == 0)
+ {
+ _os.writeStringSeq(null);
+ }
+ else
+ {
+ String[] facetPath = { facet };
+ _os.writeStringSeq(facetPath);
+ }
+
+ _os.writeString(operation);
+
+ _os.writeByte((byte) mode.value());
+
+ if(ctx != null)
+ {
+ //
+ // Explicit context
+ //
+ Ice.ContextHelper.write(_os, ctx);
+ }
+ else
+ {
+ //
+ // Implicit context
+ //
+ Ice.ImplicitContextI implicitContext = ref.getInstance().getImplicitContext();
+ java.util.Map<String, String> prxContext = ref.getContext();
+
+ if(implicitContext == null)
+ {
+ Ice.ContextHelper.write(_os, prxContext);
+ }
+ else
+ {
+ implicitContext.write(prxContext, _os);
+ }
+ }
+ }
+
+ @Override
+ public boolean sent()
+ {
+ return sent(!_proxy.ice_isTwoway()); // done = true if not a two-way proxy (no response expected)
+ }
+
+ @Override
+ public int invokeRemote(Ice.ConnectionI connection, boolean compress, boolean response) throws RetryException
+ {
+ _cachedConnection = connection;
+ return connection.sendAsyncRequest(this, compress, response, 0);
+ }
+
+ @Override
+ public int invokeCollocated(CollocatedRequestHandler handler)
+ {
+ // The stream cannot be cached if the proxy is not a twoway or there is an invocation timeout set.
+ if(!_proxy.ice_isTwoway() || _proxy.__reference().getInvocationTimeout() > 0)
+ {
+ // Disable caching by marking the streams as cached!
+ _state |= StateCachedBuffers;
+ }
+ return handler.invokeAsyncRequest(this, 0, _synchronous);
+ }
+
+ @Override
+ public void abort(Ice.Exception ex)
+ {
+ int mode = _proxy.__reference().getMode();
+ if(mode == Reference.ModeBatchOneway || mode == Reference.ModeBatchDatagram)
+ {
+ //
+ // If we didn't finish a batch oneway or datagram request, we
+ // must notify the connection about that we give up ownership
+ // of the batch stream.
+ //
+ _proxy.__getBatchRequestQueue().abortBatchRequest(_os);
+ }
+
+ super.abort(ex);
+ }
+
+ public void invoke()
+ {
+ int mode = _proxy.__reference().getMode();
+ if(mode == Reference.ModeBatchOneway || mode == Reference.ModeBatchDatagram)
+ {
+ //
+ // NOTE: we don't call sent/completed callbacks for batch AMI requests
+ //
+ _sentSynchronously = true;
+ _proxy.__getBatchRequestQueue().finishBatchRequest(_os, _proxy, getOperation());
+ finished(true);
+ }
+ else
+ {
+ //
+ // NOTE: invokeImpl doesn't throw so this can be called from the
+ // try block with the catch block calling abort() in case of an
+ // exception.
+ //
+ invokeImpl(true); // userThread = true
+ }
+ }
+
+ @Override
+ public final boolean completed(Ice.InputStream is)
+ {
+ //
+ // NOTE: this method is called from ConnectionI.parseMessage
+ // with the connection locked. Therefore, it must not invoke
+ // any user callbacks.
+ //
+
+ assert(_proxy.ice_isTwoway()); // Can only be called for twoways.
+
+ if(_childObserver != null)
+ {
+ _childObserver.reply(is.size() - Protocol.headerSize - 4);
+ _childObserver.detach();
+ _childObserver = null;
+ }
+
+ byte replyStatus;
+ try
+ {
+ // _is can already be initialized if the invocation is retried
+ if(_is == null)
+ {
+ _is = new Ice.InputStream(_instance, IceInternal.Protocol.currentProtocolEncoding);
+ }
+ _is.swap(is);
+ replyStatus = _is.readByte();
+
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyOK:
+ {
+ break;
+ }
+
+ case ReplyStatus.replyUserException:
+ {
+ if(_observer != null)
+ {
+ _observer.userException();
+ }
+ break;
+ }
+
+ case ReplyStatus.replyObjectNotExist:
+ case ReplyStatus.replyFacetNotExist:
+ case ReplyStatus.replyOperationNotExist:
+ {
+ Ice.Identity id = new Ice.Identity();
+ id.__read(_is);
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ String[] facetPath = _is.readStringSeq();
+ String facet;
+ if(facetPath.length > 0)
+ {
+ if(facetPath.length > 1)
+ {
+ throw new Ice.MarshalException();
+ }
+ facet = facetPath[0];
+ }
+ else
+ {
+ facet = "";
+ }
+
+ String operation = _is.readString();
+
+ Ice.RequestFailedException ex = null;
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyObjectNotExist:
+ {
+ ex = new Ice.ObjectNotExistException();
+ break;
+ }
+
+ case ReplyStatus.replyFacetNotExist:
+ {
+ ex = new Ice.FacetNotExistException();
+ break;
+ }
+
+ case ReplyStatus.replyOperationNotExist:
+ {
+ ex = new Ice.OperationNotExistException();
+ break;
+ }
+
+ default:
+ {
+ assert(false);
+ break;
+ }
+ }
+
+ ex.id = id;
+ ex.facet = facet;
+ ex.operation = operation;
+ throw ex;
+ }
+
+ case ReplyStatus.replyUnknownException:
+ case ReplyStatus.replyUnknownLocalException:
+ case ReplyStatus.replyUnknownUserException:
+ {
+ String unknown = _is.readString();
+
+ Ice.UnknownException ex = null;
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyUnknownException:
+ {
+ ex = new Ice.UnknownException();
+ break;
+ }
+
+ case ReplyStatus.replyUnknownLocalException:
+ {
+ ex = new Ice.UnknownLocalException();
+ break;
+ }
+
+ case ReplyStatus.replyUnknownUserException:
+ {
+ ex = new Ice.UnknownUserException();
+ break;
+ }
+
+ default:
+ {
+ assert(false);
+ break;
+ }
+ }
+
+ ex.unknown = unknown;
+ throw ex;
+ }
+
+ default:
+ {
+ throw new Ice.UnknownReplyStatusException();
+ }
+ }
+
+ return finished(replyStatus == ReplyStatus.replyOK);
+ }
+ catch(Ice.Exception ex)
+ {
+ return completed(ex);
+ }
+ }
+
+ public Ice.OutputStream startWriteParams(Ice.FormatType format)
+ {
+ _os.startEncapsulation(_encoding, format);
+ return _os;
+ }
+
+ public void endWriteParams()
+ {
+ _os.endEncapsulation();
+ }
+
+ public void writeEmptyParams()
+ {
+ _os.writeEmptyEncapsulation(_encoding);
+ }
+
+ public void writeParamEncaps(byte[] encaps)
+ {
+ if(encaps == null || encaps.length == 0)
+ {
+ _os.writeEmptyEncapsulation(_encoding);
+ }
+ else
+ {
+ _os.writeEncapsulation(encaps);
+ }
+ }
+
+ public Ice.InputStream startReadParams()
+ {
+ _is.startEncapsulation();
+ return _is;
+ }
+
+ public void endReadParams()
+ {
+ _is.endEncapsulation();
+ }
+
+ public void readEmptyParams()
+ {
+ _is.skipEmptyEncapsulation();
+ }
+
+ public byte[] readParamEncaps()
+ {
+ return _is.readEncapsulation(null);
+ }
+
+ public final void throwUserException()
+ throws Ice.UserException
+ {
+ try
+ {
+ _is.startEncapsulation();
+ _is.throwException(null);
+ }
+ catch(Ice.UserException ex)
+ {
+ _is.endEncapsulation();
+ throw ex;
+ }
+ }
+
+ @Override
+ public void cacheMessageBuffers()
+ {
+ if(_proxy.__reference().getInstance().cacheMessageBuffers() > 0)
+ {
+ synchronized(this)
+ {
+ if((_state & StateCachedBuffers) > 0)
+ {
+ return;
+ }
+ _state |= StateCachedBuffers;
+ }
+
+ if(_is != null)
+ {
+ _is.reset();
+ }
+ _os.reset();
+
+ _proxy.cacheMessageBuffers(_is, _os);
+
+ _is = null;
+ _os = null;
+ }
+ }
+
+ final private Ice.EncodingVersion _encoding;
+ private Ice.InputStream _is;
+
+ //
+ // If true this AMI request is being used for a generated synchronous invocation.
+ //
+ private boolean _synchronous;
+
+ private static final java.util.Map<String, String> _emptyContext = new java.util.HashMap<String, String>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/OutgoingAsyncBase.java b/java-compat/src/Ice/src/main/java/IceInternal/OutgoingAsyncBase.java
new file mode 100644
index 00000000000..7af12ad2912
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/OutgoingAsyncBase.java
@@ -0,0 +1,107 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+//
+// Base class for handling asynchronous invocations. This class is
+// responsible for the handling of the output stream and the child
+// invocation observer.
+//
+public abstract class OutgoingAsyncBase extends IceInternal.AsyncResultI
+{
+ public boolean sent()
+ {
+ return sent(true);
+ }
+
+ public boolean completed(Ice.InputStream is)
+ {
+ assert(false); // Must be implemented by classes that handle responses
+ return false;
+ }
+
+ public boolean completed(Ice.Exception ex)
+ {
+ return finished(ex);
+ }
+
+ public final void attachRemoteObserver(Ice.ConnectionInfo info, Ice.Endpoint endpt, int requestId)
+ {
+ if(_observer != null)
+ {
+ final int size = _os.size() - IceInternal.Protocol.headerSize - 4;
+ _childObserver = getObserver().getRemoteObserver(info, endpt, requestId, size);
+ if(_childObserver != null)
+ {
+ _childObserver.attach();
+ }
+ }
+ }
+
+ public final void attachCollocatedObserver(Ice.ObjectAdapter adapter, int requestId)
+ {
+ if(_observer != null)
+ {
+ final int size = _os.size() - IceInternal.Protocol.headerSize - 4;
+ _childObserver = getObserver().getCollocatedObserver(adapter, requestId, size);
+ if(_childObserver != null)
+ {
+ _childObserver.attach();
+ }
+ }
+ }
+
+ public final Ice.OutputStream getOs()
+ {
+ return _os;
+ }
+
+ protected OutgoingAsyncBase(Ice.Communicator com, Instance instance, String op, CallbackBase del)
+ {
+ super(com, instance, op, del);
+ _os = new Ice.OutputStream(instance, Protocol.currentProtocolEncoding);
+ }
+
+ protected OutgoingAsyncBase(Ice.Communicator com, Instance instance, String op, CallbackBase del,
+ Ice.OutputStream os)
+ {
+ super(com, instance, op, del);
+ _os = os;
+ }
+
+ @Override
+ protected boolean sent(boolean done)
+ {
+ if(done)
+ {
+ if(_childObserver != null)
+ {
+ _childObserver.detach();
+ _childObserver = null;
+ }
+ }
+ return super.sent(done);
+ }
+
+ @Override
+ protected boolean finished(Ice.Exception ex)
+ {
+ if(_childObserver != null)
+ {
+ _childObserver.failed(ex.ice_id());
+ _childObserver.detach();
+ _childObserver = null;
+ }
+ return super.finished(ex);
+ }
+
+ protected Ice.OutputStream _os;
+ protected Ice.Instrumentation.ChildInvocationObserver _childObserver;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/OutgoingConnectionFactory.java b/java-compat/src/Ice/src/main/java/IceInternal/OutgoingConnectionFactory.java
new file mode 100644
index 00000000000..94b80c0e2fb
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/OutgoingConnectionFactory.java
@@ -0,0 +1,1149 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class OutgoingConnectionFactory
+{
+ //
+ // Helper class to multi hash map.
+ //
+ private static class MultiHashMap<K, V> extends java.util.HashMap<K, java.util.List<V>>
+ {
+ public void
+ putOne(K key, V value)
+ {
+ java.util.List<V> list = this.get(key);
+ if(list == null)
+ {
+ list = new java.util.LinkedList<V>();
+ this.put(key, list);
+ }
+ list.add(value);
+ }
+
+ public boolean
+ removeElementWithValue(K key, V value)
+ {
+ java.util.List<V> list = this.get(key);
+ assert(list != null);
+ boolean v = list.remove(value);
+ if(list.isEmpty())
+ {
+ this.remove(key);
+ }
+ return v;
+ }
+ }
+
+ interface CreateConnectionCallback
+ {
+ void setConnection(Ice.ConnectionI connection, boolean compress);
+ void setException(Ice.LocalException ex);
+ }
+
+ public synchronized void
+ destroy()
+ {
+ if(_destroyed)
+ {
+ return;
+ }
+
+ for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
+ {
+ for(Ice.ConnectionI connection : connectionList)
+ {
+ connection.destroy(Ice.ConnectionI.CommunicatorDestroyed);
+ }
+ }
+
+ _destroyed = true;
+ _communicator = null;
+ notifyAll();
+ }
+
+ public synchronized void
+ updateConnectionObservers()
+ {
+ for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
+ {
+ for(Ice.ConnectionI connection : connectionList)
+ {
+ connection.updateObserver();
+ }
+ }
+ }
+
+ // Called from Instance.destroy().
+ public void
+ waitUntilFinished()
+ {
+ java.util.Map<Connector, java.util.List<Ice.ConnectionI> > connections = null;
+ synchronized(this)
+ {
+ //
+ // First we wait until the factory is destroyed. We also
+ // wait until there are no pending connections
+ // anymore. Only then we can be sure the _connections
+ // contains all connections.
+ //
+ while(!_destroyed || !_pending.isEmpty() || _pendingConnectCount > 0)
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+
+ //
+ // We want to wait until all connections are finished outside the
+ // thread synchronization.
+ //
+ connections = new java.util.HashMap<Connector, java.util.List<Ice.ConnectionI> >(_connections);
+ }
+
+ //
+ // Now we wait until the destruction of each connection is finished.
+ //
+ for(java.util.List<Ice.ConnectionI> connectionList : connections.values())
+ {
+ for(Ice.ConnectionI connection : connectionList)
+ {
+ try
+ {
+ connection.waitUntilFinished();
+ }
+ catch(InterruptedException e)
+ {
+ //
+ // Force close all of the connections.
+ //
+ for(java.util.List<Ice.ConnectionI> l : connections.values())
+ {
+ for(Ice.ConnectionI c : l)
+ {
+ c.close(true);
+ }
+ }
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+ }
+
+ synchronized(this)
+ {
+ // Ensure all the connections are finished and reapable at this point.
+ java.util.List<Ice.ConnectionI> cons = _monitor.swapReapedConnections();
+ if(cons != null)
+ {
+ int size = 0;
+ for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
+ {
+ size += connectionList.size();
+ }
+ assert(cons.size() == size);
+ _connections.clear();
+ _connectionsByEndpoint.clear();
+ }
+ else
+ {
+ assert(_connections.isEmpty());
+ assert(_connectionsByEndpoint.isEmpty());
+ }
+ _monitor.destroy();
+ }
+ }
+
+ public void
+ create(EndpointI[] endpts, boolean hasMore, Ice.EndpointSelectionType selType, CreateConnectionCallback callback)
+ {
+ assert(endpts.length > 0);
+
+ //
+ // Apply the overrides.
+ //
+ java.util.List<EndpointI> endpoints = applyOverrides(endpts);
+
+ //
+ // Try to find a connection to one of the given endpoints.
+ //
+ try
+ {
+ Ice.Holder<Boolean> compress = new Ice.Holder<Boolean>();
+ Ice.ConnectionI connection = findConnectionByEndpoint(endpoints, compress);
+ if(connection != null)
+ {
+ callback.setConnection(connection, compress.value);
+ return;
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ callback.setException(ex);
+ return;
+ }
+
+ ConnectCallback cb = new ConnectCallback(this, endpoints, hasMore, callback, selType);
+ cb.getConnectors();
+ }
+
+ public synchronized void
+ setRouterInfo(IceInternal.RouterInfo routerInfo)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ assert(routerInfo != null);
+
+ //
+ // 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.
+ //
+ Ice.ObjectAdapter adapter = routerInfo.getAdapter();
+ DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+ for(EndpointI endpoint : routerInfo.getClientEndpoints())
+ {
+ //
+ // Modify endpoints with overrides.
+ //
+ if(defaultsAndOverrides.overrideTimeout)
+ {
+ endpoint = endpoint.timeout(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.compress(false);
+
+ for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
+ {
+ for(Ice.ConnectionI connection : connectionList)
+ {
+ if(connection.endpoint() == endpoint)
+ {
+ connection.setAdapter(adapter);
+ }
+ }
+ }
+ }
+ }
+
+ public synchronized void
+ removeAdapter(Ice.ObjectAdapter adapter)
+ {
+ if(_destroyed)
+ {
+ return;
+ }
+
+ for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
+ {
+ for(Ice.ConnectionI connection : connectionList)
+ {
+ if(connection.getAdapter() == adapter)
+ {
+ connection.setAdapter(null);
+ }
+ }
+ }
+ }
+
+ public void
+ flushAsyncBatchRequests(CommunicatorFlushBatch outAsync)
+ {
+ java.util.List<Ice.ConnectionI> c = new java.util.LinkedList<Ice.ConnectionI>();
+
+ synchronized(this)
+ {
+ if(!_destroyed)
+ {
+ for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
+ {
+ for(Ice.ConnectionI connection : connectionList)
+ {
+ if(connection.isActiveOrHolding())
+ {
+ c.add(connection);
+ }
+ }
+ }
+ }
+ }
+
+ for(Ice.ConnectionI conn : c)
+ {
+ try
+ {
+ outAsync.flushConnection(conn);
+ }
+ catch(Ice.LocalException ex)
+ {
+ // Ignore.
+ }
+ }
+ }
+
+ //
+ // Only for use by Instance.
+ //
+ OutgoingConnectionFactory(Ice.Communicator communicator, Instance instance)
+ {
+ _communicator = communicator;
+ _instance = instance;
+ _monitor = new FactoryACMMonitor(instance, instance.clientACM());
+ _destroyed = false;
+ }
+
+ @Override
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_destroyed);
+ IceUtilInternal.Assert.FinalizerAssert(_connections.isEmpty());
+ IceUtilInternal.Assert.FinalizerAssert(_connectionsByEndpoint.isEmpty());
+ IceUtilInternal.Assert.FinalizerAssert(_pendingConnectCount == 0);
+ IceUtilInternal.Assert.FinalizerAssert(_pending.isEmpty());
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ private java.util.List<EndpointI>
+ applyOverrides(EndpointI[] endpts)
+ {
+ DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+ java.util.List<EndpointI> endpoints = new java.util.ArrayList<EndpointI>();
+ for(EndpointI endpoint : endpts)
+ {
+ //
+ // Modify endpoints with overrides.
+ //
+ if(defaultsAndOverrides.overrideTimeout)
+ {
+ endpoints.add(endpoint.timeout(defaultsAndOverrides.overrideTimeoutValue));
+ }
+ else
+ {
+ endpoints.add(endpoint);
+ }
+ }
+
+ return endpoints;
+ }
+
+ synchronized private Ice.ConnectionI
+ findConnectionByEndpoint(java.util.List<EndpointI> endpoints, Ice.Holder<Boolean> compress)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+ assert(!endpoints.isEmpty());
+
+ for(EndpointI endpoint : endpoints)
+ {
+ java.util.List<Ice.ConnectionI> connectionList = _connectionsByEndpoint.get(endpoint);
+ if(connectionList == null)
+ {
+ continue;
+ }
+
+ for(Ice.ConnectionI connection : connectionList)
+ {
+ if(connection.isActiveOrHolding()) // Don't return destroyed or un-validated connections
+ {
+ if(defaultsAndOverrides.overrideCompress)
+ {
+ compress.value = defaultsAndOverrides.overrideCompressValue;
+ }
+ else
+ {
+ compress.value = endpoint.compress();
+ }
+ return connection;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ //
+ // Must be called while synchronized.
+ //
+ private Ice.ConnectionI
+ findConnection(java.util.List<ConnectorInfo> connectors, Ice.Holder<Boolean> compress)
+ {
+ DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+ for(ConnectorInfo ci : connectors)
+ {
+ if(_pending.containsKey(ci.connector))
+ {
+ continue;
+ }
+
+ java.util.List<Ice.ConnectionI> connectionList = _connections.get(ci.connector);
+ if(connectionList == null)
+ {
+ continue;
+ }
+
+ for(Ice.ConnectionI connection : connectionList)
+ {
+ if(connection.isActiveOrHolding()) // Don't return destroyed or un-validated connections
+ {
+ if(defaultsAndOverrides.overrideCompress)
+ {
+ compress.value = defaultsAndOverrides.overrideCompressValue;
+ }
+ else
+ {
+ compress.value = ci.endpoint.compress();
+ }
+ return connection;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ synchronized private void
+ incPendingConnectCount()
+ {
+ //
+ // 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(_destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+ ++_pendingConnectCount;
+ }
+
+ synchronized private void
+ decPendingConnectCount()
+ {
+ --_pendingConnectCount;
+ assert(_pendingConnectCount >= 0);
+ if(_destroyed && _pendingConnectCount == 0)
+ {
+ notifyAll();
+ }
+ }
+
+ private Ice.ConnectionI
+ getConnection(java.util.List<ConnectorInfo> connectors, ConnectCallback cb, Ice.Holder<Boolean> compress)
+ {
+ assert(cb != null);
+ synchronized(this)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ //
+ // Reap closed connections
+ //
+ java.util.List<Ice.ConnectionI> cons = _monitor.swapReapedConnections();
+ if(cons != null)
+ {
+ for(Ice.ConnectionI c : cons)
+ {
+ _connections.removeElementWithValue(c.connector(), c);
+ _connectionsByEndpoint.removeElementWithValue(c.endpoint(), c);
+ _connectionsByEndpoint.removeElementWithValue(c.endpoint().compress(true), c);
+ }
+ }
+
+ //
+ // Try to get the connection. We may need to wait for other threads to
+ // finish if one of them is currently establishing a connection to one
+ // of our connectors.
+ //
+ while(true)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ //
+ // Search for a matching connection. If we find one, we're done.
+ //
+ Ice.ConnectionI connection = findConnection(connectors, compress);
+ if(connection != null)
+ {
+ return connection;
+ }
+
+ if(addToPending(cb, connectors))
+ {
+ return null;
+ }
+ else
+ {
+ //
+ // If no thread is currently establishing a connection to one of our connectors,
+ // we get out of this loop and start the connection establishment to one of the
+ // given connectors.
+ //
+ break;
+ }
+ }
+ }
+
+ //
+ // At this point, we're responsible for establishing the connection to one of
+ // the given connectors. If it's a non-blocking connect, calling nextConnector
+ // will start the connection establishment. Otherwise, we return null to get
+ // the caller to establish the connection.
+ //
+ if(cb != null)
+ {
+ cb.nextConnector();
+ }
+
+ return null;
+ }
+
+ private synchronized Ice.ConnectionI
+ createConnection(Transceiver transceiver, ConnectorInfo ci)
+ {
+ assert(_pending.containsKey(ci.connector) && 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.
+ //
+ Ice.ConnectionI connection = null;
+ try
+ {
+ if(_destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+
+ connection = new Ice.ConnectionI(_communicator, _instance, _monitor, transceiver, ci.connector,
+ ci.endpoint.compress(false), null);
+ }
+ catch(Ice.LocalException ex)
+ {
+ try
+ {
+ transceiver.close();
+ }
+ catch(Ice.LocalException exc)
+ {
+ // Ignore
+ }
+ throw ex;
+ }
+
+ _connections.putOne(ci.connector, connection);
+ _connectionsByEndpoint.putOne(connection.endpoint(), connection);
+ _connectionsByEndpoint.putOne(connection.endpoint().compress(true), connection);
+ return connection;
+ }
+
+ private void
+ finishGetConnection(java.util.List<ConnectorInfo> connectors,
+ ConnectorInfo ci,
+ Ice.ConnectionI connection,
+ ConnectCallback cb)
+ {
+ java.util.Set<ConnectCallback> connectionCallbacks = new java.util.HashSet<ConnectCallback>();
+ if(cb != null)
+ {
+ connectionCallbacks.add(cb);
+ }
+
+ java.util.Set<ConnectCallback> callbacks = new java.util.HashSet<ConnectCallback>();
+ synchronized(this)
+ {
+ for(ConnectorInfo c : connectors)
+ {
+ java.util.Set<ConnectCallback> cbs = _pending.remove(c.connector);
+ if(cbs != null)
+ {
+ for(ConnectCallback cc : cbs)
+ {
+ if(cc.hasConnector(ci))
+ {
+ connectionCallbacks.add(cc);
+ }
+ else
+ {
+ callbacks.add(cc);
+ }
+ }
+ }
+ }
+
+ for(ConnectCallback cc : connectionCallbacks)
+ {
+ cc.removeFromPending();
+ callbacks.remove(cc);
+ }
+ for(ConnectCallback cc : callbacks)
+ {
+ cc.removeFromPending();
+ }
+ notifyAll();
+ }
+
+ boolean compress;
+ DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideCompress)
+ {
+ compress = defaultsAndOverrides.overrideCompressValue;
+ }
+ else
+ {
+ compress = ci.endpoint.compress();
+ }
+
+ for(ConnectCallback cc : callbacks)
+ {
+ cc.getConnection();
+ }
+ for(ConnectCallback cc : connectionCallbacks)
+ {
+ cc.setConnection(connection, compress);
+ }
+ }
+
+ private void
+ finishGetConnection(java.util.List<ConnectorInfo> connectors, Ice.LocalException ex, ConnectCallback cb)
+ {
+ java.util.Set<ConnectCallback> failedCallbacks = new java.util.HashSet<ConnectCallback>();
+ if(cb != null)
+ {
+ failedCallbacks.add(cb);
+ }
+
+ java.util.Set<ConnectCallback> callbacks = new java.util.HashSet<ConnectCallback>();
+ synchronized(this)
+ {
+ for(ConnectorInfo c : connectors)
+ {
+ java.util.Set<ConnectCallback> cbs = _pending.remove(c.connector);
+ if(cbs != null)
+ {
+ for(ConnectCallback cc : cbs)
+ {
+ if(cc.removeConnectors(connectors))
+ {
+ failedCallbacks.add(cc);
+ }
+ else
+ {
+ callbacks.add(cc);
+ }
+ }
+ }
+ }
+
+ for(ConnectCallback cc : callbacks)
+ {
+ assert(!failedCallbacks.contains(cc));
+ cc.removeFromPending();
+ }
+ notifyAll();
+ }
+
+ for(ConnectCallback cc : callbacks)
+ {
+ cc.getConnection();
+ }
+ for(ConnectCallback cc : failedCallbacks)
+ {
+ cc.setException(ex);
+ }
+ }
+
+ private boolean
+ addToPending(ConnectCallback cb, java.util.List<ConnectorInfo> connectors)
+ {
+ //
+ // Add the callback to each connector pending list.
+ //
+ boolean found = false;
+ for(ConnectorInfo p : connectors)
+ {
+ java.util.Set<ConnectCallback> cbs = _pending.get(p.connector);
+ if(cbs != null)
+ {
+ found = true;
+ if(cb != null)
+ {
+ cbs.add(cb); // Add the callback to each pending connector.
+ }
+ }
+ }
+
+ if(found)
+ {
+ return true;
+ }
+
+ //
+ // If there's no pending connection for the given connectors, we're
+ // responsible for its establishment. We add empty pending lists,
+ // other callbacks to the same connectors will be queued.
+ //
+ for(ConnectorInfo p : connectors)
+ {
+ if(!_pending.containsKey(p.connector))
+ {
+ _pending.put(p.connector, new java.util.HashSet<ConnectCallback>());
+ }
+ }
+
+ return false;
+ }
+
+ private void
+ removeFromPending(ConnectCallback cb, java.util.List<ConnectorInfo> connectors)
+ {
+ for(ConnectorInfo p : connectors)
+ {
+ java.util.Set<ConnectCallback> cbs = _pending.get(p.connector);
+ if(cbs != null)
+ {
+ cbs.remove(cb);
+ }
+ }
+ }
+
+ private void
+ handleConnectionException(Ice.LocalException ex, boolean hasMore)
+ {
+ TraceLevels traceLevels = _instance.traceLevels();
+ if(traceLevels.retry >= 2)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("connection to endpoint failed");
+ if(ex instanceof Ice.CommunicatorDestroyedException)
+ {
+ s.append("\n");
+ }
+ else
+ {
+ if(hasMore)
+ {
+ s.append(", trying next endpoint\n");
+ }
+ else
+ {
+ s.append(" and no more endpoints to try\n");
+ }
+ }
+ s.append(ex.toString());
+ _instance.initializationData().logger.trace(traceLevels.retryCat, s.toString());
+ }
+ }
+
+ private void
+ handleException(Ice.LocalException ex, boolean hasMore)
+ {
+ TraceLevels traceLevels = _instance.traceLevels();
+ if(traceLevels.retry >= 2)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("couldn't resolve endpoint host");
+ if(ex instanceof Ice.CommunicatorDestroyedException)
+ {
+ s.append("\n");
+ }
+ else
+ {
+ if(hasMore)
+ {
+ s.append(", trying next endpoint\n");
+ }
+ else
+ {
+ s.append(" and no more endpoints to try\n");
+ }
+ }
+ s.append(ex.toString());
+ _instance.initializationData().logger.trace(traceLevels.retryCat, s.toString());
+ }
+ }
+
+ private static class ConnectorInfo
+ {
+ public ConnectorInfo(Connector c, EndpointI e)
+ {
+ connector = c;
+ endpoint = e;
+ }
+
+ @Override
+ public boolean
+ equals(Object obj)
+ {
+ ConnectorInfo r = (ConnectorInfo)obj;
+ return connector.equals(r.connector);
+ }
+
+ @Override
+ public int
+ hashCode()
+ {
+ return connector.hashCode();
+ }
+
+ public Connector connector;
+ public EndpointI endpoint;
+ }
+
+ private static class ConnectCallback implements Ice.ConnectionI.StartCallback, EndpointI_connectors
+ {
+ ConnectCallback(OutgoingConnectionFactory f, java.util.List<EndpointI> endpoints, boolean more,
+ CreateConnectionCallback cb, Ice.EndpointSelectionType selType)
+ {
+ _factory = f;
+ _endpoints = endpoints;
+ _hasMore = more;
+ _callback = cb;
+ _selType = selType;
+ _endpointsIter = _endpoints.iterator();
+ }
+
+ //
+ // Methods from ConnectionI.StartCallback
+ //
+ @Override
+ public void
+ connectionStartCompleted(Ice.ConnectionI connection)
+ {
+ if(_observer != null)
+ {
+ _observer.detach();
+ }
+ connection.activate();
+ _factory.finishGetConnection(_connectors, _current, connection, this);
+ }
+
+ @Override
+ public void
+ connectionStartFailed(Ice.ConnectionI connection, Ice.LocalException ex)
+ {
+ assert(_current != null);
+ if(connectionStartFailedImpl(ex))
+ {
+ nextConnector();
+ }
+ }
+
+ //
+ // Methods from EndpointI_connectors
+ //
+ @Override
+ public void
+ connectors(java.util.List<Connector> cons)
+ {
+ for(Connector p : cons)
+ {
+ _connectors.add(new ConnectorInfo(p, _currentEndpoint));
+ }
+
+ if(_endpointsIter.hasNext())
+ {
+ nextEndpoint();
+ }
+ else
+ {
+ assert(!_connectors.isEmpty());
+
+ //
+ // We now have all the connectors for the given endpoints. We can try to obtain the
+ // connection.
+ //
+ _iter = _connectors.iterator();
+ getConnection();
+ }
+ }
+
+ @Override
+ public void
+ exception(Ice.LocalException ex)
+ {
+ _factory.handleException(ex, _hasMore || _endpointsIter.hasNext());
+ if(_endpointsIter.hasNext())
+ {
+ nextEndpoint();
+ }
+ else if(!_connectors.isEmpty())
+ {
+ //
+ // We now have all the connectors for the given endpoints. We can try to obtain the
+ // connection.
+ //
+ _iter = _connectors.iterator();
+ getConnection();
+ }
+ else
+ {
+ _callback.setException(ex);
+ _factory.decPendingConnectCount(); // Must be called last.
+ }
+ }
+
+ void
+ setConnection(Ice.ConnectionI connection, boolean compress)
+ {
+ //
+ // Callback from the factory: the connection to one of the callback
+ // connectors has been established.
+ //
+ _callback.setConnection(connection, compress);
+ _factory.decPendingConnectCount(); // Must be called last.
+ }
+
+ void
+ setException(Ice.LocalException ex)
+ {
+ //
+ // Callback from the factory: connection establishment failed.
+ //
+ _callback.setException(ex);
+ _factory.decPendingConnectCount(); // Must be called last.
+ }
+
+ boolean
+ hasConnector(ConnectorInfo ci)
+ {
+ return _connectors.contains(ci);
+ }
+
+ boolean
+ removeConnectors(java.util.List<ConnectorInfo> connectors)
+ {
+ _connectors.removeAll(connectors);
+ _iter = _connectors.iterator();
+ return _connectors.isEmpty();
+ }
+
+ void
+ removeFromPending()
+ {
+ _factory.removeFromPending(this, _connectors);
+ }
+
+ private void
+ getConnectors()
+ {
+ 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.
+ //
+ _factory.incPendingConnectCount();
+ }
+ catch(Ice.LocalException ex)
+ {
+ _callback.setException(ex);
+ return;
+ }
+
+ nextEndpoint();
+ }
+
+ private void
+ nextEndpoint()
+ {
+ try
+ {
+ assert(_endpointsIter.hasNext());
+ _currentEndpoint = _endpointsIter.next();
+ _currentEndpoint.connectors_async(_selType, this);
+ }
+ catch(Ice.LocalException ex)
+ {
+ exception(ex);
+ }
+ }
+
+ private void
+ getConnection()
+ {
+ try
+ {
+ //
+ // If all the connectors have been created, we ask the factory to get a
+ // connection.
+ //
+ Ice.Holder<Boolean> compress = new Ice.Holder<Boolean>();
+ Ice.ConnectionI connection = _factory.getConnection(_connectors, this, compress);
+ if(connection == null)
+ {
+ //
+ // A null return value from getConnection indicates that the connection
+ // is being established and that everything has been done to ensure that
+ // the callback will be notified when the connection establishment is
+ // done.
+ //
+ return;
+ }
+
+ _callback.setConnection(connection, compress.value);
+ _factory.decPendingConnectCount(); // Must be called last.
+ }
+ catch(Ice.LocalException ex)
+ {
+ _callback.setException(ex);
+ _factory.decPendingConnectCount(); // Must be called last.
+ }
+ }
+
+ private void
+ nextConnector()
+ {
+ while(true)
+ {
+ try
+ {
+ assert(_iter.hasNext());
+ _current = _iter.next();
+
+ Ice.Instrumentation.CommunicatorObserver obsv = _factory._instance.initializationData().observer;
+ if(obsv != null)
+ {
+ _observer = obsv.getConnectionEstablishmentObserver(_current.endpoint,
+ _current.connector.toString());
+ if(_observer != null)
+ {
+ _observer.attach();
+ }
+ }
+
+ if(_factory._instance.traceLevels().network >= 2)
+ {
+ StringBuffer s = new StringBuffer("trying to establish ");
+ s.append(_current.endpoint.protocol());
+ s.append(" connection to ");
+ s.append(_current.connector.toString());
+ _factory._instance.initializationData().logger.trace(_factory._instance.traceLevels().networkCat,
+ s.toString());
+ }
+
+ Ice.ConnectionI connection = _factory.createConnection(_current.connector.connect(), _current);
+ connection.start(this);
+ }
+ catch(Ice.LocalException ex)
+ {
+ if(_factory._instance.traceLevels().network >= 2)
+ {
+ StringBuffer s = new StringBuffer("failed to establish ");
+ s.append(_current.endpoint.protocol());
+ s.append(" connection to ");
+ s.append(_current.connector.toString());
+ s.append("\n");
+ s.append(ex);
+ _factory._instance.initializationData().logger.trace(_factory._instance.traceLevels().networkCat,
+ s.toString());
+ }
+
+ if(connectionStartFailedImpl(ex))
+ {
+ continue;
+ }
+ }
+ break;
+ }
+ }
+
+ private boolean
+ connectionStartFailedImpl(Ice.LocalException ex)
+ {
+ if(_observer != null)
+ {
+ _observer.failed(ex.ice_id());
+ _observer.detach();
+ }
+
+ _factory.handleConnectionException(ex, _hasMore || _iter.hasNext());
+ if(ex instanceof Ice.CommunicatorDestroyedException) // No need to continue.
+ {
+ _factory.finishGetConnection(_connectors, ex, this);
+ }
+ else if(_iter.hasNext()) // Try the next connector.
+ {
+ return true;
+ }
+ else
+ {
+ _factory.finishGetConnection(_connectors, ex, this);
+ }
+ return false;
+ }
+
+ private final OutgoingConnectionFactory _factory;
+ private final boolean _hasMore;
+ private final CreateConnectionCallback _callback;
+ private final java.util.List<EndpointI> _endpoints;
+ private final Ice.EndpointSelectionType _selType;
+ private java.util.Iterator<EndpointI> _endpointsIter;
+ private EndpointI _currentEndpoint;
+ private java.util.List<ConnectorInfo> _connectors = new java.util.ArrayList<ConnectorInfo>();
+ private java.util.Iterator<ConnectorInfo> _iter;
+ private ConnectorInfo _current;
+ private Ice.Instrumentation.Observer _observer;
+ }
+
+ private Ice.Communicator _communicator;
+ private final Instance _instance;
+ private final FactoryACMMonitor _monitor;
+ private boolean _destroyed;
+
+ private MultiHashMap<Connector, Ice.ConnectionI> _connections = new MultiHashMap<Connector, Ice.ConnectionI>();
+ private MultiHashMap<EndpointI, Ice.ConnectionI> _connectionsByEndpoint =
+ new MultiHashMap<EndpointI, Ice.ConnectionI>();
+ private java.util.Map<Connector, java.util.HashSet<ConnectCallback> > _pending =
+ new java.util.HashMap<Connector, java.util.HashSet<ConnectCallback> >();
+ private int _pendingConnectCount = 0;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/OutputStreamWrapper.java b/java-compat/src/Ice/src/main/java/IceInternal/OutputStreamWrapper.java
new file mode 100644
index 00000000000..6f9e2f9a9d6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/OutputStreamWrapper.java
@@ -0,0 +1,178 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.io.*;
+
+//
+// Class to provide a java.io.OutputStream on top of our stream.
+// We use this to serialize arbitrary Java serializable classes into
+//
+// Slice sequences are encoded on the wire as a count of elements, followed
+// by the sequence contents. For arbitrary Java classes, we do not know how
+// big the sequence that is eventually written will be. To avoid excessive
+// data copying, this class mantains a private _bytes array of 254 bytes and,
+// initially, writes data into that array. If more than 254 bytes end up being
+// written, we write a dummy sequence size of 255 (which occupies five bytes
+// on the wire) into the stream and, once this stream is closed, patch
+// that size to match the actual size. Otherwise, if the _bytes buffer contains
+// fewer than 255 bytes when this stream is closed, we write the sequence size
+// as a single byte, followed by the contents of the _bytes buffer.
+//
+
+public class OutputStreamWrapper extends java.io.OutputStream
+{
+ public
+ OutputStreamWrapper(Ice.OutputStream s)
+ {
+ _s = s;
+ _spos = s.pos();
+ _bytes = new byte[254];
+ _pos = 0;
+ }
+
+ @Override
+ public void
+ write(int b) throws IOException
+ {
+ try
+ {
+ if(_bytes != null)
+ {
+ //
+ // If we can fit the data into the first 254 bytes, write it to _bytes.
+ //
+ if(_pos < _bytes.length)
+ {
+ _bytes[_pos++] = (byte)b;
+ return;
+ }
+
+ _s.writeSize(255); // Dummy size, until we know how big the stream
+ // really is and can patch the size.
+
+ if(_pos > 0)
+ {
+ //
+ // Write the current contents of _bytes.
+ //
+ _s.expand(_pos);
+ _s.getBuffer().b.put(_bytes, 0, _pos);
+ }
+ _bytes = null;
+ }
+
+ //
+ // Write data passed by caller.
+ //
+ _s.expand(1);
+ _s.getBuffer().b.put((byte)b);
+ _pos += 1;
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new IOException(ex.toString());
+ }
+ }
+
+ @Override
+ public void
+ write(byte[] b) throws IOException
+ {
+ write(b, 0, b.length);
+ }
+
+ @Override
+ public void
+ write(byte[] bytes, int offset, int count) throws IOException
+ {
+ try
+ {
+ if(_bytes != null)
+ {
+ //
+ // If we can fit the data into the first 254 bytes, write it to _bytes.
+ //
+ if(count <= _bytes.length - _pos)
+ {
+ System.arraycopy(bytes, offset, _bytes, _pos, count);
+ _pos += count;
+ return;
+ }
+
+ _s.writeSize(255); // Dummy size, until we know how big the stream
+ // really is and can patch the size.
+
+ if(_pos > 0)
+ {
+ //
+ // Write the current contents of _bytes.
+ //
+ _s.expand(_pos);
+ _s.getBuffer().b.put(_bytes, 0, _pos);
+ }
+ _bytes = null;
+ }
+
+ //
+ // Write data passed by caller.
+ //
+ _s.expand(count);
+ _s.getBuffer().b.put(bytes, offset, count);
+ _pos += count;
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new IOException(ex.toString());
+ }
+ }
+
+ @Override
+ public void
+ flush() throws IOException
+ {
+ // This does nothing because we do not know the final size of a writable stream until it is closed,
+ // and we cannot write to the stream until we know whether the final size is < 255 or not.
+ }
+
+ @Override
+ public void
+ close() throws IOException
+ {
+ try
+ {
+ if(_bytes != null)
+ {
+ assert(_pos <= _bytes.length);
+ _s.pos(_spos);
+ _s.writeSize(_pos);
+ _s.expand(_pos);
+ _s.getBuffer().b.put(_bytes, 0, _pos);
+ _bytes = null;
+ }
+ else
+ {
+ int currentPos = _s.pos();
+ _s.pos(_spos);
+ _s.writeSize(_pos); // Patch previously-written dummy value.
+ _s.pos(currentPos);
+ }
+ }
+ catch(java.lang.Exception ex)
+ {
+ throw new IOException(ex.toString());
+ }
+ }
+
+ private Ice.OutputStream _s;
+ private int _spos;
+ private byte[] _bytes;
+ private int _pos;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ProcessI.java b/java-compat/src/Ice/src/main/java/IceInternal/ProcessI.java
new file mode 100644
index 00000000000..516d5f03aa9
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ProcessI.java
@@ -0,0 +1,46 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ProcessI extends Ice._ProcessDisp
+{
+ public ProcessI(Ice.Communicator communicator)
+ {
+ _communicator = communicator;
+ }
+
+ @Override
+ public void
+ shutdown(Ice.Current current)
+ {
+ _communicator.shutdown();
+ }
+
+ @Override
+ public void
+ writeMessage(String message, int fd, Ice.Current current)
+ {
+ switch(fd)
+ {
+ case 1:
+ {
+ System.out.println(message);
+ break;
+ }
+ case 2:
+ {
+ System.err.println(message);
+ break;
+ }
+ }
+ }
+
+ private Ice.Communicator _communicator;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/PropertiesAdminI.java b/java-compat/src/Ice/src/main/java/IceInternal/PropertiesAdminI.java
new file mode 100644
index 00000000000..b6041ba4fd6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/PropertiesAdminI.java
@@ -0,0 +1,214 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+class PropertiesAdminI extends Ice._PropertiesAdminDisp implements Ice.NativePropertiesAdmin
+{
+ public PropertiesAdminI(Instance instance)
+ {
+ _properties = instance.initializationData().properties;
+ _logger = instance.initializationData().logger;
+ }
+
+ @Override
+ public synchronized String
+ getProperty(String name, Ice.Current current)
+ {
+ return _properties.getProperty(name);
+ }
+
+ @Override
+ public synchronized java.util.TreeMap<String, String>
+ getPropertiesForPrefix(String name, Ice.Current current)
+ {
+ return new java.util.TreeMap<String, String>(_properties.getPropertiesForPrefix(name));
+ }
+
+ @Override
+ synchronized public void setProperties(java.util.Map<String, String> props, Ice.Current current)
+ {
+ java.util.Map<String, String> old = _properties.getPropertiesForPrefix("");
+ final int traceLevel = _properties.getPropertyAsInt("Ice.Trace.Admin.Properties");
+
+ //
+ // Compute the difference between the new property set and the existing property set:
+ //
+ // 1) Any properties in the new set that were not defined in the existing set.
+ //
+ // 2) Any properties that appear in both sets but with different values.
+ //
+ // 3) Any properties not present in the new set but present in the existing set.
+ // In other words, the property has been removed.
+ //
+ java.util.Map<String, String> added = new java.util.HashMap<String, String>();
+ java.util.Map<String, String> changed = new java.util.HashMap<String, String>();
+ java.util.Map<String, String> removed = new java.util.HashMap<String, String>();
+ for(java.util.Map.Entry<String, String> e : props.entrySet())
+ {
+ final String key = e.getKey();
+ final String value = e.getValue();
+ if(!old.containsKey(key))
+ {
+ if(value.length() > 0)
+ {
+ //
+ // This property is new.
+ //
+ added.put(key, value);
+ }
+ }
+ else
+ {
+ if(!value.equals(old.get(key)))
+ {
+ if(value.length() == 0)
+ {
+ //
+ // This property was removed.
+ //
+ removed.put(key, value);
+ }
+ else
+ {
+ //
+ // This property has changed.
+ //
+ changed.put(key, value);
+ }
+ }
+
+ old.remove(key);
+ }
+ }
+
+ if(traceLevel > 0 && (!added.isEmpty() || !changed.isEmpty() || !removed.isEmpty()))
+ {
+ StringBuilder out = new StringBuilder(128);
+ out.append("Summary of property changes");
+
+ if(!added.isEmpty())
+ {
+ out.append("\nNew properties:");
+ for(java.util.Map.Entry<String, String> e : added.entrySet())
+ {
+ out.append("\n ");
+ out.append(e.getKey());
+ if(traceLevel > 1)
+ {
+ out.append(" = ");
+ out.append(e.getValue());
+ }
+ }
+ }
+
+ if(!changed.isEmpty())
+ {
+ out.append("\nChanged properties:");
+ for(java.util.Map.Entry<String, String> e : changed.entrySet())
+ {
+ out.append("\n ");
+ out.append(e.getKey());
+ if(traceLevel > 1)
+ {
+ out.append(" = ");
+ out.append(e.getValue());
+ out.append(" (old value = ");
+ out.append(_properties.getProperty(e.getKey()));
+ out.append(")");
+ }
+ }
+ }
+
+ if(!removed.isEmpty())
+ {
+ out.append("\nRemoved properties:");
+ for(java.util.Map.Entry<String, String> e : removed.entrySet())
+ {
+ out.append("\n ");
+ out.append(e.getKey());
+ }
+ }
+
+ _logger.trace(_traceCategory, out.toString());
+ }
+
+ //
+ // Update the property set.
+ //
+
+ for(java.util.Map.Entry<String, String> e : added.entrySet())
+ {
+ _properties.setProperty(e.getKey(), e.getValue());
+ }
+
+ for(java.util.Map.Entry<String, String> e : changed.entrySet())
+ {
+ _properties.setProperty(e.getKey(), e.getValue());
+ }
+
+ for(java.util.Map.Entry<String, String> e : removed.entrySet())
+ {
+ _properties.setProperty(e.getKey(), "");
+ }
+
+ if(!_updateCallbacks.isEmpty())
+ {
+ java.util.Map<String, String> changes = new java.util.HashMap<String, String>(added);
+ changes.putAll(changed);
+ changes.putAll(removed);
+
+ //
+ // Copy the callbacks to allow callbacks to update the callbacks.
+ //
+ java.util.List<Ice.PropertiesAdminUpdateCallback> callbacks =
+ new java.util.ArrayList<Ice.PropertiesAdminUpdateCallback>(_updateCallbacks);
+ for(Ice.PropertiesAdminUpdateCallback callback : callbacks)
+ {
+ try
+ {
+ callback.updated(changes);
+ }
+ catch(java.lang.Exception ex)
+ {
+ if(_properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 1)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ _logger.warning("properties admin update callback raised unexpected exception:\n" +
+ sw.toString());
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public synchronized void
+ addUpdateCallback (Ice.PropertiesAdminUpdateCallback cb)
+ {
+ _updateCallbacks.add(cb);
+ }
+
+ @Override
+ public synchronized void
+ removeUpdateCallback(Ice.PropertiesAdminUpdateCallback cb)
+ {
+ _updateCallbacks.remove(cb);
+ }
+
+ private final Ice.Properties _properties;
+ private final Ice.Logger _logger;
+ private java.util.List<Ice.PropertiesAdminUpdateCallback> _updateCallbacks =
+ new java.util.ArrayList<Ice.PropertiesAdminUpdateCallback>();
+
+ static private final String _traceCategory = "Admin.Properties";
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Property.java b/java-compat/src/Ice/src/main/java/IceInternal/Property.java
new file mode 100644
index 00000000000..3d8395c0289
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Property.java
@@ -0,0 +1,42 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class Property
+{
+ public Property(String pattern, boolean deprecated, String deprecatedBy)
+ {
+ _pattern = pattern;
+ _deprecated = deprecated;
+ _deprecatedBy = deprecatedBy;
+ }
+
+ public String
+ pattern()
+ {
+ return _pattern;
+ }
+
+ public boolean
+ deprecated()
+ {
+ return _deprecated;
+ }
+
+ public String
+ deprecatedBy()
+ {
+ return _deprecatedBy;
+ }
+
+ private String _pattern;
+ private boolean _deprecated;
+ private String _deprecatedBy;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java b/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java
new file mode 100644
index 00000000000..78fca903d04
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java
@@ -0,0 +1,1254 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Aug 18 20:28:56 2016
+
+// IMPORTANT: Do not edit this file -- any edits made here will be lost!
+
+package IceInternal;
+
+public final class PropertyNames
+{
+ public static final Property IceProps[] =
+ {
+ new Property("Ice\\.ACM\\.Client", true, null),
+ new Property("Ice\\.ACM\\.Server", true, null),
+ new Property("Ice\\.ACM\\.Timeout", false, null),
+ new Property("Ice\\.ACM\\.Heartbeat", false, null),
+ new Property("Ice\\.ACM\\.Close", false, null),
+ new Property("Ice\\.ACM", false, null),
+ new Property("Ice\\.ACM\\.Client\\.Timeout", false, null),
+ new Property("Ice\\.ACM\\.Client\\.Heartbeat", false, null),
+ new Property("Ice\\.ACM\\.Client\\.Close", false, null),
+ new Property("Ice\\.ACM\\.Client", false, null),
+ new Property("Ice\\.ACM\\.Server\\.Timeout", false, null),
+ new Property("Ice\\.ACM\\.Server\\.Heartbeat", false, null),
+ new Property("Ice\\.ACM\\.Server\\.Close", false, null),
+ new Property("Ice\\.ACM\\.Server", false, null),
+ new Property("Ice\\.Admin\\.ACM\\.Timeout", false, null),
+ new Property("Ice\\.Admin\\.ACM\\.Heartbeat", false, null),
+ new Property("Ice\\.Admin\\.ACM\\.Close", 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\\.InvocationTimeout", 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\\.Context\\.[^\\s]+", 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\\.InvocationTimeout", 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\\.Context\\.[^\\s]+", 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\\.MessageSizeMax", false, null),
+ new Property("Ice\\.Admin\\.DelayCreation", false, null),
+ new Property("Ice\\.Admin\\.Enabled", false, null),
+ new Property("Ice\\.Admin\\.Facets", false, null),
+ new Property("Ice\\.Admin\\.InstanceName", false, null),
+ new Property("Ice\\.Admin\\.Logger\\.KeepLogs", false, null),
+ new Property("Ice\\.Admin\\.Logger\\.KeepTraces", false, null),
+ new Property("Ice\\.Admin\\.Logger\\.Properties", false, null),
+ new Property("Ice\\.Admin\\.ServerId", false, null),
+ new Property("Ice\\.BackgroundLocatorCacheUpdates", false, null),
+ new Property("Ice\\.BatchAutoFlush", true, null),
+ new Property("Ice\\.BatchAutoFlushSize", false, null),
+ new Property("Ice\\.ChangeUser", false, null),
+ new Property("Ice\\.ClientAccessPolicyProtocol", false, null),
+ new Property("Ice\\.Compression\\.Level", false, null),
+ new Property("Ice\\.CollectObjects", 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\\.InvocationTimeout", 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\\.Context\\.[^\\s]+", false, null),
+ new Property("Ice\\.Default\\.Locator", false, null),
+ new Property("Ice\\.Default\\.LocatorCacheTimeout", false, null),
+ new Property("Ice\\.Default\\.InvocationTimeout", 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\\.InvocationTimeout", 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\\.Context\\.[^\\s]+", false, null),
+ new Property("Ice\\.Default\\.Router", false, null),
+ new Property("Ice\\.Default\\.SlicedFormat", false, null),
+ new Property("Ice\\.Default\\.SourceAddress", false, null),
+ new Property("Ice\\.Default\\.Timeout", false, null),
+ new Property("Ice\\.EventLog\\.Source", false, null),
+ new Property("Ice\\.FactoryAssemblies", false, null),
+ new Property("Ice\\.HTTPProxyHost", false, null),
+ new Property("Ice\\.HTTPProxyPort", false, null),
+ new Property("Ice\\.ImplicitContext", false, null),
+ new Property("Ice\\.InitPlugins", false, null),
+ new Property("Ice\\.IPv4", false, null),
+ new Property("Ice\\.IPv6", false, null),
+ new Property("Ice\\.LogFile", false, null),
+ new Property("Ice\\.LogFile\\.SizeMax", false, null),
+ new Property("Ice\\.LogStdErr\\.Convert", false, null),
+ new Property("Ice\\.MessageSizeMax", 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\\.[^\\s]+", false, null),
+ new Property("Ice\\.Plugin\\.[^\\s]+", 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\\.Admin\\.Logger", 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),
+ new Property("Ice\\.ThreadInterruptSafe", false, null),
+ new Property("Ice\\.Voip", false, null),
+ null
+ };
+
+ public static final Property IceMXProps[] =
+ {
+ new Property("IceMX\\.Metrics\\.[^\\s]+\\.GroupBy", false, null),
+ new Property("IceMX\\.Metrics\\.[^\\s]+\\.Map", false, null),
+ new Property("IceMX\\.Metrics\\.[^\\s]+\\.RetainDetached", false, null),
+ new Property("IceMX\\.Metrics\\.[^\\s]+\\.Accept", false, null),
+ new Property("IceMX\\.Metrics\\.[^\\s]+\\.Reject", false, null),
+ new Property("IceMX\\.Metrics\\.[^\\s]+", false, null),
+ null
+ };
+
+ public static final Property IceDiscoveryProps[] =
+ {
+ new Property("IceDiscovery\\.Multicast\\.ACM\\.Timeout", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ACM\\.Heartbeat", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ACM\\.Close", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ACM", false, null),
+ new Property("IceDiscovery\\.Multicast\\.AdapterId", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Endpoints", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Locator\\.PreferSecure", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Locator\\.Locator", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Locator\\.Router", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Locator", false, null),
+ new Property("IceDiscovery\\.Multicast\\.PublishedEndpoints", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ReplicaGroupId", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Router\\.EndpointSelection", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Router\\.ConnectionCached", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Router\\.PreferSecure", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Router\\.Locator", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Router\\.Router", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceDiscovery\\.Multicast\\.Router", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ProxyOptions", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ThreadPool\\.Size", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceDiscovery\\.Multicast\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceDiscovery\\.Multicast\\.MessageSizeMax", false, null),
+ new Property("IceDiscovery\\.Reply\\.ACM\\.Timeout", false, null),
+ new Property("IceDiscovery\\.Reply\\.ACM\\.Heartbeat", false, null),
+ new Property("IceDiscovery\\.Reply\\.ACM\\.Close", false, null),
+ new Property("IceDiscovery\\.Reply\\.ACM", false, null),
+ new Property("IceDiscovery\\.Reply\\.AdapterId", false, null),
+ new Property("IceDiscovery\\.Reply\\.Endpoints", false, null),
+ new Property("IceDiscovery\\.Reply\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceDiscovery\\.Reply\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceDiscovery\\.Reply\\.Locator\\.PreferSecure", false, null),
+ new Property("IceDiscovery\\.Reply\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceDiscovery\\.Reply\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceDiscovery\\.Reply\\.Locator\\.Locator", false, null),
+ new Property("IceDiscovery\\.Reply\\.Locator\\.Router", false, null),
+ new Property("IceDiscovery\\.Reply\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceDiscovery\\.Reply\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceDiscovery\\.Reply\\.Locator", false, null),
+ new Property("IceDiscovery\\.Reply\\.PublishedEndpoints", false, null),
+ new Property("IceDiscovery\\.Reply\\.ReplicaGroupId", false, null),
+ new Property("IceDiscovery\\.Reply\\.Router\\.EndpointSelection", false, null),
+ new Property("IceDiscovery\\.Reply\\.Router\\.ConnectionCached", false, null),
+ new Property("IceDiscovery\\.Reply\\.Router\\.PreferSecure", false, null),
+ new Property("IceDiscovery\\.Reply\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceDiscovery\\.Reply\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceDiscovery\\.Reply\\.Router\\.Locator", false, null),
+ new Property("IceDiscovery\\.Reply\\.Router\\.Router", false, null),
+ new Property("IceDiscovery\\.Reply\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceDiscovery\\.Reply\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceDiscovery\\.Reply\\.Router", false, null),
+ new Property("IceDiscovery\\.Reply\\.ProxyOptions", false, null),
+ new Property("IceDiscovery\\.Reply\\.ThreadPool\\.Size", false, null),
+ new Property("IceDiscovery\\.Reply\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceDiscovery\\.Reply\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceDiscovery\\.Reply\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceDiscovery\\.Reply\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceDiscovery\\.Reply\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceDiscovery\\.Reply\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceDiscovery\\.Reply\\.MessageSizeMax", false, null),
+ new Property("IceDiscovery\\.Locator\\.ACM\\.Timeout", false, null),
+ new Property("IceDiscovery\\.Locator\\.ACM\\.Heartbeat", false, null),
+ new Property("IceDiscovery\\.Locator\\.ACM\\.Close", false, null),
+ new Property("IceDiscovery\\.Locator\\.ACM", false, null),
+ new Property("IceDiscovery\\.Locator\\.AdapterId", false, null),
+ new Property("IceDiscovery\\.Locator\\.Endpoints", false, null),
+ new Property("IceDiscovery\\.Locator\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceDiscovery\\.Locator\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceDiscovery\\.Locator\\.Locator\\.PreferSecure", false, null),
+ new Property("IceDiscovery\\.Locator\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceDiscovery\\.Locator\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceDiscovery\\.Locator\\.Locator\\.Locator", false, null),
+ new Property("IceDiscovery\\.Locator\\.Locator\\.Router", false, null),
+ new Property("IceDiscovery\\.Locator\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceDiscovery\\.Locator\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceDiscovery\\.Locator\\.Locator", false, null),
+ new Property("IceDiscovery\\.Locator\\.PublishedEndpoints", false, null),
+ new Property("IceDiscovery\\.Locator\\.ReplicaGroupId", false, null),
+ new Property("IceDiscovery\\.Locator\\.Router\\.EndpointSelection", false, null),
+ new Property("IceDiscovery\\.Locator\\.Router\\.ConnectionCached", false, null),
+ new Property("IceDiscovery\\.Locator\\.Router\\.PreferSecure", false, null),
+ new Property("IceDiscovery\\.Locator\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceDiscovery\\.Locator\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceDiscovery\\.Locator\\.Router\\.Locator", false, null),
+ new Property("IceDiscovery\\.Locator\\.Router\\.Router", false, null),
+ new Property("IceDiscovery\\.Locator\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceDiscovery\\.Locator\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceDiscovery\\.Locator\\.Router", false, null),
+ new Property("IceDiscovery\\.Locator\\.ProxyOptions", false, null),
+ new Property("IceDiscovery\\.Locator\\.ThreadPool\\.Size", false, null),
+ new Property("IceDiscovery\\.Locator\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceDiscovery\\.Locator\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceDiscovery\\.Locator\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceDiscovery\\.Locator\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceDiscovery\\.Locator\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceDiscovery\\.Locator\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceDiscovery\\.Locator\\.MessageSizeMax", false, null),
+ new Property("IceDiscovery\\.Lookup", false, null),
+ new Property("IceDiscovery\\.Timeout", false, null),
+ new Property("IceDiscovery\\.RetryCount", false, null),
+ new Property("IceDiscovery\\.LatencyMultiplier", false, null),
+ new Property("IceDiscovery\\.Address", false, null),
+ new Property("IceDiscovery\\.Port", false, null),
+ new Property("IceDiscovery\\.Interface", false, null),
+ new Property("IceDiscovery\\.DomainId", false, null),
+ null
+ };
+
+ public static final Property IceGridDiscoveryProps[] =
+ {
+ new Property("IceGridDiscovery\\.Reply\\.ACM\\.Timeout", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ACM\\.Close", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ACM", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.AdapterId", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Endpoints", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Locator\\.Locator", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Locator\\.Router", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Locator", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.PublishedEndpoints", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ReplicaGroupId", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Router\\.PreferSecure", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Router\\.Locator", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Router\\.Router", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.Router", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ProxyOptions", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ThreadPool\\.Size", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGridDiscovery\\.Reply\\.MessageSizeMax", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ACM\\.Timeout", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ACM\\.Close", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ACM", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.AdapterId", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Endpoints", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Locator\\.Locator", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Locator\\.Router", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Locator", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.PublishedEndpoints", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ReplicaGroupId", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Router\\.PreferSecure", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Router\\.Locator", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Router\\.Router", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.Router", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ProxyOptions", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ThreadPool\\.Size", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGridDiscovery\\.Locator\\.MessageSizeMax", false, null),
+ new Property("IceGridDiscovery\\.Lookup", false, null),
+ new Property("IceGridDiscovery\\.Timeout", false, null),
+ new Property("IceGridDiscovery\\.RetryCount", false, null),
+ new Property("IceGridDiscovery\\.RetryDelay", false, null),
+ new Property("IceGridDiscovery\\.Address", false, null),
+ new Property("IceGridDiscovery\\.Port", false, null),
+ new Property("IceGridDiscovery\\.Interface", false, null),
+ new Property("IceGridDiscovery\\.InstanceName", false, null),
+ null
+ };
+
+ public static final Property IceBoxProps[] =
+ {
+ new Property("IceBox\\.InheritProperties", false, null),
+ new Property("IceBox\\.InstanceName", true, null),
+ new Property("IceBox\\.LoadOrder", false, null),
+ new Property("IceBox\\.PrintServicesReady", false, null),
+ new Property("IceBox\\.Service\\.[^\\s]+", false, null),
+ new Property("IceBox\\.ServiceManager\\.AdapterId", true, null),
+ new Property("IceBox\\.ServiceManager\\.Endpoints", true, null),
+ new Property("IceBox\\.ServiceManager\\.Locator", true, null),
+ new Property("IceBox\\.ServiceManager\\.PublishedEndpoints", true, null),
+ new Property("IceBox\\.ServiceManager\\.ReplicaGroupId", true, null),
+ new Property("IceBox\\.ServiceManager\\.Router", true, null),
+ new Property("IceBox\\.ServiceManager\\.ThreadPool\\.Size", true, null),
+ new Property("IceBox\\.ServiceManager\\.ThreadPool\\.SizeMax", true, null),
+ new Property("IceBox\\.ServiceManager\\.ThreadPool\\.SizeWarn", true, null),
+ new Property("IceBox\\.ServiceManager\\.ThreadPool\\.StackSize", true, null),
+ new Property("IceBox\\.Trace\\.ServiceObserver", false, null),
+ new Property("IceBox\\.UseSharedCommunicator\\.[^\\s]+", false, null),
+ null
+ };
+
+ public static final Property IceBoxAdminProps[] =
+ {
+ new Property("IceBoxAdmin\\.ServiceManager\\.Proxy\\.EndpointSelection", false, null),
+ new Property("IceBoxAdmin\\.ServiceManager\\.Proxy\\.ConnectionCached", false, null),
+ new Property("IceBoxAdmin\\.ServiceManager\\.Proxy\\.PreferSecure", false, null),
+ new Property("IceBoxAdmin\\.ServiceManager\\.Proxy\\.LocatorCacheTimeout", false, null),
+ new Property("IceBoxAdmin\\.ServiceManager\\.Proxy\\.InvocationTimeout", false, null),
+ new Property("IceBoxAdmin\\.ServiceManager\\.Proxy\\.Locator", false, null),
+ new Property("IceBoxAdmin\\.ServiceManager\\.Proxy\\.Router", false, null),
+ new Property("IceBoxAdmin\\.ServiceManager\\.Proxy\\.CollocationOptimized", false, null),
+ new Property("IceBoxAdmin\\.ServiceManager\\.Proxy\\.Context\\.[^\\s]+", false, null),
+ new Property("IceBoxAdmin\\.ServiceManager\\.Proxy", false, null),
+ null
+ };
+
+ public static final Property IceGridAdminProps[] =
+ {
+ new Property("IceGridAdmin\\.AuthenticateUsingSSL", false, null),
+ new Property("IceGridAdmin\\.MetricsConfig", false, null),
+ new Property("IceGridAdmin\\.Username", false, null),
+ new Property("IceGridAdmin\\.Password", false, null),
+ new Property("IceGridAdmin\\.Replica", false, null),
+ new Property("IceGridAdmin\\.Host", false, null),
+ new Property("IceGridAdmin\\.Port", false, null),
+ new Property("IceGridAdmin\\.InstanceName", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Address", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Interface", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Lookup", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ACM\\.Timeout", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ACM\\.Close", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ACM", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.AdapterId", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Endpoints", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Locator\\.Locator", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Locator\\.Router", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Locator", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.PublishedEndpoints", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ReplicaGroupId", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Router\\.PreferSecure", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Router\\.Locator", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Router\\.Router", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.Router", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ProxyOptions", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.Size", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGridAdmin\\.Discovery\\.Reply\\.MessageSizeMax", false, null),
+ new Property("IceGridAdmin\\.Trace\\.Observers", false, null),
+ new Property("IceGridAdmin\\.Trace\\.SaveToRegistry", false, null),
+ null
+ };
+
+ public static final Property IceGridProps[] =
+ {
+ new Property("IceGrid\\.AdminRouter\\.ACM\\.Timeout", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ACM\\.Close", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ACM", false, null),
+ new Property("IceGrid\\.AdminRouter\\.AdapterId", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Endpoints", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Locator\\.Locator", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Locator\\.Router", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Locator", false, null),
+ new Property("IceGrid\\.AdminRouter\\.PublishedEndpoints", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ReplicaGroupId", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Router\\.PreferSecure", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Router\\.Locator", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Router\\.Router", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.AdminRouter\\.Router", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ProxyOptions", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ThreadPool\\.Size", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGrid\\.AdminRouter\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGrid\\.AdminRouter\\.MessageSizeMax", false, null),
+ new Property("IceGrid\\.InstanceName", false, null),
+ new Property("IceGrid\\.Node\\.ACM\\.Timeout", false, null),
+ new Property("IceGrid\\.Node\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGrid\\.Node\\.ACM\\.Close", false, null),
+ new Property("IceGrid\\.Node\\.ACM", false, null),
+ new Property("IceGrid\\.Node\\.AdapterId", false, null),
+ new Property("IceGrid\\.Node\\.Endpoints", false, null),
+ new Property("IceGrid\\.Node\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Node\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Node\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Node\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Node\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Node\\.Locator\\.Locator", false, null),
+ new Property("IceGrid\\.Node\\.Locator\\.Router", false, null),
+ new Property("IceGrid\\.Node\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Node\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Node\\.Locator", false, null),
+ new Property("IceGrid\\.Node\\.PublishedEndpoints", false, null),
+ new Property("IceGrid\\.Node\\.ReplicaGroupId", false, null),
+ new Property("IceGrid\\.Node\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Node\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Node\\.Router\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Node\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Node\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Node\\.Router\\.Locator", false, null),
+ new Property("IceGrid\\.Node\\.Router\\.Router", false, null),
+ new Property("IceGrid\\.Node\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Node\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Node\\.Router", false, null),
+ new Property("IceGrid\\.Node\\.ProxyOptions", false, null),
+ new Property("IceGrid\\.Node\\.ThreadPool\\.Size", false, null),
+ new Property("IceGrid\\.Node\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGrid\\.Node\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGrid\\.Node\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGrid\\.Node\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGrid\\.Node\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGrid\\.Node\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGrid\\.Node\\.MessageSizeMax", false, null),
+ new Property("IceGrid\\.Node\\.AllowRunningServersAsRoot", false, null),
+ new Property("IceGrid\\.Node\\.AllowEndpointsOverride", false, null),
+ new Property("IceGrid\\.Node\\.CollocateRegistry", false, null),
+ new Property("IceGrid\\.Node\\.Data", false, null),
+ new Property("IceGrid\\.Node\\.DisableOnFailure", false, null),
+ new Property("IceGrid\\.Node\\.Name", false, null),
+ new Property("IceGrid\\.Node\\.Output", false, null),
+ new Property("IceGrid\\.Node\\.ProcessorSocketCount", false, null),
+ new Property("IceGrid\\.Node\\.PrintServersReady", false, null),
+ new Property("IceGrid\\.Node\\.PropertiesOverride", false, null),
+ new Property("IceGrid\\.Node\\.RedirectErrToOut", false, null),
+ new Property("IceGrid\\.Node\\.Trace\\.Activator", false, null),
+ new Property("IceGrid\\.Node\\.Trace\\.Adapter", false, null),
+ new Property("IceGrid\\.Node\\.Trace\\.Patch", false, null),
+ new Property("IceGrid\\.Node\\.Trace\\.Replica", false, null),
+ new Property("IceGrid\\.Node\\.Trace\\.Server", false, null),
+ new Property("IceGrid\\.Node\\.UserAccounts", false, null),
+ new Property("IceGrid\\.Node\\.UserAccountMapper\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Node\\.UserAccountMapper\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Node\\.UserAccountMapper\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Node\\.UserAccountMapper\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Node\\.UserAccountMapper\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Node\\.UserAccountMapper\\.Locator", false, null),
+ new Property("IceGrid\\.Node\\.UserAccountMapper\\.Router", false, null),
+ new Property("IceGrid\\.Node\\.UserAccountMapper\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Node\\.UserAccountMapper\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Node\\.UserAccountMapper", false, null),
+ new Property("IceGrid\\.Node\\.WaitTime", false, null),
+ new Property("IceGrid\\.Registry\\.AdminCryptPasswords", false, null),
+ new Property("IceGrid\\.Registry\\.AdminPermissionsVerifier\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.AdminPermissionsVerifier\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.AdminPermissionsVerifier\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.AdminPermissionsVerifier\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.AdminPermissionsVerifier\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.AdminPermissionsVerifier\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.AdminPermissionsVerifier\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.AdminPermissionsVerifier\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.AdminPermissionsVerifier\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.AdminPermissionsVerifier", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionFilters", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ACM\\.Timeout", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ACM\\.Close", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ACM", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.AdapterId", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Endpoints", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Locator\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Locator\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.PublishedEndpoints", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ReplicaGroupId", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Router\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Router\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Router\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ProxyOptions", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ThreadPool\\.Size", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSessionManager\\.MessageSizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSSLPermissionsVerifier\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSSLPermissionsVerifier\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSSLPermissionsVerifier\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSSLPermissionsVerifier\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSSLPermissionsVerifier\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSSLPermissionsVerifier\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSSLPermissionsVerifier\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSSLPermissionsVerifier\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSSLPermissionsVerifier\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.AdminSSLPermissionsVerifier", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ACM\\.Timeout", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ACM\\.Close", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ACM", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.AdapterId", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Endpoints", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Locator\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Locator\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.PublishedEndpoints", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ReplicaGroupId", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Router\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Router\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Router\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ProxyOptions", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ThreadPool\\.Size", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGrid\\.Registry\\.Client\\.MessageSizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.CryptPasswords", false, null),
+ new Property("IceGrid\\.Registry\\.DefaultTemplates", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ACM\\.Timeout", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ACM\\.Close", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ACM", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.AdapterId", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Endpoints", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Locator\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Locator\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.PublishedEndpoints", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ReplicaGroupId", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Router\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Router\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Router\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ProxyOptions", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ThreadPool\\.Size", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.MessageSizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Enabled", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Address", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Port", false, null),
+ new Property("IceGrid\\.Registry\\.Discovery\\.Interface", false, null),
+ new Property("IceGrid\\.Registry\\.DynamicRegistration", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ACM\\.Timeout", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ACM\\.Close", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ACM", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.AdapterId", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Endpoints", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Locator\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Locator\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.PublishedEndpoints", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ReplicaGroupId", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Router\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Router\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Router\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ProxyOptions", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ThreadPool\\.Size", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGrid\\.Registry\\.Internal\\.MessageSizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.LMDB\\.MapSize", false, null),
+ new Property("IceGrid\\.Registry\\.LMDB\\.Path", false, null),
+ new Property("IceGrid\\.Registry\\.NodeSessionTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.PermissionsVerifier\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.PermissionsVerifier\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.PermissionsVerifier\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.PermissionsVerifier\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.PermissionsVerifier\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.PermissionsVerifier\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.PermissionsVerifier\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.PermissionsVerifier\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.PermissionsVerifier\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.PermissionsVerifier", false, null),
+ new Property("IceGrid\\.Registry\\.ReplicaName", false, null),
+ new Property("IceGrid\\.Registry\\.ReplicaSessionTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.RequireNodeCertCN", false, null),
+ new Property("IceGrid\\.Registry\\.RequireReplicaCertCN", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ACM\\.Timeout", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ACM\\.Close", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ACM", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.AdapterId", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Endpoints", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Locator\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Locator\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.PublishedEndpoints", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ReplicaGroupId", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Router\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Router\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Router\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ProxyOptions", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ThreadPool\\.Size", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGrid\\.Registry\\.Server\\.MessageSizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.SessionFilters", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ACM\\.Timeout", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ACM\\.Heartbeat", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ACM\\.Close", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ACM", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.AdapterId", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Endpoints", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Locator\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Locator\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Locator\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Locator\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Locator\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.PublishedEndpoints", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ReplicaGroupId", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Router\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Router\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Router\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Router\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Router\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Router\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Router\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ProxyOptions", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ThreadPool\\.Size", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ThreadPool\\.StackSize", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ThreadPool\\.Serialize", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IceGrid\\.Registry\\.SessionManager\\.MessageSizeMax", false, null),
+ new Property("IceGrid\\.Registry\\.SessionTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.SSLPermissionsVerifier\\.EndpointSelection", false, null),
+ new Property("IceGrid\\.Registry\\.SSLPermissionsVerifier\\.ConnectionCached", false, null),
+ new Property("IceGrid\\.Registry\\.SSLPermissionsVerifier\\.PreferSecure", false, null),
+ new Property("IceGrid\\.Registry\\.SSLPermissionsVerifier\\.LocatorCacheTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.SSLPermissionsVerifier\\.InvocationTimeout", false, null),
+ new Property("IceGrid\\.Registry\\.SSLPermissionsVerifier\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.SSLPermissionsVerifier\\.Router", false, null),
+ new Property("IceGrid\\.Registry\\.SSLPermissionsVerifier\\.CollocationOptimized", false, null),
+ new Property("IceGrid\\.Registry\\.SSLPermissionsVerifier\\.Context\\.[^\\s]+", false, null),
+ new Property("IceGrid\\.Registry\\.SSLPermissionsVerifier", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Application", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Adapter", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Locator", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Node", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Object", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Patch", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Replica", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Server", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Session", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Subscriber", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.Topic", false, null),
+ new Property("IceGrid\\.Registry\\.Trace\\.TopicManager", false, null),
+ new Property("IceGrid\\.Registry\\.UserAccounts", false, null),
+ null
+ };
+
+ public static final Property IcePatch2Props[] =
+ {
+ new Property("IcePatch2\\.ACM\\.Timeout", false, null),
+ new Property("IcePatch2\\.ACM\\.Heartbeat", false, null),
+ new Property("IcePatch2\\.ACM\\.Close", false, null),
+ new Property("IcePatch2\\.ACM", false, null),
+ new Property("IcePatch2\\.AdapterId", false, null),
+ new Property("IcePatch2\\.Endpoints", false, null),
+ new Property("IcePatch2\\.Locator\\.EndpointSelection", false, null),
+ new Property("IcePatch2\\.Locator\\.ConnectionCached", false, null),
+ new Property("IcePatch2\\.Locator\\.PreferSecure", false, null),
+ new Property("IcePatch2\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("IcePatch2\\.Locator\\.InvocationTimeout", false, null),
+ new Property("IcePatch2\\.Locator\\.Locator", false, null),
+ new Property("IcePatch2\\.Locator\\.Router", false, null),
+ new Property("IcePatch2\\.Locator\\.CollocationOptimized", false, null),
+ new Property("IcePatch2\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("IcePatch2\\.Locator", false, null),
+ new Property("IcePatch2\\.PublishedEndpoints", false, null),
+ new Property("IcePatch2\\.ReplicaGroupId", false, null),
+ new Property("IcePatch2\\.Router\\.EndpointSelection", false, null),
+ new Property("IcePatch2\\.Router\\.ConnectionCached", false, null),
+ new Property("IcePatch2\\.Router\\.PreferSecure", false, null),
+ new Property("IcePatch2\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("IcePatch2\\.Router\\.InvocationTimeout", false, null),
+ new Property("IcePatch2\\.Router\\.Locator", false, null),
+ new Property("IcePatch2\\.Router\\.Router", false, null),
+ new Property("IcePatch2\\.Router\\.CollocationOptimized", false, null),
+ new Property("IcePatch2\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("IcePatch2\\.Router", false, null),
+ new Property("IcePatch2\\.ProxyOptions", false, null),
+ new Property("IcePatch2\\.ThreadPool\\.Size", false, null),
+ new Property("IcePatch2\\.ThreadPool\\.SizeMax", false, null),
+ new Property("IcePatch2\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("IcePatch2\\.ThreadPool\\.StackSize", false, null),
+ new Property("IcePatch2\\.ThreadPool\\.Serialize", false, null),
+ new Property("IcePatch2\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("IcePatch2\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("IcePatch2\\.MessageSizeMax", false, null),
+ new Property("IcePatch2\\.Directory", false, null),
+ new Property("IcePatch2\\.InstanceName", false, null),
+ null
+ };
+
+ public static final Property IcePatch2ClientProps[] =
+ {
+ new Property("IcePatch2Client\\.ChunkSize", false, null),
+ new Property("IcePatch2Client\\.Directory", false, null),
+ new Property("IcePatch2Client\\.Proxy", false, null),
+ new Property("IcePatch2Client\\.Remove", false, null),
+ new Property("IcePatch2Client\\.Thorough", false, null),
+ null
+ };
+
+ public static final Property IceSSLProps[] =
+ {
+ new Property("IceSSL\\.Alias", false, null),
+ new Property("IceSSL\\.CAs", false, null),
+ new Property("IceSSL\\.CertAuthDir", true, "IceSSL.CAs"),
+ new Property("IceSSL\\.CertAuthFile", true, "IceSSL.CAs"),
+ new Property("IceSSL\\.CertStore", false, null),
+ new Property("IceSSL\\.CertStoreLocation", false, null),
+ new Property("IceSSL\\.CertFile", false, null),
+ new Property("IceSSL\\.CertVerifier", false, null),
+ new Property("IceSSL\\.CheckCertName", false, null),
+ new Property("IceSSL\\.CheckCRL", false, null),
+ new Property("IceSSL\\.Ciphers", false, null),
+ new Property("IceSSL\\.DefaultDir", false, null),
+ new Property("IceSSL\\.DH\\.[^\\s]+", false, null),
+ new Property("IceSSL\\.DHParams", false, null),
+ new Property("IceSSL\\.EntropyDaemon", false, null),
+ new Property("IceSSL\\.FindCert", false, null),
+ new Property("IceSSL\\.FindCert\\.[^\\s]+", true, "IceSSL.FindCert"),
+ new Property("IceSSL\\.InitOpenSSL", false, null),
+ new Property("IceSSL\\.KeyFile", true, null),
+ new Property("IceSSL\\.Keychain", false, null),
+ new Property("IceSSL\\.KeychainPassword", false, null),
+ new Property("IceSSL\\.Keystore", false, null),
+ new Property("IceSSL\\.KeystorePassword", false, null),
+ new Property("IceSSL\\.KeystoreType", false, null),
+ new Property("IceSSL\\.Password", false, null),
+ new Property("IceSSL\\.PasswordCallback", false, null),
+ new Property("IceSSL\\.PasswordRetryMax", false, null),
+ new Property("IceSSL\\.Protocols", false, null),
+ new Property("IceSSL\\.ProtocolVersionMax", false, null),
+ new Property("IceSSL\\.ProtocolVersionMin", false, null),
+ new Property("IceSSL\\.Random", false, null),
+ new Property("IceSSL\\.Trace\\.Security", false, null),
+ new Property("IceSSL\\.TrustOnly", false, null),
+ new Property("IceSSL\\.TrustOnly\\.Client", false, null),
+ new Property("IceSSL\\.TrustOnly\\.Server", false, null),
+ new Property("IceSSL\\.TrustOnly\\.Server\\.[^\\s]+", false, null),
+ new Property("IceSSL\\.Truststore", false, null),
+ new Property("IceSSL\\.TruststorePassword", false, null),
+ new Property("IceSSL\\.TruststoreType", false, null),
+ new Property("IceSSL\\.UsePlatformCAs", false, null),
+ new Property("IceSSL\\.VerifyDepthMax", false, null),
+ new Property("IceSSL\\.VerifyPeer", false, null),
+ null
+ };
+
+ public static final Property IceStormAdminProps[] =
+ {
+ new Property("IceStormAdmin\\.TopicManager\\.[^\\s]+", false, null),
+ new Property("IceStormAdmin\\.Host", false, null),
+ new Property("IceStormAdmin\\.Port", false, null),
+ null
+ };
+
+ public static final Property IceBTProps[] =
+ {
+ new Property("IceBT\\.RcvSize", false, null),
+ new Property("IceBT\\.SndSize", false, null),
+ null
+ };
+
+ public static final Property Glacier2Props[] =
+ {
+ new Property("Glacier2\\.AddConnectionContext", false, null),
+ new Property("Glacier2\\.Client\\.ACM\\.Timeout", false, null),
+ new Property("Glacier2\\.Client\\.ACM\\.Heartbeat", false, null),
+ new Property("Glacier2\\.Client\\.ACM\\.Close", false, null),
+ new Property("Glacier2\\.Client\\.ACM", false, null),
+ new Property("Glacier2\\.Client\\.AdapterId", false, null),
+ new Property("Glacier2\\.Client\\.Endpoints", false, null),
+ new Property("Glacier2\\.Client\\.Locator\\.EndpointSelection", false, null),
+ new Property("Glacier2\\.Client\\.Locator\\.ConnectionCached", false, null),
+ new Property("Glacier2\\.Client\\.Locator\\.PreferSecure", false, null),
+ new Property("Glacier2\\.Client\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("Glacier2\\.Client\\.Locator\\.InvocationTimeout", false, null),
+ new Property("Glacier2\\.Client\\.Locator\\.Locator", false, null),
+ new Property("Glacier2\\.Client\\.Locator\\.Router", false, null),
+ new Property("Glacier2\\.Client\\.Locator\\.CollocationOptimized", false, null),
+ new Property("Glacier2\\.Client\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("Glacier2\\.Client\\.Locator", false, null),
+ new Property("Glacier2\\.Client\\.PublishedEndpoints", false, null),
+ new Property("Glacier2\\.Client\\.ReplicaGroupId", false, null),
+ new Property("Glacier2\\.Client\\.Router\\.EndpointSelection", false, null),
+ new Property("Glacier2\\.Client\\.Router\\.ConnectionCached", false, null),
+ new Property("Glacier2\\.Client\\.Router\\.PreferSecure", false, null),
+ new Property("Glacier2\\.Client\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("Glacier2\\.Client\\.Router\\.InvocationTimeout", false, null),
+ new Property("Glacier2\\.Client\\.Router\\.Locator", false, null),
+ new Property("Glacier2\\.Client\\.Router\\.Router", false, null),
+ new Property("Glacier2\\.Client\\.Router\\.CollocationOptimized", false, null),
+ new Property("Glacier2\\.Client\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("Glacier2\\.Client\\.Router", false, null),
+ new Property("Glacier2\\.Client\\.ProxyOptions", false, null),
+ new Property("Glacier2\\.Client\\.ThreadPool\\.Size", false, null),
+ new Property("Glacier2\\.Client\\.ThreadPool\\.SizeMax", false, null),
+ new Property("Glacier2\\.Client\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("Glacier2\\.Client\\.ThreadPool\\.StackSize", false, null),
+ new Property("Glacier2\\.Client\\.ThreadPool\\.Serialize", false, null),
+ new Property("Glacier2\\.Client\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("Glacier2\\.Client\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("Glacier2\\.Client\\.MessageSizeMax", false, null),
+ new Property("Glacier2\\.Client\\.AlwaysBatch", false, null),
+ new Property("Glacier2\\.Client\\.Buffered", false, null),
+ new Property("Glacier2\\.Client\\.ForwardContext", false, null),
+ new Property("Glacier2\\.Client\\.SleepTime", false, null),
+ new Property("Glacier2\\.Client\\.Trace\\.Override", false, null),
+ new Property("Glacier2\\.Client\\.Trace\\.Reject", false, null),
+ new Property("Glacier2\\.Client\\.Trace\\.Request", false, null),
+ new Property("Glacier2\\.CryptPasswords", false, null),
+ new Property("Glacier2\\.Filter\\.Address\\.Reject", false, null),
+ new Property("Glacier2\\.Filter\\.Address\\.Accept", false, null),
+ new Property("Glacier2\\.Filter\\.ProxySizeMax", false, null),
+ new Property("Glacier2\\.Filter\\.Category\\.Accept", false, null),
+ new Property("Glacier2\\.Filter\\.Category\\.AcceptUser", false, null),
+ new Property("Glacier2\\.Filter\\.AdapterId\\.Accept", false, null),
+ new Property("Glacier2\\.Filter\\.Identity\\.Accept", false, null),
+ new Property("Glacier2\\.InstanceName", false, null),
+ new Property("Glacier2\\.PermissionsVerifier\\.EndpointSelection", false, null),
+ new Property("Glacier2\\.PermissionsVerifier\\.ConnectionCached", false, null),
+ new Property("Glacier2\\.PermissionsVerifier\\.PreferSecure", false, null),
+ new Property("Glacier2\\.PermissionsVerifier\\.LocatorCacheTimeout", false, null),
+ new Property("Glacier2\\.PermissionsVerifier\\.InvocationTimeout", false, null),
+ new Property("Glacier2\\.PermissionsVerifier\\.Locator", false, null),
+ new Property("Glacier2\\.PermissionsVerifier\\.Router", false, null),
+ new Property("Glacier2\\.PermissionsVerifier\\.CollocationOptimized", false, null),
+ new Property("Glacier2\\.PermissionsVerifier\\.Context\\.[^\\s]+", false, null),
+ new Property("Glacier2\\.PermissionsVerifier", false, null),
+ new Property("Glacier2\\.ReturnClientProxy", false, null),
+ new Property("Glacier2\\.SSLPermissionsVerifier\\.EndpointSelection", false, null),
+ new Property("Glacier2\\.SSLPermissionsVerifier\\.ConnectionCached", false, null),
+ new Property("Glacier2\\.SSLPermissionsVerifier\\.PreferSecure", false, null),
+ new Property("Glacier2\\.SSLPermissionsVerifier\\.LocatorCacheTimeout", false, null),
+ new Property("Glacier2\\.SSLPermissionsVerifier\\.InvocationTimeout", false, null),
+ new Property("Glacier2\\.SSLPermissionsVerifier\\.Locator", false, null),
+ new Property("Glacier2\\.SSLPermissionsVerifier\\.Router", false, null),
+ new Property("Glacier2\\.SSLPermissionsVerifier\\.CollocationOptimized", false, null),
+ new Property("Glacier2\\.SSLPermissionsVerifier\\.Context\\.[^\\s]+", false, null),
+ new Property("Glacier2\\.SSLPermissionsVerifier", false, null),
+ new Property("Glacier2\\.RoutingTable\\.MaxSize", false, null),
+ new Property("Glacier2\\.Server\\.ACM\\.Timeout", false, null),
+ new Property("Glacier2\\.Server\\.ACM\\.Heartbeat", false, null),
+ new Property("Glacier2\\.Server\\.ACM\\.Close", false, null),
+ new Property("Glacier2\\.Server\\.ACM", false, null),
+ new Property("Glacier2\\.Server\\.AdapterId", false, null),
+ new Property("Glacier2\\.Server\\.Endpoints", false, null),
+ new Property("Glacier2\\.Server\\.Locator\\.EndpointSelection", false, null),
+ new Property("Glacier2\\.Server\\.Locator\\.ConnectionCached", false, null),
+ new Property("Glacier2\\.Server\\.Locator\\.PreferSecure", false, null),
+ new Property("Glacier2\\.Server\\.Locator\\.LocatorCacheTimeout", false, null),
+ new Property("Glacier2\\.Server\\.Locator\\.InvocationTimeout", false, null),
+ new Property("Glacier2\\.Server\\.Locator\\.Locator", false, null),
+ new Property("Glacier2\\.Server\\.Locator\\.Router", false, null),
+ new Property("Glacier2\\.Server\\.Locator\\.CollocationOptimized", false, null),
+ new Property("Glacier2\\.Server\\.Locator\\.Context\\.[^\\s]+", false, null),
+ new Property("Glacier2\\.Server\\.Locator", false, null),
+ new Property("Glacier2\\.Server\\.PublishedEndpoints", false, null),
+ new Property("Glacier2\\.Server\\.ReplicaGroupId", false, null),
+ new Property("Glacier2\\.Server\\.Router\\.EndpointSelection", false, null),
+ new Property("Glacier2\\.Server\\.Router\\.ConnectionCached", false, null),
+ new Property("Glacier2\\.Server\\.Router\\.PreferSecure", false, null),
+ new Property("Glacier2\\.Server\\.Router\\.LocatorCacheTimeout", false, null),
+ new Property("Glacier2\\.Server\\.Router\\.InvocationTimeout", false, null),
+ new Property("Glacier2\\.Server\\.Router\\.Locator", false, null),
+ new Property("Glacier2\\.Server\\.Router\\.Router", false, null),
+ new Property("Glacier2\\.Server\\.Router\\.CollocationOptimized", false, null),
+ new Property("Glacier2\\.Server\\.Router\\.Context\\.[^\\s]+", false, null),
+ new Property("Glacier2\\.Server\\.Router", false, null),
+ new Property("Glacier2\\.Server\\.ProxyOptions", false, null),
+ new Property("Glacier2\\.Server\\.ThreadPool\\.Size", false, null),
+ new Property("Glacier2\\.Server\\.ThreadPool\\.SizeMax", false, null),
+ new Property("Glacier2\\.Server\\.ThreadPool\\.SizeWarn", false, null),
+ new Property("Glacier2\\.Server\\.ThreadPool\\.StackSize", false, null),
+ new Property("Glacier2\\.Server\\.ThreadPool\\.Serialize", false, null),
+ new Property("Glacier2\\.Server\\.ThreadPool\\.ThreadIdleTime", false, null),
+ new Property("Glacier2\\.Server\\.ThreadPool\\.ThreadPriority", false, null),
+ new Property("Glacier2\\.Server\\.MessageSizeMax", false, null),
+ new Property("Glacier2\\.Server\\.AlwaysBatch", false, null),
+ new Property("Glacier2\\.Server\\.Buffered", false, null),
+ new Property("Glacier2\\.Server\\.ForwardContext", false, null),
+ new Property("Glacier2\\.Server\\.SleepTime", false, null),
+ new Property("Glacier2\\.Server\\.Trace\\.Override", false, null),
+ new Property("Glacier2\\.Server\\.Trace\\.Request", false, null),
+ new Property("Glacier2\\.SessionManager\\.EndpointSelection", false, null),
+ new Property("Glacier2\\.SessionManager\\.ConnectionCached", false, null),
+ new Property("Glacier2\\.SessionManager\\.PreferSecure", false, null),
+ new Property("Glacier2\\.SessionManager\\.LocatorCacheTimeout", false, null),
+ new Property("Glacier2\\.SessionManager\\.InvocationTimeout", false, null),
+ new Property("Glacier2\\.SessionManager\\.Locator", false, null),
+ new Property("Glacier2\\.SessionManager\\.Router", false, null),
+ new Property("Glacier2\\.SessionManager\\.CollocationOptimized", false, null),
+ new Property("Glacier2\\.SessionManager\\.Context\\.[^\\s]+", false, null),
+ new Property("Glacier2\\.SessionManager", false, null),
+ new Property("Glacier2\\.SSLSessionManager\\.EndpointSelection", false, null),
+ new Property("Glacier2\\.SSLSessionManager\\.ConnectionCached", false, null),
+ new Property("Glacier2\\.SSLSessionManager\\.PreferSecure", false, null),
+ new Property("Glacier2\\.SSLSessionManager\\.LocatorCacheTimeout", false, null),
+ new Property("Glacier2\\.SSLSessionManager\\.InvocationTimeout", false, null),
+ new Property("Glacier2\\.SSLSessionManager\\.Locator", false, null),
+ new Property("Glacier2\\.SSLSessionManager\\.Router", false, null),
+ new Property("Glacier2\\.SSLSessionManager\\.CollocationOptimized", false, null),
+ new Property("Glacier2\\.SSLSessionManager\\.Context\\.[^\\s]+", false, null),
+ new Property("Glacier2\\.SSLSessionManager", false, null),
+ new Property("Glacier2\\.SessionTimeout", false, null),
+ new Property("Glacier2\\.Trace\\.RoutingTable", false, null),
+ new Property("Glacier2\\.Trace\\.Session", false, null),
+ null
+ };
+
+ public static final Property Glacier2CryptPermissionsVerifierProps[] =
+ {
+ new Property("Glacier2CryptPermissionsVerifier\\.[^\\s]+\\.PermissionsVerifier", false, null),
+ new Property("Glacier2CryptPermissionsVerifier\\.[^\\s]+\\.AdminPermissionsVerifier", false, null),
+ null
+ };
+
+ public static final Property FreezeProps[] =
+ {
+ new Property("Freeze\\.DbEnv\\.[^\\s]+\\.CheckpointPeriod", false, null),
+ new Property("Freeze\\.DbEnv\\.[^\\s]+\\.DbHome", false, null),
+ new Property("Freeze\\.DbEnv\\.[^\\s]+\\.DbPrivate", false, null),
+ new Property("Freeze\\.DbEnv\\.[^\\s]+\\.DbRecoverFatal", false, null),
+ new Property("Freeze\\.DbEnv\\.[^\\s]+\\.EncodingVersion", false, null),
+ new Property("Freeze\\.DbEnv\\.[^\\s]+\\.LockFile", false, null),
+ new Property("Freeze\\.DbEnv\\.[^\\s]+\\.OldLogsAutoDelete", false, null),
+ new Property("Freeze\\.DbEnv\\.[^\\s]+\\.PeriodicCheckpointMinSize", false, null),
+ new Property("Freeze\\.Evictor\\.[^\\s]+\\.BtreeMinKey", false, null),
+ new Property("Freeze\\.Evictor\\.[^\\s]+\\.Checksum", false, null),
+ new Property("Freeze\\.Evictor\\.[^\\s]+\\.MaxTxSize", false, null),
+ new Property("Freeze\\.Evictor\\.[^\\s]+\\.PageSize", false, null),
+ new Property("Freeze\\.Evictor\\.[^\\s]+\\.PopulateEmptyIndices", false, null),
+ new Property("Freeze\\.Evictor\\.[^\\s]+\\.RollbackOnUserException", false, null),
+ new Property("Freeze\\.Evictor\\.[^\\s]+\\.SavePeriod", false, null),
+ new Property("Freeze\\.Evictor\\.[^\\s]+\\.SaveSizeTrigger", false, null),
+ new Property("Freeze\\.Evictor\\.[^\\s]+\\.StreamTimeout", false, null),
+ new Property("Freeze\\.Map\\.[^\\s]+\\.BtreeMinKey", false, null),
+ new Property("Freeze\\.Map\\.[^\\s]+\\.Checksum", false, null),
+ new Property("Freeze\\.Map\\.[^\\s]+\\.PageSize", false, null),
+ new Property("Freeze\\.Trace\\.DbEnv", false, null),
+ new Property("Freeze\\.Trace\\.Evictor", false, null),
+ new Property("Freeze\\.Trace\\.Map", false, null),
+ new Property("Freeze\\.Trace\\.Transaction", false, null),
+ new Property("Freeze\\.Warn\\.Deadlocks", false, null),
+ new Property("Freeze\\.Warn\\.Rollback", false, null),
+ null
+ };
+
+
+ public static final Property[] validProps[] =
+ {
+ IceProps,
+ IceMXProps,
+ IceDiscoveryProps,
+ IceGridDiscoveryProps,
+ IceBoxProps,
+ IceBoxAdminProps,
+ IceGridAdminProps,
+ IceGridProps,
+ IcePatch2Props,
+ IcePatch2ClientProps,
+ IceSSLProps,
+ IceStormAdminProps,
+ IceBTProps,
+ Glacier2Props,
+ Glacier2CryptPermissionsVerifierProps,
+ FreezeProps,
+ null
+ };
+
+ public static final String clPropNames[] =
+ {
+ "Ice",
+ "IceMX",
+ "IceDiscovery",
+ "IceGridDiscovery",
+ "IceBox",
+ "IceBoxAdmin",
+ "IceGridAdmin",
+ "IceGrid",
+ "IcePatch2",
+ "IcePatch2Client",
+ "IceSSL",
+ "IceStormAdmin",
+ "IceBT",
+ "Glacier2",
+ "Glacier2CryptPermissionsVerifier",
+ "Freeze",
+ null
+ };
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Protocol.java b/java-compat/src/Ice/src/main/java/IceInternal/Protocol.java
new file mode 100644
index 00000000000..01b9a460b42
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Protocol.java
@@ -0,0 +1,198 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final public class Protocol
+{
+ //
+ // 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)
+ //
+ public final static int headerSize = 14;
+
+ //
+ // The magic number at the front of each message
+ //
+ public final static byte magic[] = { 0x49, 0x63, 0x65, 0x50 }; // 'I', 'c', 'e', 'P'
+
+ //
+ // The current Ice protocol and encoding version
+ //
+ public final static byte protocolMajor = 1;
+ public final static byte protocolMinor = 0;
+ public final static byte protocolEncodingMajor = 1;
+ public final static byte protocolEncodingMinor = 0;
+
+ public final static byte encodingMajor = 1;
+ public final static byte encodingMinor = 1;
+
+ //
+ // The Ice protocol message types
+ //
+ public final static byte requestMsg = 0;
+ public final static byte requestBatchMsg = 1;
+ public final static byte replyMsg = 2;
+ public final static byte validateConnectionMsg = 3;
+ public final static byte closeConnectionMsg = 4;
+
+ public final static byte[] requestHdr =
+ {
+ IceInternal.Protocol.magic[0],
+ IceInternal.Protocol.magic[1],
+ IceInternal.Protocol.magic[2],
+ IceInternal.Protocol.magic[3],
+ IceInternal.Protocol.protocolMajor,
+ IceInternal.Protocol.protocolMinor,
+ IceInternal.Protocol.protocolEncodingMajor,
+ IceInternal.Protocol.protocolEncodingMinor,
+ IceInternal.Protocol.requestMsg,
+ (byte)0, // Compression status.
+ (byte)0, (byte)0, (byte)0, (byte)0, // Message size (placeholder).
+ (byte)0, (byte)0, (byte)0, (byte)0 // Request ID (placeholder).
+ };
+
+ public final static byte[] requestBatchHdr =
+ {
+ IceInternal.Protocol.magic[0],
+ IceInternal.Protocol.magic[1],
+ IceInternal.Protocol.magic[2],
+ IceInternal.Protocol.magic[3],
+ IceInternal.Protocol.protocolMajor,
+ IceInternal.Protocol.protocolMinor,
+ IceInternal.Protocol.protocolEncodingMajor,
+ IceInternal.Protocol.protocolEncodingMinor,
+ IceInternal.Protocol.requestBatchMsg,
+ 0, // Compression status.
+ (byte)0, (byte)0, (byte)0, (byte)0, // Message size (placeholder).
+ (byte)0, (byte)0, (byte)0, (byte)0 // Number of requests in batch (placeholder).
+ };
+
+ public final static byte[] replyHdr =
+ {
+ IceInternal.Protocol.magic[0],
+ IceInternal.Protocol.magic[1],
+ IceInternal.Protocol.magic[2],
+ IceInternal.Protocol.magic[3],
+ IceInternal.Protocol.protocolMajor,
+ IceInternal.Protocol.protocolMinor,
+ IceInternal.Protocol.protocolEncodingMajor,
+ IceInternal.Protocol.protocolEncodingMinor,
+ IceInternal.Protocol.replyMsg,
+ (byte)0, // Compression status.
+ (byte)0, (byte)0, (byte)0, (byte)0 // Message size (placeholder).
+ };
+
+ static final public Ice.ProtocolVersion currentProtocol = new Ice.ProtocolVersion(protocolMajor, protocolMinor);
+ static final public Ice.EncodingVersion currentProtocolEncoding = new Ice.EncodingVersion(protocolEncodingMajor,
+ protocolEncodingMinor);
+
+ static final public Ice.EncodingVersion currentEncoding = new Ice.EncodingVersion(encodingMajor, encodingMinor);
+
+ static public void
+ checkSupportedProtocol(Ice.ProtocolVersion v)
+ {
+ if(v.major != currentProtocol.major || v.minor > currentProtocol.minor)
+ {
+ throw new Ice.UnsupportedProtocolException("", v, currentProtocol);
+ }
+ }
+
+ static public void
+ checkSupportedProtocolEncoding(Ice.EncodingVersion v)
+ {
+ if(v.major != currentProtocolEncoding.major || v.minor > currentProtocolEncoding.minor)
+ {
+ throw new Ice.UnsupportedEncodingException("", v, currentProtocolEncoding);
+ }
+ }
+
+ static public void
+ checkSupportedEncoding(Ice.EncodingVersion v)
+ {
+ if(v.major != currentEncoding.major || v.minor > currentEncoding.minor)
+ {
+ throw new Ice.UnsupportedEncodingException("", v, currentEncoding);
+ }
+ }
+
+ //
+ // Either return the given protocol if not compatible, or the greatest
+ // supported protocol otherwise.
+ //
+ static public Ice.ProtocolVersion
+ getCompatibleProtocol(Ice.ProtocolVersion v)
+ {
+ if(v.major != currentProtocol.major)
+ {
+ return v; // Unsupported protocol, return as is.
+ }
+ else if(v.minor < currentProtocol.minor)
+ {
+ return v; // Supported protocol.
+ }
+ else
+ {
+ //
+ // Unsupported but compatible, use the currently supported
+ // protocol, that's the best we can do.
+ //
+ return currentProtocol;
+ }
+ }
+
+ //
+ // Either return the given encoding if not compatible, or the greatest
+ // supported encoding otherwise.
+ //
+ static public Ice.EncodingVersion
+ getCompatibleEncoding(Ice.EncodingVersion v)
+ {
+ if(v.major != currentEncoding.major)
+ {
+ return v; // Unsupported encoding, return as is.
+ }
+ else if(v.minor < currentEncoding.minor)
+ {
+ return v; // Supported encoding.
+ }
+ else
+ {
+ //
+ // Unsupported but compatible, use the currently supported
+ // encoding, that's the best we can do.
+ //
+ return currentEncoding;
+ }
+ }
+
+ static public boolean
+ isSupported(Ice.EncodingVersion version, Ice.EncodingVersion supported)
+ {
+ return version.major == supported.major && version.minor <= supported.minor;
+ }
+
+ public static final int OPTIONAL_END_MARKER = 0xFF;
+
+ public static final byte FLAG_HAS_TYPE_ID_STRING = (byte)(1<<0);
+ public static final byte FLAG_HAS_TYPE_ID_INDEX = (byte)(1<<1);
+ public static final byte FLAG_HAS_TYPE_ID_COMPACT = (byte)(1<<1 | 1<<0);
+ public static final byte FLAG_HAS_OPTIONAL_MEMBERS = (byte)(1<<2);
+ public static final byte FLAG_HAS_INDIRECTION_TABLE = (byte)(1<<3);
+ public static final byte FLAG_HAS_SLICE_SIZE = (byte)(1<<4);
+ public static final byte FLAG_IS_LAST_SLICE = (byte)(1<<5);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ProtocolInstance.java b/java-compat/src/Ice/src/main/java/IceInternal/ProtocolInstance.java
new file mode 100644
index 00000000000..e88ec007887
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ProtocolInstance.java
@@ -0,0 +1,142 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ProtocolInstance
+{
+ public ProtocolInstance(Ice.Communicator communicator, short type, String protocol, boolean secure)
+ {
+ _instance = Util.getInstance(communicator);
+ _traceLevel = _instance.traceLevels().network;
+ _traceCategory = _instance.traceLevels().networkCat;
+ _logger = _instance.initializationData().logger;
+ _properties = _instance.initializationData().properties;
+ _type = type;
+ _protocol = protocol;
+ _secure = secure;
+ }
+
+ public int traceLevel()
+ {
+ return _traceLevel;
+ }
+
+ public String traceCategory()
+ {
+ return _traceCategory;
+ }
+
+ public Ice.Logger logger()
+ {
+ return _logger;
+ }
+
+ public String protocol()
+ {
+ return _protocol;
+ }
+
+ public short type()
+ {
+ return _type;
+ }
+
+ public boolean secure()
+ {
+ return _secure;
+ }
+
+ public Ice.Properties properties()
+ {
+ return _properties;
+ }
+
+ public boolean preferIPv6()
+ {
+ return _instance.preferIPv6();
+ }
+
+ public int protocolSupport()
+ {
+ return _instance.protocolSupport();
+ }
+
+ public String defaultHost()
+ {
+ return _instance.defaultsAndOverrides().defaultHost;
+ }
+
+ public java.net.InetSocketAddress defaultSourceAddress()
+ {
+ return _instance.defaultsAndOverrides().defaultSourceAddress;
+ }
+
+ public Ice.EncodingVersion defaultEncoding()
+ {
+ return _instance.defaultsAndOverrides().defaultEncoding;
+ }
+
+ public int defaultTimeout()
+ {
+ return _instance.defaultsAndOverrides().defaultTimeout;
+ }
+
+ public NetworkProxy networkProxy()
+ {
+ return _instance.networkProxy();
+ }
+
+ public int messageSizeMax()
+ {
+ return _instance.messageSizeMax();
+ }
+
+ public void resolve(String host, int port, Ice.EndpointSelectionType type, IPEndpointI endpt,
+ EndpointI_connectors callback)
+ {
+ _instance.endpointHostResolver().resolve(host, port, type, endpt, callback);
+ }
+
+ public BufSizeWarnInfo getBufSizeWarn(short type)
+ {
+ return _instance.getBufSizeWarn(type);
+ }
+
+ public void setSndBufSizeWarn(short type, int size)
+ {
+ _instance.setSndBufSizeWarn(type, size);
+ }
+
+ public void setRcvBufSizeWarn(short type, int size)
+ {
+ _instance.setRcvBufSizeWarn(type, size);
+ }
+
+ ProtocolInstance(Instance instance, short type, String protocol, boolean secure)
+ {
+ _instance = instance;
+ _traceLevel = _instance.traceLevels().network;
+ _traceCategory = _instance.traceLevels().networkCat;
+ _logger = _instance.initializationData().logger;
+ _properties = _instance.initializationData().properties;
+ _type = type;
+ _protocol = protocol;
+ _secure = secure;
+ }
+
+ protected Instance _instance;
+ protected int _traceLevel;
+ protected String _traceCategory;
+ protected Ice.Logger _logger;
+ protected Ice.Properties _properties;
+ protected String _protocol;
+ protected short _type;
+ protected boolean _secure;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ProtocolPluginFacade.java b/java-compat/src/Ice/src/main/java/IceInternal/ProtocolPluginFacade.java
new file mode 100644
index 00000000000..7bfb91f3e04
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ProtocolPluginFacade.java
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface ProtocolPluginFacade
+{
+ //
+ // Get the Communicator instance with which this facade is
+ // associated.
+ //
+ Ice.Communicator getCommunicator();
+
+ //
+ // Register an EndpointFactory.
+ //
+ void addEndpointFactory(EndpointFactory factory);
+
+ //
+ // Get an EndpointFactory.
+ //
+ EndpointFactory getEndpointFactory(short type);
+
+ //
+ // Look up a Java class by name.
+ //
+ Class<?> findClass(String className);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ProtocolPluginFacadeI.java b/java-compat/src/Ice/src/main/java/IceInternal/ProtocolPluginFacadeI.java
new file mode 100644
index 00000000000..fa510e2e6f9
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ProtocolPluginFacadeI.java
@@ -0,0 +1,59 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ProtocolPluginFacadeI implements ProtocolPluginFacade
+{
+ public ProtocolPluginFacadeI(Ice.Communicator communicator)
+ {
+ _communicator = communicator;
+ _instance = Util.getInstance(communicator);
+ }
+
+ //
+ // Get the Communicator instance with which this facade is
+ // associated.
+ //
+ @Override
+ public Ice.Communicator getCommunicator()
+ {
+ return _communicator;
+ }
+
+ //
+ // Register an EndpointFactory.
+ //
+ @Override
+ public void addEndpointFactory(EndpointFactory factory)
+ {
+ _instance.endpointFactoryManager().add(factory);
+ }
+
+ //
+ // Register an EndpointFactory.
+ //
+ @Override
+ public EndpointFactory getEndpointFactory(short type)
+ {
+ return _instance.endpointFactoryManager().get(type);
+ }
+
+ //
+ // Look up a Java class by name.
+ //
+ @Override
+ public Class<?> findClass(String className)
+ {
+ return _instance.findClass(className);
+ }
+
+ private Instance _instance;
+ private Ice.Communicator _communicator;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ProxyFactory.java b/java-compat/src/Ice/src/main/java/IceInternal/ProxyFactory.java
new file mode 100644
index 00000000000..ed3f1b81bd6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ProxyFactory.java
@@ -0,0 +1,302 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import Ice.OperationInterruptedException;
+
+public final class ProxyFactory
+{
+ public Ice.ObjectPrx
+ stringToProxy(String str)
+ {
+ Reference ref = _instance.referenceFactory().create(str, null);
+ return referenceToProxy(ref);
+ }
+
+ public String
+ proxyToString(Ice.ObjectPrx proxy)
+ {
+ if(proxy != null)
+ {
+ Ice.ObjectPrxHelperBase h = (Ice.ObjectPrxHelperBase)proxy;
+ return h.__reference().toString();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ public Ice.ObjectPrx
+ propertyToProxy(String prefix)
+ {
+ String proxy = _instance.initializationData().properties.getProperty(prefix);
+ Reference ref = _instance.referenceFactory().create(proxy, prefix);
+ return referenceToProxy(ref);
+ }
+
+ public java.util.Map<String, String>
+ proxyToProperty(Ice.ObjectPrx proxy, String prefix)
+ {
+ if(proxy != null)
+ {
+ Ice.ObjectPrxHelperBase h = (Ice.ObjectPrxHelperBase)proxy;
+ return h.__reference().toProperty(prefix);
+ }
+ else
+ {
+ return new java.util.HashMap<String, String>();
+ }
+ }
+
+ public Ice.ObjectPrx
+ streamToProxy(Ice.InputStream s)
+ {
+ Ice.Identity ident = new Ice.Identity();
+ ident.__read(s);
+
+ Reference ref = _instance.referenceFactory().create(ident, s);
+ return referenceToProxy(ref);
+ }
+
+ public Ice.ObjectPrx
+ referenceToProxy(Reference ref)
+ {
+ if(ref != null)
+ {
+ Ice.ObjectPrxHelperBase proxy = new Ice.ObjectPrxHelperBase();
+ proxy.__setup(ref);
+ return proxy;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public int
+ checkRetryAfterException(Ice.LocalException ex, Reference ref, Ice.Holder<Integer> sleepInterval, int cnt)
+ {
+ TraceLevels traceLevels = _instance.traceLevels();
+ Ice.Logger logger = _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() == IceInternal.Reference.ModeBatchOneway ||
+ ref.getMode() == IceInternal.Reference.ModeBatchDatagram)
+ {
+ throw ex;
+ }
+
+ if(ex instanceof Ice.ObjectNotExistException)
+ {
+ Ice.ObjectNotExistException one = (Ice.ObjectNotExistException)ex;
+
+ if(ref.getRouterInfo() != null && one.operation.equals("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)
+ {
+ String s = "retrying operation call to add proxy to router\n" + ex.toString();
+ logger.trace(traceLevels.retryCat, s);
+ }
+
+ 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())
+ {
+ LocatorInfo 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 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;
+ }
+
+ //
+ // Don't retry if the communicator is destroyed or object adapter
+ // deactivated.
+ //
+ if(ex instanceof Ice.CommunicatorDestroyedException || ex instanceof Ice.ObjectAdapterDeactivatedException)
+ {
+ throw ex;
+ }
+
+ //
+ // Don't retry invocation timeouts.
+ //
+ if(ex instanceof Ice.InvocationTimeoutException || ex instanceof Ice.InvocationCanceledException)
+ {
+ throw ex;
+ }
+
+ //
+ // Don't retry on OperationInterruptedException.
+ //
+ if(ex instanceof OperationInterruptedException)
+ {
+ throw ex;
+ }
+
+ ++cnt;
+ assert(cnt > 0);
+
+ int interval;
+ if(cnt == (_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 > _retryIntervals.length)
+ {
+ if(traceLevels.retry >= 1)
+ {
+ String s = "cannot retry operation call because retry limit has been exceeded\n" + ex.toString();
+ logger.trace(traceLevels.retryCat, s);
+ }
+ throw ex;
+ }
+ else
+ {
+ interval = _retryIntervals[cnt - 1];
+ }
+
+ if(traceLevels.retry >= 1)
+ {
+ String s = "retrying operation call";
+ if(interval > 0)
+ {
+ s += " in " + interval + "ms";
+ }
+ s += " because of exception\n" + ex;
+ logger.trace(traceLevels.retryCat, s);
+ }
+
+ sleepInterval.value = interval;
+ return cnt;
+ }
+
+ //
+ // Only for use by Instance.
+ //
+ ProxyFactory(Instance instance)
+ {
+ _instance = instance;
+
+ String[] arr = _instance.initializationData().properties.getPropertyAsList("Ice.RetryIntervals");
+
+ if(arr.length > 0)
+ {
+ _retryIntervals = new int[arr.length];
+
+ for(int i = 0; i < arr.length; i++)
+ {
+ int v;
+
+ try
+ {
+ v = Integer.parseInt(arr[i]);
+ }
+ catch(NumberFormatException ex)
+ {
+ v = 0;
+ }
+
+ //
+ // If -1 is the first value, no retry and wait intervals.
+ //
+ if(i == 0 && v == -1)
+ {
+ _retryIntervals = new int[0];
+ break;
+ }
+
+ _retryIntervals[i] = v > 0 ? v : 0;
+ }
+ }
+ else
+ {
+ _retryIntervals = new int[1];
+ _retryIntervals[0] = 0;
+ }
+ }
+
+ private Instance _instance;
+ private int[] _retryIntervals;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ProxyFlushBatch.java b/java-compat/src/Ice/src/main/java/IceInternal/ProxyFlushBatch.java
new file mode 100644
index 00000000000..eb49b24c6f1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ProxyFlushBatch.java
@@ -0,0 +1,62 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ProxyFlushBatch extends ProxyOutgoingAsyncBase
+{
+ public static ProxyFlushBatch check(Ice.AsyncResult r, Ice.ObjectPrx prx, String operation)
+ {
+ ProxyOutgoingAsyncBase.checkImpl(r, prx, operation);
+ try
+ {
+ return (ProxyFlushBatch)r;
+ }
+ catch(ClassCastException ex)
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ }
+
+ public ProxyFlushBatch(Ice.ObjectPrxHelperBase prx, String operation, CallbackBase callback)
+ {
+ super(prx, operation, callback);
+ _observer = ObserverHelper.get(prx, operation);
+ _batchRequestNum = prx.__getBatchRequestQueue().swap(_os);
+ }
+
+ @Override
+ public int invokeRemote(Ice.ConnectionI connection, boolean compress, boolean response) throws RetryException
+ {
+ if(_batchRequestNum == 0)
+ {
+ return sent() ? AsyncStatus.Sent | AsyncStatus.InvokeSentCallback : AsyncStatus.Sent;
+ }
+ _cachedConnection = connection;
+ return connection.sendAsyncRequest(this, compress, false, _batchRequestNum);
+ }
+
+ @Override
+ public int invokeCollocated(CollocatedRequestHandler handler)
+ {
+ if(_batchRequestNum == 0)
+ {
+ return sent() ? AsyncStatus.Sent | AsyncStatus.InvokeSentCallback : AsyncStatus.Sent;
+ }
+ return handler.invokeAsyncRequest(this, _batchRequestNum, false);
+ }
+
+ public void invoke()
+ {
+ Protocol.checkSupportedProtocol(Protocol.getCompatibleProtocol(_proxy.__reference().getProtocol()));
+ invokeImpl(true); // userThread = true
+ }
+
+ protected int _batchRequestNum;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ProxyGetConnection.java b/java-compat/src/Ice/src/main/java/IceInternal/ProxyGetConnection.java
new file mode 100644
index 00000000000..f4da8e83e12
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ProxyGetConnection.java
@@ -0,0 +1,65 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ProxyGetConnection extends ProxyOutgoingAsyncBase
+{
+ public static ProxyGetConnection check(Ice.AsyncResult r, Ice.ObjectPrx prx, String operation)
+ {
+ ProxyOutgoingAsyncBase.checkImpl(r, prx, operation);
+ try
+ {
+ return (ProxyGetConnection)r;
+ }
+ catch(ClassCastException ex)
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ }
+
+ public ProxyGetConnection(Ice.ObjectPrxHelperBase prx, String operation, CallbackBase cb)
+ {
+ super(prx, operation, cb);
+ _observer = ObserverHelper.get(prx, operation);
+ }
+
+ @Override
+ public int invokeRemote(Ice.ConnectionI connection, boolean compress, boolean response)
+ throws RetryException
+ {
+ _cachedConnection = connection;
+ if(finished(true))
+ {
+ invokeCompletedAsync();
+ }
+ return AsyncStatus.Sent;
+ }
+
+ @Override
+ public int invokeCollocated(CollocatedRequestHandler handler)
+ {
+ if(finished(true))
+ {
+ invokeCompletedAsync();
+ }
+ return AsyncStatus.Sent;
+ }
+
+ @Override
+ public Ice.Connection getConnection()
+ {
+ return _cachedConnection;
+ }
+
+ public void invoke()
+ {
+ invokeImpl(true); // userThread = true
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ProxyOutgoingAsyncBase.java b/java-compat/src/Ice/src/main/java/IceInternal/ProxyOutgoingAsyncBase.java
new file mode 100644
index 00000000000..a38c6c28c7a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ProxyOutgoingAsyncBase.java
@@ -0,0 +1,318 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+//
+// Base class for proxy based invocations. This class handles the
+// retry for proxy invocations. It also ensures the child observer is
+// correct notified of failures and make sure the retry task is
+// correctly canceled when the invocation completes.
+//
+public abstract class ProxyOutgoingAsyncBase extends OutgoingAsyncBase
+{
+ public static ProxyOutgoingAsyncBase check(Ice.AsyncResult r, Ice.ObjectPrx prx, String operation)
+ {
+ ProxyOutgoingAsyncBase.checkImpl(r, prx, operation);
+ try
+ {
+ return (ProxyOutgoingAsyncBase)r;
+ }
+ catch(ClassCastException ex)
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ }
+
+ public abstract int invokeRemote(Ice.ConnectionI con, boolean compress, boolean response) throws RetryException;
+
+ public abstract int invokeCollocated(CollocatedRequestHandler handler);
+
+ @Override
+ public Ice.ObjectPrx getProxy()
+ {
+ return _proxy;
+ }
+
+ @Override
+ public boolean completed(Ice.Exception exc)
+ {
+ if(_childObserver != null)
+ {
+ _childObserver.failed(exc.ice_id());
+ _childObserver.detach();
+ _childObserver = null;
+ }
+
+ //
+ // NOTE: at this point, synchronization isn't needed, no other threads should be
+ // calling on the callback.
+ //
+ try
+ {
+ //
+ // It's important to let the retry queue do the retry even if
+ // the retry interval is 0. This method can be called with the
+ // connection locked so we can't just retry here.
+ //
+ _instance.retryQueue().add(this, handleException(exc));
+ return false;
+ }
+ catch(Ice.Exception ex)
+ {
+ return finished(ex); // No retries, we're done
+ }
+ }
+
+ public void retryException(Ice.Exception ex)
+ {
+ try
+ {
+ //
+ // It's important to let the retry queue do the retry. This is
+ // called from the connect request handler and the retry might
+ // require could end up waiting for the flush of the
+ // connection to be done.
+ //
+ _proxy.__updateRequestHandler(_handler, null); // Clear request handler and always retry.
+ _instance.retryQueue().add(this, 0);
+ }
+ catch(Ice.Exception exc)
+ {
+ if(completed(exc))
+ {
+ invokeCompletedAsync();
+ }
+ }
+ }
+
+ public void retry()
+ {
+ invokeImpl(false);
+ }
+
+ public void cancelable(final CancellationHandler handler)
+ {
+ if(_proxy.__reference().getInvocationTimeout() == -2 && _cachedConnection != null)
+ {
+ final int timeout = _cachedConnection.timeout();
+ if(timeout > 0)
+ {
+ _future = _instance.timer().schedule(
+ new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ cancel(new Ice.ConnectionTimeoutException());
+ }
+ }, timeout, java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+ }
+ super.cancelable(handler);
+ }
+
+ public void abort(Ice.Exception ex)
+ {
+ assert(_childObserver == null);
+ if(finished(ex))
+ {
+ invokeCompletedAsync();
+ }
+ else if(ex instanceof Ice.CommunicatorDestroyedException)
+ {
+ //
+ // If it's a communicator destroyed exception, don't swallow
+ // it but instead notify the user thread. Even if no callback
+ // was provided.
+ //
+ throw ex;
+ }
+ }
+
+ protected ProxyOutgoingAsyncBase(Ice.ObjectPrxHelperBase prx, String op, CallbackBase delegate)
+ {
+ super(prx.ice_getCommunicator(), prx.__reference().getInstance(), op, delegate);
+ _proxy = prx;
+ _mode = Ice.OperationMode.Normal;
+ _cnt = 0;
+ _sent = false;
+ }
+
+ protected ProxyOutgoingAsyncBase(Ice.ObjectPrxHelperBase prx, String op, CallbackBase delegate, Ice.OutputStream os)
+ {
+ super(prx.ice_getCommunicator(), prx.__reference().getInstance(), op, delegate, os);
+ _proxy = prx;
+ _mode = Ice.OperationMode.Normal;
+ _cnt = 0;
+ _sent = false;
+ }
+
+ protected static Ice.AsyncResult checkImpl(Ice.AsyncResult r, Ice.ObjectPrx p, String operation)
+ {
+ check(r, operation);
+ if(r.getProxy() != p)
+ {
+ throw new IllegalArgumentException("Proxy for call to end_" + operation +
+ " does not match proxy that was used to call corresponding " +
+ "begin_" + operation + " method");
+ }
+ return r;
+ }
+
+ protected void invokeImpl(boolean userThread)
+ {
+ try
+ {
+ if(userThread)
+ {
+ int invocationTimeout = _proxy.__reference().getInvocationTimeout();
+ if(invocationTimeout > 0)
+ {
+ _future = _instance.timer().schedule(
+ new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ cancel(new Ice.InvocationTimeoutException());
+ }
+ }, invocationTimeout, java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+ }
+ else // If not called from the user thread, it's called from the retry queue
+ {
+ if(_observer != null)
+ {
+ _observer.retried();
+ }
+ }
+
+ while(true)
+ {
+ try
+ {
+ _sent = false;
+ _handler = null;
+ _handler = _proxy.__getRequestHandler();
+ int status = _handler.sendAsyncRequest(this);
+ if((status & AsyncStatus.Sent) > 0)
+ {
+ if(userThread)
+ {
+ _sentSynchronously = true;
+ if((status & AsyncStatus.InvokeSentCallback) > 0)
+ {
+ invokeSent(); // Call the sent callback from the user thread.
+ }
+ }
+ else
+ {
+ if((status & AsyncStatus.InvokeSentCallback) > 0)
+ {
+ invokeSentAsync(); // Call the sent callback from a client thread pool thread.
+ }
+ }
+ }
+ return; // We're done!
+ }
+ catch(RetryException ex)
+ {
+ _proxy.__updateRequestHandler(_handler, null); // Clear request handler and always retry.
+ }
+ catch(Ice.Exception ex)
+ {
+ if(_childObserver != null)
+ {
+ _childObserver.failed(ex.ice_id());
+ _childObserver.detach();
+ _childObserver = null;
+ }
+ final int interval = handleException(ex);
+ if(interval > 0)
+ {
+ _instance.retryQueue().add(this, interval);
+ return;
+ }
+ else if(_observer != null)
+ {
+ _observer.retried();
+ }
+ }
+ }
+ }
+ catch(Ice.Exception ex)
+ {
+ //
+ // If called from the user thread we re-throw, the exception
+ // will be catch by the caller and abort() will be called.
+ //
+ if(userThread)
+ {
+ throw ex;
+ }
+ else if(finished(ex)) // No retries, we're done
+ {
+ invokeCompletedAsync();
+ }
+ }
+ }
+
+ @Override
+ protected boolean sent(boolean done)
+ {
+ _sent = true;
+ if(done)
+ {
+ if(_future != null)
+ {
+ _future.cancel(false);
+ _future = null;
+ }
+ }
+ return super.sent(done);
+ }
+
+ @Override
+ protected boolean finished(Ice.Exception ex)
+ {
+ if(_future != null)
+ {
+ _future.cancel(false);
+ _future = null;
+ }
+ return super.finished(ex);
+ }
+
+ @Override
+ protected boolean finished(boolean ok)
+ {
+ if(_future != null)
+ {
+ _future.cancel(false);
+ _future = null;
+ }
+ return super.finished(ok);
+ }
+
+ protected int handleException(Ice.Exception exc)
+ {
+ Ice.Holder<Integer> interval = new Ice.Holder<Integer>();
+ _cnt = _proxy.__handleException(exc, _handler, _mode, _sent, interval, _cnt);
+ return interval.value;
+ }
+
+ final protected Ice.ObjectPrxHelperBase _proxy;
+ protected RequestHandler _handler;
+ protected Ice.OperationMode _mode;
+
+ private java.util.concurrent.Future<?> _future;
+ private int _cnt;
+ private boolean _sent;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/QueueExecutorService.java b/java-compat/src/Ice/src/main/java/IceInternal/QueueExecutorService.java
new file mode 100644
index 00000000000..cb46d5dfe0b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/QueueExecutorService.java
@@ -0,0 +1,118 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+
+public final class QueueExecutorService
+{
+ QueueExecutorService(ExecutorService executor)
+ {
+ _executor = executor;
+ _thread = executeNoThrow(new Callable<Thread>()
+ {
+ @Override
+ public Thread call()
+ {
+ return Thread.currentThread();
+ }
+ });
+ }
+
+ public <T> T executeNoThrow(Callable<T> callable)
+ {
+ try
+ {
+ return execute(callable);
+ }
+ catch(RetryException ex)
+ {
+ assert(false);
+ return null;
+ }
+ }
+
+ public <T> T execute(Callable<T> callable)
+ throws RetryException
+ {
+ if(_thread == Thread.currentThread())
+ {
+ try
+ {
+ return callable.call();
+ }
+ catch(RuntimeException ex)
+ {
+ throw ex;
+ }
+ catch(Exception ex)
+ {
+ // RetryException is the only checked exception that
+ // can be raised by Ice internals.
+ assert(ex instanceof RetryException);
+ throw (RetryException)ex;
+ }
+ }
+
+ boolean interrupted = false;
+ try
+ {
+ Future<T> future = _executor.submit(callable);
+ while(true)
+ {
+ try
+ {
+ T value = future.get();
+ return value;
+ }
+ catch(InterruptedException ex)
+ {
+ interrupted = true;
+ }
+ }
+ }
+ catch(RejectedExecutionException e)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+ catch(ExecutionException e)
+ {
+ try
+ {
+ throw e.getCause();
+ }
+ catch(RuntimeException ex)
+ {
+ throw ex;
+ }
+ catch(Throwable ex)
+ {
+ // RetryException is the only checked exception that
+ // can be raised by Ice internals.
+ assert(ex instanceof RetryException);
+ throw (RetryException)ex;
+ }
+ }
+ finally
+ {
+ if(interrupted)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ final ExecutorService _executor;
+ final Thread _thread;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/QueueRequestHandler.java b/java-compat/src/Ice/src/main/java/IceInternal/QueueRequestHandler.java
new file mode 100644
index 00000000000..a77e67c0f9f
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/QueueRequestHandler.java
@@ -0,0 +1,96 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.util.concurrent.Callable;
+
+import Ice.ConnectionI;
+
+public class QueueRequestHandler implements RequestHandler
+{
+ public
+ QueueRequestHandler(Instance instance, RequestHandler delegate)
+ {
+ _executor = instance.getQueueExecutor();
+ assert(delegate != null);
+ _delegate = delegate;
+ }
+
+ @Override
+ public RequestHandler
+ update(RequestHandler previousHandler, RequestHandler newHandler)
+ {
+ //
+ // Only update to new handler if the previous handler matches this one.
+ //
+ try
+ {
+ if(previousHandler == this || previousHandler == _delegate)
+ {
+ return newHandler;
+ }
+ else if(previousHandler.getConnection() == _delegate.getConnection())
+ {
+ return newHandler;
+ }
+ }
+ catch(Ice.Exception ex)
+ {
+ // Ignore
+ }
+ return this;
+ }
+
+ @Override
+ public int
+ sendAsyncRequest(final ProxyOutgoingAsyncBase out) throws RetryException
+ {
+ return _executor.execute(new Callable<Integer>()
+ {
+ @Override
+ public Integer call() throws RetryException
+ {
+ return _delegate.sendAsyncRequest(out);
+ }
+ });
+ }
+
+ @Override
+ public void
+ asyncRequestCanceled(final OutgoingAsyncBase outAsync, final Ice.LocalException ex)
+ {
+ _executor.executeNoThrow(new Callable<Void>()
+ {
+ @Override
+ public Void call()
+ {
+ _delegate.asyncRequestCanceled(outAsync, ex);
+ return null;
+ }
+ });
+ }
+
+ @Override
+ public Reference
+ getReference()
+ {
+ return _delegate.getReference();
+ }
+
+ @Override
+ public ConnectionI
+ getConnection()
+ {
+ return _delegate.getConnection();
+ }
+
+ private final RequestHandler _delegate;
+ private final QueueExecutorService _executor;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ReadyCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/ReadyCallback.java
new file mode 100644
index 00000000000..e4c1482c5fb
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ReadyCallback.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface ReadyCallback
+{
+ void ready(int op, boolean value);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Reference.java b/java-compat/src/Ice/src/main/java/IceInternal/Reference.java
new file mode 100644
index 00000000000..b7ea1dd2f32
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Reference.java
@@ -0,0 +1,547 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class Reference implements Cloneable
+{
+ public final static int ModeTwoway = 0;
+ public final static int ModeOneway = 1;
+ public final static int ModeBatchOneway = 2;
+ public final static int ModeDatagram = 3;
+ public final static int ModeBatchDatagram = 4;
+ public final static int ModeLast = ModeBatchDatagram;
+
+ public interface GetConnectionCallback
+ {
+ void setConnection(Ice.ConnectionI connection, boolean compress);
+ void setException(Ice.LocalException ex);
+ }
+
+ public final int
+ getMode()
+ {
+ return _mode;
+ }
+
+ public final boolean
+ getSecure()
+ {
+ return _secure;
+ }
+
+ public final Ice.ProtocolVersion
+ getProtocol()
+ {
+ return _protocol;
+ }
+
+ public final Ice.EncodingVersion
+ getEncoding()
+ {
+ return _encoding;
+ }
+
+ public final Ice.Identity
+ getIdentity()
+ {
+ return _identity;
+ }
+
+ public final String
+ getFacet()
+ {
+ return _facet;
+ }
+
+ public final Instance
+ getInstance()
+ {
+ return _instance;
+ }
+
+ public final java.util.Map<String, String>
+ getContext()
+ {
+ return _context;
+ }
+
+ public int
+ getInvocationTimeout()
+ {
+ return _invocationTimeout;
+ }
+
+ public final Ice.Communicator
+ getCommunicator()
+ {
+ return _communicator;
+ }
+
+ public abstract EndpointI[] getEndpoints();
+ public abstract String getAdapterId();
+ public abstract RouterInfo getRouterInfo();
+ public abstract LocatorInfo getLocatorInfo();
+ public abstract boolean getCollocationOptimized();
+ public abstract boolean getCacheConnection();
+ public abstract boolean getPreferSecure();
+ public abstract Ice.EndpointSelectionType getEndpointSelection();
+ public abstract int getLocatorCacheTimeout();
+ public abstract String getConnectionId();
+
+ //
+ // The change* methods (here and in derived classes) create
+ // a new reference based on the existing one, with the
+ // corresponding value changed.
+ //
+ public final Reference
+ changeContext(java.util.Map<String, String> newContext)
+ {
+ if(newContext == null)
+ {
+ newContext = _emptyContext;
+ }
+ Reference r = _instance.referenceFactory().copy(this);
+ if(newContext.isEmpty())
+ {
+ r._context = _emptyContext;
+ }
+ else
+ {
+ r._context = new java.util.HashMap<String, String>(newContext);
+ }
+ return r;
+ }
+
+ public final Reference
+ changeMode(int newMode)
+ {
+ if(newMode == _mode)
+ {
+ return this;
+ }
+ Reference r = _instance.referenceFactory().copy(this);
+ r._mode = newMode;
+ return r;
+ }
+
+ public Reference
+ changeSecure(boolean newSecure)
+ {
+ if(newSecure == _secure)
+ {
+ return this;
+ }
+ Reference r = _instance.referenceFactory().copy(this);
+ r._secure = newSecure;
+ return r;
+ }
+
+ public final Reference
+ changeIdentity(Ice.Identity newIdentity)
+ {
+ if(newIdentity.equals(_identity))
+ {
+ return this;
+ }
+ Reference r = _instance.referenceFactory().copy(this);
+ r._identity = newIdentity.clone();
+ return r;
+ }
+
+ public final Reference
+ changeFacet(String newFacet)
+ {
+ if(newFacet.equals(_facet))
+ {
+ return this;
+ }
+ Reference r = _instance.referenceFactory().copy(this);
+ r._facet = newFacet;
+ return r;
+ }
+
+ public final Reference
+ changeInvocationTimeout(int newTimeout)
+ {
+ if(newTimeout == _invocationTimeout)
+ {
+ return this;
+ }
+ Reference r = _instance.referenceFactory().copy(this);
+ r._invocationTimeout = newTimeout;
+ return r;
+ }
+
+ public Reference
+ changeEncoding(Ice.EncodingVersion newEncoding)
+ {
+ if(newEncoding.equals(_encoding))
+ {
+ return this;
+ }
+ Reference r = _instance.referenceFactory().copy(this);
+ r._encoding = newEncoding;
+ return r;
+ }
+
+ public Reference
+ changeCompress(boolean newCompress)
+ {
+ if(_overrideCompress && _compress == newCompress)
+ {
+ return this;
+ }
+ Reference r = _instance.referenceFactory().copy(this);
+ r._compress = newCompress;
+ r._overrideCompress = true;
+ return r;
+ }
+
+ public abstract Reference changeAdapterId(String newAdapterId);
+ public abstract Reference changeEndpoints(EndpointI[] newEndpoints);
+ public abstract Reference changeLocator(Ice.LocatorPrx newLocator);
+ public abstract Reference changeRouter(Ice.RouterPrx newRouter);
+ public abstract Reference changeCollocationOptimized(boolean newCollocationOptimized);
+ public abstract Reference changeCacheConnection(boolean newCache);
+ public abstract Reference changePreferSecure(boolean newPreferSecure);
+ public abstract Reference changeEndpointSelection(Ice.EndpointSelectionType newType);
+ public abstract Reference changeLocatorCacheTimeout(int newTimeout);
+
+ public abstract Reference changeTimeout(int newTimeout);
+ public abstract Reference changeConnectionId(String connectionId);
+
+ @Override
+ public synchronized int
+ hashCode()
+ {
+ if(_hashInitialized)
+ {
+ return _hashValue;
+ }
+
+ int h = 5381;
+ h = IceInternal.HashUtil.hashAdd(h, _mode);
+ h = IceInternal.HashUtil.hashAdd(h, _secure);
+ h = IceInternal.HashUtil.hashAdd(h, _identity);
+ h = IceInternal.HashUtil.hashAdd(h, _context);
+ h = IceInternal.HashUtil.hashAdd(h, _facet);
+ h = IceInternal.HashUtil.hashAdd(h, _overrideCompress);
+ if(_overrideCompress)
+ {
+ h = IceInternal.HashUtil.hashAdd(h, _compress);
+ }
+ h = IceInternal.HashUtil.hashAdd(h, _protocol);
+ h = IceInternal.HashUtil.hashAdd(h, _encoding);
+ h = IceInternal.HashUtil.hashAdd(h, _invocationTimeout);
+
+ _hashValue = h;
+ _hashInitialized = true;
+
+ return _hashValue;
+ }
+
+ //
+ // Utility methods
+ //
+ public abstract boolean isIndirect();
+ public abstract boolean isWellKnown();
+
+ //
+ // Marshal the reference.
+ //
+ public void
+ streamWrite(Ice.OutputStream s)
+ {
+ //
+ // Don't write the identity here. Operations calling streamWrite
+ // write the identity.
+ //
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ if(_facet.length() == 0)
+ {
+ s.writeStringSeq(null);
+ }
+ else
+ {
+ String[] facetPath = { _facet };
+ s.writeStringSeq(facetPath);
+ }
+
+ s.writeByte((byte)_mode);
+
+ s.writeBool(_secure);
+
+ if(!s.getEncoding().equals(Ice.Util.Encoding_1_0))
+ {
+ _protocol.__write(s);
+ _encoding.__write(s);
+ }
+
+ // Derived class writes the remainder of the reference.
+ }
+
+ //
+ // Convert the reference to its string form.
+ //
+ @Override
+ public String
+ toString()
+ {
+ //
+ // 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.
+ //
+ StringBuilder s = new StringBuilder(128);
+
+ //
+ // If the encoded identity string contains characters which
+ // the reference parser uses as separators, then we enclose
+ // the identity string in quotes.
+ //
+ String id = Ice.Util.identityToString(_identity);
+ if(IceUtilInternal.StringUtil.findFirstOf(id, " :@") != -1)
+ {
+ s.append('"');
+ s.append(id);
+ s.append('"');
+ }
+ else
+ {
+ s.append(id);
+ }
+
+ if(_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.append(" -f ");
+ String fs = IceUtilInternal.StringUtil.escapeString(_facet, "");
+ if(IceUtilInternal.StringUtil.findFirstOf(fs, " :@") != -1)
+ {
+ s.append('"');
+ s.append(fs);
+ s.append('"');
+ }
+ else
+ {
+ s.append(fs);
+ }
+ }
+
+ switch(_mode)
+ {
+ case ModeTwoway:
+ {
+ s.append(" -t");
+ break;
+ }
+
+ case ModeOneway:
+ {
+ s.append(" -o");
+ break;
+ }
+
+ case ModeBatchOneway:
+ {
+ s.append(" -O");
+ break;
+ }
+
+ case ModeDatagram:
+ {
+ s.append(" -d");
+ break;
+ }
+
+ case ModeBatchDatagram:
+ {
+ s.append(" -D");
+ break;
+ }
+ }
+
+ if(_secure)
+ {
+ s.append(" -s");
+ }
+
+ if(!_protocol.equals(Ice.Util.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.append(" -p ");
+ s.append(Ice.Util.protocolVersionToString(_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.append(" -e ");
+ s.append(Ice.Util.encodingVersionToString(_encoding));
+
+ return s.toString();
+
+ // Derived class writes the remainder of the string.
+ }
+
+ //
+ // Convert the reference to its property form.
+ //
+ public abstract java.util.Map<String, String> toProperty(String prefix);
+
+ public abstract RequestHandler getRequestHandler(Ice.ObjectPrxHelperBase proxy);
+
+ public abstract BatchRequestQueue getBatchRequestQueue();
+
+ @Override
+ public boolean
+ equals(java.lang.Object obj)
+ {
+ //
+ // Note: if(this == obj) and type test are performed by each non-abstract derived class.
+ //
+
+ Reference r = (Reference)obj; // Guaranteed to succeed.
+
+ if(_mode != r._mode)
+ {
+ return false;
+ }
+
+ if(_secure != r._secure)
+ {
+ return false;
+ }
+
+ if(!_identity.equals(r._identity))
+ {
+ return false;
+ }
+
+ if(!_context.equals(r._context))
+ {
+ return false;
+ }
+
+ if(!_facet.equals(r._facet))
+ {
+ return false;
+ }
+
+ if(_overrideCompress != r._overrideCompress)
+ {
+ return false;
+ }
+ if(_overrideCompress && _compress != r._compress)
+ {
+ return false;
+ }
+
+ if(!_protocol.equals(r._protocol))
+ {
+ return false;
+ }
+
+ if(!_encoding.equals(r._encoding))
+ {
+ return false;
+ }
+
+ if(_invocationTimeout != r._invocationTimeout)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public Reference clone()
+ {
+ Reference c = null;
+ try
+ {
+ c = (Reference)super.clone();
+ }
+ catch(CloneNotSupportedException ex)
+ {
+ assert false;
+ }
+ return c;
+ }
+
+ protected int _hashValue;
+ protected boolean _hashInitialized;
+ private static java.util.Map<String, String> _emptyContext = new java.util.HashMap<String, String>();
+
+ final private Instance _instance;
+ final private Ice.Communicator _communicator;
+
+ private int _mode;
+ private boolean _secure;
+ private Ice.Identity _identity;
+ private java.util.Map<String, String> _context;
+ private String _facet;
+ private Ice.ProtocolVersion _protocol;
+ private Ice.EncodingVersion _encoding;
+ private int _invocationTimeout;
+ protected boolean _overrideCompress;
+ protected boolean _compress; // Only used if _overrideCompress == true
+
+ protected
+ Reference(Instance instance,
+ Ice.Communicator communicator,
+ Ice.Identity identity,
+ String facet,
+ int mode,
+ boolean secure,
+ Ice.ProtocolVersion protocol,
+ Ice.EncodingVersion encoding,
+ int invocationTimeout,
+ java.util.Map<String, String> context)
+ {
+ //
+ // Validate string arguments.
+ //
+ assert(identity.name != null);
+ assert(identity.category != null);
+ assert(facet != null);
+
+ _instance = instance;
+ _communicator = communicator;
+ _mode = mode;
+ _secure = secure;
+ _identity = identity;
+ _context = context != null ? new java.util.HashMap<String, String>(context) : _emptyContext;
+ _facet = facet;
+ _protocol = protocol;
+ _encoding = encoding;
+ _invocationTimeout = invocationTimeout;
+ _hashInitialized = false;
+ _overrideCompress = false;
+ _compress = false;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ReferenceFactory.java b/java-compat/src/Ice/src/main/java/IceInternal/ReferenceFactory.java
new file mode 100644
index 00000000000..ed36537017e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ReferenceFactory.java
@@ -0,0 +1,916 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class ReferenceFactory
+{
+ public Reference
+ create(Ice.Identity ident, String facet, Reference tmpl, EndpointI[] endpoints)
+ {
+ if(ident.name.length() == 0 && ident.category.length() == 0)
+ {
+ return null;
+ }
+
+ return create(ident, facet, tmpl.getMode(), tmpl.getSecure(), tmpl.getProtocol(), tmpl.getEncoding(),
+ endpoints, null, null);
+ }
+
+ public Reference
+ create(Ice.Identity ident, String facet, Reference tmpl, String adapterId)
+ {
+ if(ident.name.length() == 0 && ident.category.length() == 0)
+ {
+ return null;
+ }
+
+ return create(ident, facet, tmpl.getMode(), tmpl.getSecure(), tmpl.getProtocol(), tmpl.getEncoding(), null,
+ adapterId, null);
+ }
+
+ public Reference
+ create(Ice.Identity ident, Ice.ConnectionI fixedConnection)
+ {
+ if(ident.name.length() == 0 && ident.category.length() == 0)
+ {
+ return null;
+ }
+
+ //
+ // Create new reference
+ //
+ return new FixedReference(
+ _instance,
+ _communicator,
+ ident,
+ "", // Facet
+ fixedConnection.endpoint().datagram() ? Reference.ModeDatagram : Reference.ModeTwoway,
+ fixedConnection.endpoint().secure(),
+ _instance.defaultsAndOverrides().defaultEncoding,
+ fixedConnection);
+ }
+
+ public Reference
+ copy(Reference r)
+ {
+ Ice.Identity ident = r.getIdentity();
+ if(ident.name.length() == 0 && ident.category.length() == 0)
+ {
+ return null;
+ }
+ return r.clone();
+ }
+
+ public Reference
+ create(String s, String propertyPrefix)
+ {
+ if(s == null || s.length() == 0)
+ {
+ return null;
+ }
+
+ final String delim = " \t\n\r";
+
+ int beg;
+ int end = 0;
+
+ beg = IceUtilInternal.StringUtil.findFirstNotOf(s, delim, end);
+ if(beg == -1)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "no non-whitespace characters found in `" + s + "'";
+ throw e;
+ }
+
+ //
+ // Extract the identity, which may be enclosed in single
+ // or double quotation marks.
+ //
+ String idstr = null;
+ end = IceUtilInternal.StringUtil.checkQuote(s, beg);
+ if(end == -1)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "mismatched quotes around identity in `" + s + "'";
+ throw e;
+ }
+ else if(end == 0)
+ {
+ end = IceUtilInternal.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)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "no identity in `" + s + "'";
+ throw e;
+ }
+
+ //
+ // Parsing the identity may raise IdentityParseException.
+ //
+ Ice.Identity ident = Ice.Util.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)
+ {
+ Ice.IllegalIdentityException e = new Ice.IllegalIdentityException();
+ e.id = ident;
+ throw e;
+ }
+ //
+ // 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(IceUtilInternal.StringUtil.findFirstNotOf(s, delim, end) != -1)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "invalid characters after identity in `" + s + "'";
+ throw e;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ String facet = "";
+ int mode = Reference.ModeTwoway;
+ boolean secure = false;
+ Ice.EncodingVersion encoding = _instance.defaultsAndOverrides().defaultEncoding;
+ Ice.ProtocolVersion protocol = Ice.Util.Protocol_1_0;
+ String adapter = "";
+
+ while(true)
+ {
+ beg = IceUtilInternal.StringUtil.findFirstNotOf(s, delim, end);
+ if(beg == -1)
+ {
+ break;
+ }
+
+ if(s.charAt(beg) == ':' || s.charAt(beg) == '@')
+ {
+ break;
+ }
+
+ end = IceUtilInternal.StringUtil.findFirstOf(s, delim + ":@", beg);
+ if(end == -1)
+ {
+ end = s.length();
+ }
+
+ if(beg == end)
+ {
+ break;
+ }
+
+ String option = s.substring(beg, end);
+ if(option.length() != 2 || option.charAt(0) != '-')
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "expected a proxy option but found `" + option + "' in `" + s + "'";
+ throw e;
+ }
+
+ //
+ // Check for the presence of an option argument. The
+ // argument may be enclosed in single or double
+ // quotation marks.
+ //
+ String argument = null;
+ int argumentBeg = IceUtilInternal.StringUtil.findFirstNotOf(s, delim, end);
+ if(argumentBeg != -1)
+ {
+ final char ch = s.charAt(argumentBeg);
+ if(ch != '@' && ch != ':' && ch != '-')
+ {
+ beg = argumentBeg;
+ end = IceUtilInternal.StringUtil.checkQuote(s, beg);
+ if(end == -1)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "mismatched quotes around value for " + option + " option in `" + s + "'";
+ throw e;
+ }
+ else if(end == 0)
+ {
+ end = IceUtilInternal.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)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "no argument provided for -f option in `" + s + "'";
+ throw e;
+ }
+
+ try
+ {
+ facet = IceUtilInternal.StringUtil.unescapeString(argument, 0, argument.length());
+ }
+ catch(IllegalArgumentException ex)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "invalid facet in `" + s + "': " + ex.getMessage();
+ throw e;
+ }
+
+ break;
+ }
+
+ case 't':
+ {
+ if(argument != null)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "unexpected argument `" + argument + "' provided for -t option in `" + s + "'";
+ throw e;
+ }
+ mode = Reference.ModeTwoway;
+ break;
+ }
+
+ case 'o':
+ {
+ if(argument != null)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "unexpected argument `" + argument + "' provided for -o option in `" + s + "'";
+ throw e;
+ }
+ mode = Reference.ModeOneway;
+ break;
+ }
+
+ case 'O':
+ {
+ if(argument != null)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "unexpected argument `" + argument + "' provided for -O option in `" + s + "'";
+ throw e;
+ }
+ mode = Reference.ModeBatchOneway;
+ break;
+ }
+
+ case 'd':
+ {
+ if(argument != null)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "unexpected argument `" + argument + "' provided for -d option in `" + s + "'";
+ throw e;
+ }
+ mode = Reference.ModeDatagram;
+ break;
+ }
+
+ case 'D':
+ {
+ if(argument != null)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "unexpected argument `" + argument + "' provided for -D option in `" + s + "'";
+ throw e;
+ }
+ mode = Reference.ModeBatchDatagram;
+ break;
+ }
+
+ case 's':
+ {
+ if(argument != null)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "unexpected argument `" + argument + "' provided for -s option in `" + s + "'";
+ throw e;
+ }
+ secure = true;
+ break;
+ }
+
+ case 'e':
+ {
+ if(argument == null)
+ {
+ throw new Ice.ProxyParseException("no argument provided for -e option in `" + s + "'");
+ }
+
+ try
+ {
+ encoding = Ice.Util.stringToEncodingVersion(argument);
+ }
+ catch(Ice.VersionParseException e)
+ {
+ 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.Util.stringToProtocolVersion(argument);
+ }
+ catch(Ice.VersionParseException e)
+ {
+ throw new Ice.ProxyParseException("invalid protocol version `" + argument + "' in `" + s +
+ "':\n" + e.str);
+ }
+ break;
+ }
+
+ default:
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "unknown option `" + option + "' in `" + s + "'";
+ throw e;
+ }
+ }
+ }
+
+ if(beg == -1)
+ {
+ return create(ident, facet, mode, secure, protocol, encoding, null, null, propertyPrefix);
+ }
+
+ java.util.ArrayList<EndpointI> endpoints = new java.util.ArrayList<EndpointI>();
+
+ if(s.charAt(beg) == ':')
+ {
+ java.util.ArrayList<String> unknownEndpoints = new java.util.ArrayList<String>();
+ 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
+ {
+ boolean quoted = false;
+ int 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;
+ }
+ }
+
+ String es = s.substring(beg, end);
+ EndpointI endp = _instance.endpointFactoryManager().create(es, false);
+ if(endp != null)
+ {
+ endpoints.add(endp);
+ }
+ else
+ {
+ unknownEndpoints.add(es);
+ }
+ }
+ if(endpoints.size() == 0)
+ {
+ assert(!unknownEndpoints.isEmpty());
+ Ice.EndpointParseException e = new Ice.EndpointParseException();
+ e.str = "invalid endpoint `" + unknownEndpoints.get(0) + "' in `" + s + "'";
+ throw e;
+ }
+ else if(unknownEndpoints.size() != 0 &&
+ _instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Endpoints", 1) > 0)
+ {
+ StringBuffer msg = new StringBuffer("Proxy contains unknown endpoints:");
+ for(String e : unknownEndpoints)
+ {
+ msg.append(" `");
+ msg.append(e);
+ msg.append("'");
+ }
+ _instance.initializationData().logger.warning(msg.toString());
+ }
+
+ EndpointI[] endp = new EndpointI[endpoints.size()];
+ endpoints.toArray(endp);
+ return create(ident, facet, mode, secure, protocol, encoding, endp, null, propertyPrefix);
+ }
+ else if(s.charAt(beg) == '@')
+ {
+ beg = IceUtilInternal.StringUtil.findFirstNotOf(s, delim, beg + 1);
+ if(beg == -1)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "missing adapter id in `" + s + "'";
+ throw e;
+ }
+
+ String adapterstr = null;
+ end = IceUtilInternal.StringUtil.checkQuote(s, beg);
+ if(end == -1)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "mismatched quotes around adapter id in `" + s + "'";
+ throw e;
+ }
+ else if(end == 0)
+ {
+ end = IceUtilInternal.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() && IceUtilInternal.StringUtil.findFirstNotOf(s, delim, end) != -1)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "invalid trailing characters after `" + s.substring(0, end + 1) + "' in `" + s + "'";
+ throw e;
+ }
+
+ try
+ {
+ adapter = IceUtilInternal.StringUtil.unescapeString(adapterstr, 0, adapterstr.length());
+ }
+ catch(IllegalArgumentException ex)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "invalid adapter id in `" + s + "': " + ex.getMessage();
+ throw e;
+ }
+ if(adapter.length() == 0)
+ {
+ Ice.ProxyParseException e = new Ice.ProxyParseException();
+ e.str = "empty adapter id in `" + s + "'";
+ throw e;
+ }
+ return create(ident, facet, mode, secure, protocol, encoding, null, adapter, propertyPrefix);
+ }
+
+ Ice.ProxyParseException ex = new Ice.ProxyParseException();
+ ex.str = "malformed proxy `" + s + "'";
+ throw ex;
+ }
+
+ public Reference
+ create(Ice.Identity ident, Ice.InputStream 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.
+ //
+ String[] facetPath = s.readStringSeq();
+ String facet;
+ if(facetPath.length > 0)
+ {
+ if(facetPath.length > 1)
+ {
+ throw new Ice.ProxyUnmarshalException();
+ }
+ facet = facetPath[0];
+ }
+ else
+ {
+ facet = "";
+ }
+
+ int mode = s.readByte();
+ if(mode < 0 || mode > Reference.ModeLast)
+ {
+ throw new Ice.ProxyUnmarshalException();
+ }
+
+ boolean secure = s.readBool();
+
+ Ice.ProtocolVersion protocol;
+ Ice.EncodingVersion encoding;
+ if(!s.getEncoding().equals(Ice.Util.Encoding_1_0))
+ {
+ protocol = new Ice.ProtocolVersion();
+ protocol.__read(s);
+ encoding = new Ice.EncodingVersion();
+ encoding.__read(s);
+ }
+ else
+ {
+ protocol = Ice.Util.Protocol_1_0;
+ encoding = Ice.Util.Encoding_1_0;
+ }
+
+ EndpointI[] endpoints = null;
+ String adapterId = null;
+
+ int sz = s.readSize();
+ if(sz > 0)
+ {
+ endpoints = new EndpointI[sz];
+ for(int i = 0; i < sz; i++)
+ {
+ endpoints[i] = _instance.endpointFactoryManager().read(s);
+ }
+ }
+ else
+ {
+ adapterId = s.readString();
+ }
+
+ return create(ident, facet, mode, secure, protocol, encoding, endpoints, adapterId, null);
+ }
+
+ public ReferenceFactory
+ setDefaultRouter(Ice.RouterPrx defaultRouter)
+ {
+ if(_defaultRouter == null ? defaultRouter == null : _defaultRouter.equals(defaultRouter))
+ {
+ return this;
+ }
+
+ ReferenceFactory factory = new ReferenceFactory(_instance, _communicator);
+ factory._defaultLocator = _defaultLocator;
+ factory._defaultRouter = defaultRouter;
+ return factory;
+ }
+
+ public Ice.RouterPrx
+ getDefaultRouter()
+ {
+ return _defaultRouter;
+ }
+
+ public ReferenceFactory
+ setDefaultLocator(Ice.LocatorPrx defaultLocator)
+ {
+ if(_defaultLocator == null ? defaultLocator == null : _defaultLocator.equals(defaultLocator))
+ {
+ return this;
+ }
+
+ ReferenceFactory factory = new ReferenceFactory(_instance, _communicator);
+ factory._defaultRouter = _defaultRouter;
+ factory._defaultLocator = defaultLocator;
+ return factory;
+ }
+
+ public Ice.LocatorPrx
+ getDefaultLocator()
+ {
+ return _defaultLocator;
+ }
+
+ //
+ // Only for use by Instance
+ //
+ ReferenceFactory(Instance instance, Ice.Communicator communicator)
+ {
+ _instance = instance;
+ _communicator = communicator;
+ }
+
+ static private String[] _suffixes =
+ {
+ "EndpointSelection",
+ "ConnectionCached",
+ "PreferSecure",
+ "LocatorCacheTimeout",
+ "InvocationTimeout",
+ "Locator",
+ "Router",
+ "CollocationOptimized",
+ "Context\\..*"
+ };
+
+ private void
+ checkForUnknownProperties(String prefix)
+ {
+ //
+ // Do not warn about unknown properties if Ice prefix, ie Ice, Glacier2, etc
+ //
+ for(int i = 0; IceInternal.PropertyNames.clPropNames[i] != null; ++i)
+ {
+ if(prefix.startsWith(IceInternal.PropertyNames.clPropNames[i] + "."))
+ {
+ return;
+ }
+ }
+
+ java.util.ArrayList<String> unknownProps = new java.util.ArrayList<String>();
+ java.util.Map<String, String> props =
+ _instance.initializationData().properties.getPropertiesForPrefix(prefix + ".");
+ for(java.util.Map.Entry<String, String> p : props.entrySet())
+ {
+ String prop = p.getKey();
+
+ boolean valid = false;
+ for(String suffix : _suffixes)
+ {
+ String pattern = java.util.regex.Pattern.quote(prefix + ".") + suffix;
+ if(java.util.regex.Pattern.compile(pattern).matcher(prop).matches())
+ {
+ valid = true;
+ break;
+ }
+ }
+
+ if(!valid)
+ {
+ unknownProps.add(prop);
+ }
+ }
+
+ if(unknownProps.size() != 0)
+ {
+ StringBuffer message = new StringBuffer("found unknown properties for proxy '");
+ message.append(prefix);
+ message.append("':");
+ for(String s : unknownProps)
+ {
+ message.append("\n ");
+ message.append(s);
+ }
+ _instance.initializationData().logger.warning(message.toString());
+ }
+ }
+
+ private Reference
+ create(Ice.Identity ident, String facet, int mode, boolean secure, Ice.ProtocolVersion protocol,
+ Ice.EncodingVersion encoding, EndpointI[] endpoints, String adapterId, String propertyPrefix)
+ {
+ DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+
+ //
+ // Default local proxy options.
+ //
+ LocatorInfo locatorInfo = null;
+ if(_defaultLocator != null)
+ {
+ if(!((Ice.ObjectPrxHelperBase)_defaultLocator).__reference().getEncoding().equals(encoding))
+ {
+ locatorInfo = _instance.locatorManager().get(
+ (Ice.LocatorPrx)_defaultLocator.ice_encodingVersion(encoding));
+ }
+ else
+ {
+ locatorInfo = _instance.locatorManager().get(_defaultLocator);
+ }
+ }
+ RouterInfo routerInfo = _instance.routerManager().get(_defaultRouter);
+ boolean collocationOptimized = defaultsAndOverrides.defaultCollocationOptimization;
+ boolean cacheConnection = true;
+ boolean preferSecure = defaultsAndOverrides.defaultPreferSecure;
+ Ice.EndpointSelectionType endpointSelection = defaultsAndOverrides.defaultEndpointSelection;
+ int locatorCacheTimeout = defaultsAndOverrides.defaultLocatorCacheTimeout;
+ int invocationTimeout = defaultsAndOverrides.defaultInvocationTimeout;
+ java.util.Map<String, String> context = null;
+
+ //
+ // Override the defaults with the proxy properties if a property prefix is defined.
+ //
+ if(propertyPrefix != null && propertyPrefix.length() > 0)
+ {
+ Ice.Properties properties = _instance.initializationData().properties;
+
+ //
+ // Warn about unknown properties.
+ //
+ if(properties.getPropertyAsIntWithDefault("Ice.Warn.UnknownProperties", 1) > 0)
+ {
+ checkForUnknownProperties(propertyPrefix);
+ }
+
+ String property;
+
+ property = propertyPrefix + ".Locator";
+ Ice.LocatorPrx locator = Ice.LocatorPrxHelper.uncheckedCast(_communicator.propertyToProxy(property));
+ if(locator != null)
+ {
+ if(!((Ice.ObjectPrxHelperBase)locator).__reference().getEncoding().equals(encoding))
+ {
+ locatorInfo = _instance.locatorManager().get((Ice.LocatorPrx)locator.ice_encodingVersion(encoding));
+ }
+ else
+ {
+ locatorInfo = _instance.locatorManager().get(locator);
+ }
+ }
+
+ property = propertyPrefix + ".Router";
+ Ice.RouterPrx router = Ice.RouterPrxHelper.uncheckedCast(_communicator.propertyToProxy(property));
+ if(router != null)
+ {
+ if(propertyPrefix.endsWith(".Router"))
+ {
+ String s = "`" + property + "=" + properties.getProperty(property) +
+ "': cannot set a router on a router; setting ignored";
+ _instance.initializationData().logger.warning(s);
+ }
+ else
+ {
+ routerInfo = _instance.routerManager().get(router);
+ }
+ }
+
+ property = propertyPrefix + ".CollocationOptimized";
+ collocationOptimized = properties.getPropertyAsIntWithDefault(property, collocationOptimized ? 1 : 0) > 0;
+
+ 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)
+ {
+ String type = properties.getProperty(property);
+ if(type.equals("Random"))
+ {
+ endpointSelection = Ice.EndpointSelectionType.Random;
+ }
+ else if(type.equals("Ordered"))
+ {
+ endpointSelection = Ice.EndpointSelectionType.Ordered;
+ }
+ else
+ {
+ throw new Ice.EndpointSelectionTypeParseException("illegal value `" + type +
+ "'; expected `Random' or `Ordered'");
+ }
+ }
+
+ property = propertyPrefix + ".LocatorCacheTimeout";
+ String value = properties.getProperty(property);
+ if(!value.isEmpty())
+ {
+ locatorCacheTimeout = properties.getPropertyAsIntWithDefault(property, locatorCacheTimeout);
+ if(locatorCacheTimeout < -1)
+ {
+ locatorCacheTimeout = -1;
+
+ StringBuffer msg = new StringBuffer("invalid value for ");
+ msg.append(property);
+ msg.append(" '");
+ msg.append(properties.getProperty(property));
+ msg.append("': defaulting to -1");
+ _instance.initializationData().logger.warning(msg.toString());
+ }
+ }
+
+ property = propertyPrefix + ".InvocationTimeout";
+ value = properties.getProperty(property);
+ if(!value.isEmpty())
+ {
+ invocationTimeout = properties.getPropertyAsIntWithDefault(property, locatorCacheTimeout);
+ if(invocationTimeout < 1 && invocationTimeout != -1)
+ {
+ invocationTimeout = -1;
+
+ StringBuffer msg = new StringBuffer("invalid value for ");
+ msg.append(property);
+ msg.append(" '");
+ msg.append(properties.getProperty(property));
+ msg.append("': defaulting to -1");
+ _instance.initializationData().logger.warning(msg.toString());
+ }
+ }
+
+ property = propertyPrefix + ".Context.";
+ java.util.Map<String, String> contexts = properties.getPropertiesForPrefix(property);
+ if(!contexts.isEmpty())
+ {
+ context = new java.util.HashMap<String, String>();
+ for(java.util.Map.Entry<String, String> e : contexts.entrySet())
+ {
+ context.put(e.getKey().substring(property.length()), e.getValue());
+ }
+ }
+ }
+
+ //
+ // Create new reference
+ //
+ return new RoutableReference(_instance,
+ _communicator,
+ ident,
+ facet,
+ mode,
+ secure,
+ protocol,
+ encoding,
+ endpoints,
+ adapterId,
+ locatorInfo,
+ routerInfo,
+ collocationOptimized,
+ cacheConnection,
+ preferSecure,
+ endpointSelection,
+ locatorCacheTimeout,
+ invocationTimeout,
+ context);
+ }
+
+ final private Instance _instance;
+ final private Ice.Communicator _communicator;
+ private Ice.RouterPrx _defaultRouter;
+ private Ice.LocatorPrx _defaultLocator;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RemoteObserverI.java b/java-compat/src/Ice/src/main/java/IceInternal/RemoteObserverI.java
new file mode 100644
index 00000000000..f7c35f706eb
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/RemoteObserverI.java
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class RemoteObserverI
+ extends IceMX.ObserverWithDelegate<IceMX.RemoteMetrics, Ice.Instrumentation.RemoteObserver>
+ implements Ice.Instrumentation.RemoteObserver
+{
+ @Override
+ public void
+ reply(final int size)
+ {
+ forEach(new MetricsUpdate<IceMX.RemoteMetrics>()
+ {
+ @Override
+ public void
+ update(IceMX.RemoteMetrics v)
+ {
+ v.replySize += size;
+ }
+ });
+ if(_delegate != null)
+ {
+ _delegate.reply(size);
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ReplyStatus.java b/java-compat/src/Ice/src/main/java/IceInternal/ReplyStatus.java
new file mode 100644
index 00000000000..20b2cc32dd1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ReplyStatus.java
@@ -0,0 +1,22 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+interface ReplyStatus
+{
+ static final byte replyOK = 0;
+ static final byte replyUserException = 1;
+ static final byte replyObjectNotExist = 2;
+ static final byte replyFacetNotExist = 3;
+ static final byte replyOperationNotExist = 4;
+ static final byte replyUnknownLocalException = 5;
+ static final byte replyUnknownUserException = 6;
+ static final byte replyUnknownException = 7;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RequestHandler.java b/java-compat/src/Ice/src/main/java/IceInternal/RequestHandler.java
new file mode 100644
index 00000000000..5fa3485400d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/RequestHandler.java
@@ -0,0 +1,22 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface RequestHandler extends CancellationHandler
+{
+ RequestHandler update(RequestHandler previousHandler, RequestHandler newHandler);
+
+ int sendAsyncRequest(ProxyOutgoingAsyncBase out)
+ throws RetryException;
+
+ Reference getReference();
+
+ Ice.ConnectionI getConnection();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RequestHandlerFactory.java b/java-compat/src/Ice/src/main/java/IceInternal/RequestHandlerFactory.java
new file mode 100644
index 00000000000..ff4022724a9
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/RequestHandlerFactory.java
@@ -0,0 +1,96 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.concurrent.Callable;
+
+public final class RequestHandlerFactory
+{
+ RequestHandlerFactory(Instance instance)
+ {
+ _instance = instance;
+ }
+
+ public RequestHandler
+ getRequestHandler(final RoutableReference ref, Ice.ObjectPrxHelperBase proxy)
+ {
+ if(ref.getCollocationOptimized())
+ {
+ Ice.ObjectAdapter adapter = _instance.objectAdapterFactory().findObjectAdapter(proxy);
+ if(adapter != null)
+ {
+ return proxy.__setRequestHandler(new CollocatedRequestHandler(ref, adapter));
+ }
+ }
+
+ ConnectRequestHandler handler = null;
+ boolean connect = false;
+ if(ref.getCacheConnection())
+ {
+ synchronized(this)
+ {
+ handler = _handlers.get(ref);
+ if(handler == null)
+ {
+ handler = new ConnectRequestHandler(ref, proxy);
+ _handlers.put(ref, handler);
+ connect = true;
+ }
+ }
+ }
+ else
+ {
+ handler = new ConnectRequestHandler(ref, proxy);
+ connect = true;
+ }
+
+ if(connect)
+ {
+ if(_instance.queueRequests())
+ {
+ final ConnectRequestHandler h = handler;
+ _instance.getQueueExecutor().executeNoThrow(new Callable<Void>()
+ {
+ @Override
+ public Void call()
+ {
+ ref.getConnection(h);
+ return null;
+ }
+ });
+ }
+ else
+ {
+ ref.getConnection(handler);
+ }
+ }
+ return proxy.__setRequestHandler(handler.connect(proxy));
+ }
+
+ void
+ removeRequestHandler(Reference ref, RequestHandler handler)
+ {
+ if(ref.getCacheConnection())
+ {
+ synchronized(this)
+ {
+ if(_handlers.get(ref) == handler)
+ {
+ _handlers.remove(ref);
+ }
+ }
+ }
+ }
+
+ private final Instance _instance;
+ private final Map<Reference, ConnectRequestHandler> _handlers = new HashMap<Reference, ConnectRequestHandler>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ResponseHandler.java b/java-compat/src/Ice/src/main/java/IceInternal/ResponseHandler.java
new file mode 100644
index 00000000000..401d80e5451
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ResponseHandler.java
@@ -0,0 +1,18 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface ResponseHandler
+{
+ void sendResponse(int requestId, Ice.OutputStream os, byte status, boolean amd);
+ void sendNoResponse();
+ boolean systemException(int requestId, Ice.SystemException ex, boolean amd);
+ void invokeException(int requestId, Ice.LocalException ex, int invokeNum, boolean amd);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RetryException.java b/java-compat/src/Ice/src/main/java/IceInternal/RetryException.java
new file mode 100644
index 00000000000..463a675b24a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/RetryException.java
@@ -0,0 +1,27 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class RetryException extends Exception
+{
+ public
+ RetryException(Ice.LocalException ex)
+ {
+ _ex = ex;
+ }
+
+ public Ice.LocalException
+ get()
+ {
+ return _ex;
+ }
+
+ private Ice.LocalException _ex;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RetryQueue.java b/java-compat/src/Ice/src/main/java/IceInternal/RetryQueue.java
new file mode 100644
index 00000000000..f495e6ecbcc
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/RetryQueue.java
@@ -0,0 +1,84 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class RetryQueue
+{
+ RetryQueue(Instance instance)
+ {
+ _instance = instance;
+ }
+
+ synchronized public void add(ProxyOutgoingAsyncBase outAsync, int interval)
+ {
+ if(_instance == null)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+ RetryTask task = new RetryTask(_instance, this, outAsync);
+ outAsync.cancelable(task); // This will throw if the request is canceled
+ task.setFuture(_instance.timer().schedule(task, interval, java.util.concurrent.TimeUnit.MILLISECONDS));
+ _requests.add(task);
+ }
+
+ synchronized public void destroy()
+ {
+ if(_instance == null)
+ {
+ return; // Already destroyed.
+ }
+
+ java.util.HashSet<RetryTask> keep = new java.util.HashSet<RetryTask>();
+ for(RetryTask task : _requests)
+ {
+ if(!task.destroy())
+ {
+ keep.add(task);
+ }
+ }
+ _requests = keep;
+ _instance = null;
+
+ //
+ // Wait for the tasks to be executed, it shouldn't take long
+ // since they couldn't be canceled. If interrupted, we
+ // preserve the interrupt.
+ //
+ boolean interrupted = false;
+ while(!_requests.isEmpty())
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ interrupted = true;
+ }
+ }
+ if(interrupted)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ synchronized boolean remove(RetryTask task)
+ {
+ boolean removed = _requests.remove(task);
+ if(_instance == null && _requests.isEmpty())
+ {
+ notify();
+ }
+ return removed;
+ }
+
+ private Instance _instance;
+ private java.util.HashSet<RetryTask> _requests = new java.util.HashSet<RetryTask>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RetryTask.java b/java-compat/src/Ice/src/main/java/IceInternal/RetryTask.java
new file mode 100644
index 00000000000..a9b4b1d1119
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/RetryTask.java
@@ -0,0 +1,80 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+class RetryTask implements Runnable, CancellationHandler
+{
+ RetryTask(Instance instance, RetryQueue queue, ProxyOutgoingAsyncBase outAsync)
+ {
+ _instance = instance;
+ _queue = queue;
+ _outAsync = outAsync;
+ }
+
+ @Override
+ public void run()
+ {
+ _outAsync.retry();
+
+ //
+ // NOTE: this must be called last, destroy() blocks until all task
+ // are removed to prevent the client thread pool to be destroyed
+ // (we still need the client thread pool at this point to call
+ // exception callbacks with CommunicatorDestroyedException).
+ //
+ _queue.remove(this);
+ }
+
+ @Override
+ public void asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex)
+ {
+ if(_queue.remove(this) && _future.cancel(false))
+ {
+ if(_instance.traceLevels().retry >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("operation retry canceled\n");
+ s.append(Ex.toString(ex));
+ _instance.initializationData().logger.trace(_instance.traceLevels().retryCat, s.toString());
+ }
+ if(_outAsync.completed(ex))
+ {
+ _outAsync.invokeCompletedAsync();
+ }
+ }
+ }
+
+ public boolean destroy()
+ {
+ if(_future.cancel(false))
+ {
+ try
+ {
+ _outAsync.abort(new Ice.CommunicatorDestroyedException());
+ }
+ catch(Ice.CommunicatorDestroyedException ex)
+ {
+ // Abort can throw if there's no callback, just ignore in this case
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public void setFuture(java.util.concurrent.Future<?> future)
+ {
+ _future = future;
+ }
+
+ private final Instance _instance;
+ private final RetryQueue _queue;
+ private final ProxyOutgoingAsyncBase _outAsync;
+ private java.util.concurrent.Future<?> _future;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java b/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java
new file mode 100644
index 00000000000..688b2ca9935
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java
@@ -0,0 +1,974 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class RoutableReference extends Reference
+{
+ @Override
+ public final EndpointI[]
+ getEndpoints()
+ {
+ return _endpoints;
+ }
+
+ @Override
+ public final String
+ getAdapterId()
+ {
+ return _adapterId;
+ }
+
+ @Override
+ public final LocatorInfo
+ getLocatorInfo()
+ {
+ return _locatorInfo;
+ }
+
+ @Override
+ public final RouterInfo
+ getRouterInfo()
+ {
+ return _routerInfo;
+ }
+
+ @Override
+ public final boolean
+ getCollocationOptimized()
+ {
+ return _collocationOptimized;
+ }
+
+ @Override
+ public final boolean
+ getCacheConnection()
+ {
+ return _cacheConnection;
+ }
+
+ @Override
+ public final boolean
+ getPreferSecure()
+ {
+ return _preferSecure;
+ }
+
+ @Override
+ public final Ice.EndpointSelectionType
+ getEndpointSelection()
+ {
+ return _endpointSelection;
+ }
+
+ @Override
+ public final int
+ getLocatorCacheTimeout()
+ {
+ return _locatorCacheTimeout;
+ }
+
+ @Override
+ public final String
+ getConnectionId()
+ {
+ return _connectionId;
+ }
+
+ @Override
+ public Reference
+ changeEncoding(Ice.EncodingVersion newEncoding)
+ {
+ RoutableReference r = (RoutableReference)super.changeEncoding(newEncoding);
+ if(r != this)
+ {
+ LocatorInfo locInfo = r._locatorInfo;
+ if(locInfo != null && !locInfo.getLocator().ice_getEncodingVersion().equals(newEncoding))
+ {
+ r._locatorInfo = getInstance().locatorManager().get(
+ (Ice.LocatorPrx)locInfo.getLocator().ice_encodingVersion(newEncoding));
+ }
+ }
+ return r;
+ }
+
+ @Override
+ public Reference
+ changeCompress(boolean newCompress)
+ {
+ RoutableReference r = (RoutableReference)super.changeCompress(newCompress);
+ if(r != this && _endpoints.length > 0) // Also override the compress flag on the endpoints if it was updated.
+ {
+ EndpointI[] newEndpoints = new EndpointI[_endpoints.length];
+ for(int i = 0; i < _endpoints.length; i++)
+ {
+ newEndpoints[i] = _endpoints[i].compress(newCompress);
+ }
+ r._endpoints = newEndpoints;
+ }
+ return r;
+ }
+
+ @Override
+ public Reference
+ changeEndpoints(EndpointI[] newEndpoints)
+ {
+ if(java.util.Arrays.equals(newEndpoints, _endpoints))
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._endpoints = newEndpoints;
+ r._adapterId = "";
+ r.applyOverrides(r._endpoints);
+ return r;
+ }
+
+ @Override
+ public Reference
+ changeAdapterId(String newAdapterId)
+ {
+ if(_adapterId.equals(newAdapterId))
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._adapterId = newAdapterId;
+ r._endpoints = _emptyEndpoints;
+ return r;
+ }
+
+ @Override
+ public Reference
+ changeLocator(Ice.LocatorPrx newLocator)
+ {
+ LocatorInfo newLocatorInfo = getInstance().locatorManager().get(newLocator);
+ if(newLocatorInfo != null && _locatorInfo != null && newLocatorInfo.equals(_locatorInfo))
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._locatorInfo = newLocatorInfo;
+ return r;
+ }
+
+ @Override
+ public Reference
+ changeRouter(Ice.RouterPrx newRouter)
+ {
+ RouterInfo newRouterInfo = getInstance().routerManager().get(newRouter);
+ if(newRouterInfo != null && _routerInfo != null && newRouterInfo.equals(_routerInfo))
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._routerInfo = newRouterInfo;
+ return r;
+ }
+
+ @Override
+ public Reference
+ changeCollocationOptimized(boolean newCollocationOptimized)
+ {
+ if(newCollocationOptimized == _collocationOptimized)
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._collocationOptimized = newCollocationOptimized;
+ return r;
+ }
+
+ @Override
+ public final Reference
+ changeCacheConnection(boolean newCache)
+ {
+ if(newCache == _cacheConnection)
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._cacheConnection = newCache;
+ return r;
+ }
+
+ @Override
+ public Reference
+ changePreferSecure(boolean newPreferSecure)
+ {
+ if(newPreferSecure == _preferSecure)
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._preferSecure = newPreferSecure;
+ return r;
+ }
+
+ @Override
+ public final Reference
+ changeEndpointSelection(Ice.EndpointSelectionType newType)
+ {
+ if(newType == _endpointSelection)
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._endpointSelection = newType;
+ return r;
+ }
+
+ @Override
+ public Reference
+ changeLocatorCacheTimeout(int newTimeout)
+ {
+ if(_locatorCacheTimeout == newTimeout)
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._locatorCacheTimeout = newTimeout;
+ return r;
+ }
+
+ @Override
+ public Reference
+ changeTimeout(int newTimeout)
+ {
+ if(_overrideTimeout && _timeout == newTimeout)
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._timeout = newTimeout;
+ r._overrideTimeout = true;
+ if(_endpoints.length > 0)
+ {
+ EndpointI[] newEndpoints = new EndpointI[_endpoints.length];
+ for(int i = 0; i < _endpoints.length; i++)
+ {
+ newEndpoints[i] = _endpoints[i].timeout(newTimeout);
+ }
+ r._endpoints = newEndpoints;
+ }
+ return r;
+ }
+
+ @Override
+ public Reference
+ changeConnectionId(String id)
+ {
+ if(_connectionId.equals(id))
+ {
+ return this;
+ }
+ RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
+ r._connectionId = id;
+ if(_endpoints.length > 0)
+ {
+ EndpointI[] newEndpoints = new EndpointI[_endpoints.length];
+ for(int i = 0; i < _endpoints.length; i++)
+ {
+ newEndpoints[i] = _endpoints[i].connectionId(id);
+ }
+ r._endpoints = newEndpoints;
+ }
+ return r;
+ }
+
+ @Override
+ public boolean
+ isIndirect()
+ {
+ return _endpoints.length == 0;
+ }
+
+ @Override
+ public boolean
+ isWellKnown()
+ {
+ return _endpoints.length == 0 && _adapterId.length() == 0;
+ }
+
+ @Override
+ public void
+ streamWrite(Ice.OutputStream s)
+ throws Ice.MarshalException
+ {
+ super.streamWrite(s);
+
+ s.writeSize(_endpoints.length);
+ if(_endpoints.length > 0)
+ {
+ assert(_adapterId.length() == 0);
+ for(EndpointI endpoint : _endpoints)
+ {
+ s.writeShort(endpoint.type());
+ endpoint.streamWrite(s);
+ }
+ }
+ else
+ {
+ s.writeString(_adapterId); // Adapter id.
+ }
+ }
+
+ @Override
+ public String
+ toString()
+ {
+ //
+ // 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.
+ //
+ StringBuilder s = new StringBuilder(128);
+ s.append(super.toString());
+ if(_endpoints.length > 0)
+ {
+ for(EndpointI endpoint : _endpoints)
+ {
+ String endp = endpoint.toString();
+ if(endp != null && endp.length() > 0)
+ {
+ s.append(':');
+ s.append(endp);
+ }
+ }
+ }
+ else if(_adapterId.length() > 0)
+ {
+ s.append(" @ ");
+
+ //
+ // If the encoded adapter id string contains characters which
+ // the reference parser uses as separators, then we enclose
+ // the adapter id string in quotes.
+ //
+ String a = IceUtilInternal.StringUtil.escapeString(_adapterId, null);
+ if(IceUtilInternal.StringUtil.findFirstOf(a, " :@") != -1)
+ {
+ s.append('"');
+ s.append(a);
+ s.append('"');
+ }
+ else
+ {
+ s.append(a);
+ }
+ }
+ return s.toString();
+ }
+
+ @Override
+ public java.util.Map<String, String> toProperty(String prefix)
+ {
+ java.util.Map<String, String> properties = new java.util.HashMap<String, String>();
+
+ properties.put(prefix, toString());
+ properties.put(prefix + ".CollocationOptimized", _collocationOptimized ? "1" : "0");
+ properties.put(prefix + ".ConnectionCached", _cacheConnection ? "1" : "0");
+ properties.put(prefix + ".PreferSecure", _preferSecure ? "1" : "0");
+ properties.put(prefix + ".EndpointSelection",
+ _endpointSelection == Ice.EndpointSelectionType.Random ? "Random" : "Ordered");
+
+ {
+ StringBuffer s = new StringBuffer();
+ s.append(getInvocationTimeout());
+ properties.put(prefix + ".InvocationTimeout", s.toString());
+ }
+ {
+ StringBuffer s = new StringBuffer();
+ s.append(_locatorCacheTimeout);
+ properties.put(prefix + ".LocatorCacheTimeout", s.toString());
+ }
+
+ if(_routerInfo != null)
+ {
+ Ice.ObjectPrxHelperBase h = (Ice.ObjectPrxHelperBase)_routerInfo.getRouter();
+ java.util.Map<String, String> routerProperties = h.__reference().toProperty(prefix + ".Router");
+ for(java.util.Map.Entry<String, String> p : routerProperties.entrySet())
+ {
+ properties.put(p.getKey(), p.getValue());
+ }
+ }
+
+ if(_locatorInfo != null)
+ {
+ Ice.ObjectPrxHelperBase h = (Ice.ObjectPrxHelperBase)_locatorInfo.getLocator();
+ java.util.Map<String, String> locatorProperties = h.__reference().toProperty(prefix + ".Locator");
+ for(java.util.Map.Entry<String, String> p : locatorProperties.entrySet())
+ {
+ properties.put(p.getKey(), p.getValue());
+ }
+ }
+
+ return properties;
+ }
+
+ @Override
+ public synchronized int
+ hashCode()
+ {
+ if(!_hashInitialized)
+ {
+ super.hashCode(); // Initializes _hashValue.
+ _hashValue = IceInternal.HashUtil.hashAdd(_hashValue, _adapterId);
+ }
+ return _hashValue;
+ }
+
+ @Override
+ public boolean
+ equals(java.lang.Object obj)
+ {
+ if(this == obj)
+ {
+ return true;
+ }
+ if(!(obj instanceof RoutableReference))
+ {
+ return false;
+ }
+
+ if(!super.equals(obj))
+ {
+ return false;
+ }
+ RoutableReference rhs = (RoutableReference)obj; // Guaranteed to succeed.
+ if(_locatorInfo == null ? rhs._locatorInfo != null : !_locatorInfo.equals(rhs._locatorInfo))
+ {
+ return false;
+ }
+ if(_routerInfo == null ? rhs._routerInfo != null : !_routerInfo.equals(rhs._routerInfo))
+ {
+ return false;
+ }
+ if(_collocationOptimized != rhs._collocationOptimized)
+ {
+ return false;
+ }
+ if(_cacheConnection != rhs._cacheConnection)
+ {
+ return false;
+ }
+ if(_preferSecure != rhs._preferSecure)
+ {
+ return false;
+ }
+ if(_endpointSelection != rhs._endpointSelection)
+ {
+ return false;
+ }
+ if(_locatorCacheTimeout != rhs._locatorCacheTimeout)
+ {
+ return false;
+ }
+ if(!_connectionId.equals(rhs._connectionId))
+ {
+ return false;
+ }
+ if(_overrideTimeout != rhs._overrideTimeout)
+ {
+ return false;
+ }
+ if(_overrideTimeout && _timeout != rhs._timeout)
+ {
+ return false;
+ }
+ if(!java.util.Arrays.equals(_endpoints, rhs._endpoints))
+ {
+ return false;
+ }
+ if(!_adapterId.equals(rhs._adapterId))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public RequestHandler
+ getRequestHandler(Ice.ObjectPrxHelperBase proxy)
+ {
+ return getInstance().requestHandlerFactory().getRequestHandler(this, proxy);
+ }
+
+ @Override
+ public BatchRequestQueue
+ getBatchRequestQueue()
+ {
+ return new BatchRequestQueue(getInstance(), getMode() == Reference.ModeBatchDatagram);
+ }
+
+ public void
+ getConnection(final GetConnectionCallback callback)
+ {
+ if(_routerInfo != null)
+ {
+ //
+ // If we route, we send everything to the router's client
+ // proxy endpoints.
+ //
+ _routerInfo.getClientEndpoints(new RouterInfo.GetClientEndpointsCallback()
+ {
+ @Override
+ public void
+ setEndpoints(EndpointI[] endpts)
+ {
+ if(endpts.length > 0)
+ {
+ applyOverrides(endpts);
+ createConnection(endpts, callback);
+ }
+ else
+ {
+ getConnectionNoRouterInfo(callback);
+ }
+ }
+
+ @Override
+ public void
+ setException(Ice.LocalException ex)
+ {
+ callback.setException(ex);
+ }
+ });
+ }
+ else
+ {
+ getConnectionNoRouterInfo(callback);
+ }
+ }
+
+ public void
+ getConnectionNoRouterInfo(final GetConnectionCallback callback)
+ {
+ if(_endpoints.length > 0)
+ {
+ createConnection(_endpoints, callback);
+ return;
+ }
+
+ final RoutableReference self = this;
+ if(_locatorInfo != null)
+ {
+ _locatorInfo.getEndpoints(this, _locatorCacheTimeout, new LocatorInfo.GetEndpointsCallback()
+ {
+ @Override
+ public void
+ setEndpoints(EndpointI[] endpoints, final boolean cached)
+ {
+ if(endpoints.length == 0)
+ {
+ callback.setException(new Ice.NoEndpointException(self.toString()));
+ return;
+ }
+
+ applyOverrides(endpoints);
+ createConnection(endpoints, new GetConnectionCallback()
+ {
+ @Override
+ public void
+ setConnection(Ice.ConnectionI connection, boolean compress)
+ {
+ callback.setConnection(connection, compress);
+ }
+
+ @Override
+ public void
+ setException(Ice.LocalException exc)
+ {
+ try
+ {
+ throw exc;
+ }
+ catch(Ice.NoEndpointException ex)
+ {
+ callback.setException(ex); // No need to retry if there's no endpoints.
+ }
+ catch(Ice.LocalException ex)
+ {
+ assert(_locatorInfo != null);
+ _locatorInfo.clearCache(self);
+ if(cached)
+ {
+ TraceLevels traceLvls = getInstance().traceLevels();
+ if(traceLvls.retry >= 2)
+ {
+ String s = "connection to cached endpoints failed\n" +
+ "removing endpoints from cache and trying one more time\n" + ex;
+ getInstance().initializationData().logger.trace(traceLvls.retryCat, s);
+ }
+ getConnectionNoRouterInfo(callback); // Retry.
+ return;
+ }
+ callback.setException(ex);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void
+ setException(Ice.LocalException ex)
+ {
+ callback.setException(ex);
+ }
+ });
+ }
+ else
+ {
+ callback.setException(new Ice.NoEndpointException(toString()));
+ }
+ }
+
+ protected
+ RoutableReference(Instance instance,
+ Ice.Communicator communicator,
+ Ice.Identity identity,
+ String facet,
+ int mode,
+ boolean secure,
+ Ice.ProtocolVersion protocol,
+ Ice.EncodingVersion encoding,
+ EndpointI[] endpoints,
+ String adapterId,
+ LocatorInfo locatorInfo,
+ RouterInfo routerInfo,
+ boolean collocationOptimized,
+ boolean cacheConnection,
+ boolean prefereSecure,
+ Ice.EndpointSelectionType endpointSelection,
+ int locatorCacheTimeout,
+ int invocationTimeout,
+ java.util.Map<String, String> context)
+ {
+ super(instance, communicator, identity, facet, mode, secure, protocol, encoding, invocationTimeout, context);
+ _endpoints = endpoints;
+ _adapterId = adapterId;
+ _locatorInfo = locatorInfo;
+ _routerInfo = routerInfo;
+ _collocationOptimized = collocationOptimized;
+ _cacheConnection = cacheConnection;
+ _preferSecure = prefereSecure;
+ _endpointSelection = endpointSelection;
+ _locatorCacheTimeout = locatorCacheTimeout;
+ _overrideTimeout = false;
+ _timeout = -1;
+
+ if(_endpoints == null)
+ {
+ _endpoints = _emptyEndpoints;
+ }
+ if(_adapterId == null)
+ {
+ _adapterId = "";
+ }
+ assert(_adapterId.length() == 0 || _endpoints.length == 0);
+ }
+
+ protected void
+ applyOverrides(EndpointI[] endpts)
+ {
+ //
+ // Apply the endpoint overrides to each endpoint.
+ //
+ for(int i = 0; i < endpts.length; ++i)
+ {
+ endpts[i] = endpts[i].connectionId(_connectionId);
+ if(_overrideCompress)
+ {
+ endpts[i] = endpts[i].compress(_compress);
+ }
+ if(_overrideTimeout)
+ {
+ endpts[i] = endpts[i].timeout(_timeout);
+ }
+ }
+ }
+
+ private EndpointI[]
+ filterEndpoints(EndpointI[] allEndpoints)
+ {
+ java.util.List<EndpointI> endpoints = new java.util.ArrayList<EndpointI>();
+
+ //
+ // Filter out opaque endpoints.
+ //
+ for(EndpointI endpoint : allEndpoints)
+ {
+ if(!(endpoint instanceof IceInternal.OpaqueEndpointI))
+ {
+ endpoints.add(endpoint);
+ }
+ }
+
+ //
+ // Filter out endpoints according to the mode of the reference.
+ //
+ switch(getMode())
+ {
+ case Reference.ModeTwoway:
+ case Reference.ModeOneway:
+ case Reference.ModeBatchOneway:
+ {
+ //
+ // Filter out datagram endpoints.
+ //
+ java.util.Iterator<EndpointI> i = endpoints.iterator();
+ while(i.hasNext())
+ {
+ EndpointI endpoint = i.next();
+ if(endpoint.datagram())
+ {
+ i.remove();
+ }
+ }
+ break;
+ }
+
+ case Reference.ModeDatagram:
+ case Reference.ModeBatchDatagram:
+ {
+ //
+ // Filter out non-datagram endpoints.
+ //
+ java.util.Iterator<EndpointI> i = endpoints.iterator();
+ while(i.hasNext())
+ {
+ EndpointI endpoint = i.next();
+ if(!endpoint.datagram())
+ {
+ i.remove();
+ }
+ }
+ break;
+ }
+ }
+
+ //
+ // Sort the endpoints according to the endpoint selection type.
+ //
+ switch(getEndpointSelection())
+ {
+ case Random:
+ {
+ java.util.Collections.shuffle(endpoints);
+ break;
+ }
+ case Ordered:
+ {
+ // Nothing to do.
+ break;
+ }
+ default:
+ {
+ 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.
+ //
+ DefaultsAndOverrides overrides = getInstance().defaultsAndOverrides();
+ if(overrides.overrideSecure ? overrides.overrideSecureValue : getSecure())
+ {
+ java.util.Iterator<EndpointI> i = endpoints.iterator();
+ while(i.hasNext())
+ {
+ EndpointI endpoint = i.next();
+ if(!endpoint.secure())
+ {
+ i.remove();
+ }
+ }
+ }
+ else if(getPreferSecure())
+ {
+ java.util.Collections.sort(endpoints, _preferSecureEndpointComparator);
+ }
+ else
+ {
+ java.util.Collections.sort(endpoints, _preferNonSecureEndpointComparator);
+ }
+
+ return endpoints.toArray(new EndpointI[endpoints.size()]);
+ }
+
+ protected void
+ createConnection(EndpointI[] allEndpoints, final GetConnectionCallback callback)
+ {
+ final EndpointI[] endpoints = filterEndpoints(allEndpoints);
+ if(endpoints.length == 0)
+ {
+ callback.setException(new Ice.NoEndpointException(toString()));
+ return;
+ }
+
+ //
+ // Finally, create the connection.
+ //
+ final OutgoingConnectionFactory factory = getInstance().outgoingConnectionFactory();
+ if(getCacheConnection() || endpoints.length == 1)
+ {
+ //
+ // Get an existing connection or create one if there's no
+ // existing connection to one of the given endpoints.
+ //
+ factory.create(endpoints, false, getEndpointSelection(),
+ new OutgoingConnectionFactory.CreateConnectionCallback()
+ {
+ @Override
+ public void
+ setConnection(Ice.ConnectionI connection, boolean 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(_routerInfo != null && _routerInfo.getAdapter() != null)
+ {
+ connection.setAdapter(_routerInfo.getAdapter());
+ }
+ callback.setConnection(connection, compress);
+ }
+
+ @Override
+ public void
+ setException(Ice.LocalException ex)
+ {
+ callback.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.
+ //
+
+ factory.create(new EndpointI[]{ endpoints[0] }, true, getEndpointSelection(),
+ new OutgoingConnectionFactory.CreateConnectionCallback()
+ {
+ @Override
+ public void
+ setConnection(Ice.ConnectionI connection, boolean 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(_routerInfo != null && _routerInfo.getAdapter() != null)
+ {
+ connection.setAdapter(_routerInfo.getAdapter());
+ }
+ callback.setConnection(connection, compress);
+ }
+
+ @Override
+ public void
+ setException(final Ice.LocalException ex)
+ {
+ if(_exception == null)
+ {
+ _exception = ex;
+ }
+
+ if(++_i == endpoints.length)
+ {
+ callback.setException(_exception);
+ return;
+ }
+
+ final boolean more = _i != endpoints.length - 1;
+ final EndpointI[] endpoint = new EndpointI[]{ endpoints[_i] };
+ factory.create(endpoint, more, getEndpointSelection(), this);
+ }
+
+ private int _i = 0;
+ private Ice.LocalException _exception = null;
+ });
+ }
+ }
+
+ static class EndpointComparator implements java.util.Comparator<EndpointI>
+ {
+ EndpointComparator(boolean preferSecure)
+ {
+ _preferSecure = preferSecure;
+ }
+
+ @Override
+ public int
+ compare(EndpointI le, EndpointI re)
+ {
+ boolean ls = le.secure();
+ boolean rs = re.secure();
+ if((ls && rs) || (!ls && !rs))
+ {
+ return 0;
+ }
+ else if(!ls && rs)
+ {
+ if(_preferSecure)
+ {
+ return 1;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ if(_preferSecure)
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ }
+
+ private boolean _preferSecure;
+ }
+
+ private static EndpointComparator _preferNonSecureEndpointComparator = new EndpointComparator(false);
+ private static EndpointComparator _preferSecureEndpointComparator = new EndpointComparator(true);
+ private static EndpointI[] _emptyEndpoints = new EndpointI[0];
+
+ private EndpointI[] _endpoints;
+ private String _adapterId;
+ private LocatorInfo _locatorInfo; // Null if no router is used.
+ private RouterInfo _routerInfo; // Null if no router is used.
+ private boolean _collocationOptimized;
+ private boolean _cacheConnection;
+ private boolean _preferSecure;
+ private Ice.EndpointSelectionType _endpointSelection;
+ private int _locatorCacheTimeout;
+
+ private boolean _overrideTimeout;
+ private int _timeout; // Only used if _overrideTimeout == true
+ private String _connectionId = "";
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RouterInfo.java b/java-compat/src/Ice/src/main/java/IceInternal/RouterInfo.java
new file mode 100644
index 00000000000..1de08e756fe
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/RouterInfo.java
@@ -0,0 +1,280 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class RouterInfo
+{
+ interface GetClientEndpointsCallback
+ {
+ void setEndpoints(EndpointI[] endpoints);
+ void setException(Ice.LocalException ex);
+ }
+
+ interface AddProxyCallback
+ {
+ void addedProxy();
+ void setException(Ice.LocalException ex);
+ }
+
+ RouterInfo(Ice.RouterPrx router)
+ {
+ _router = router;
+
+ assert(_router != null);
+ }
+
+ synchronized public void
+ destroy()
+ {
+ _clientEndpoints = new EndpointI[0];
+ _serverEndpoints = new EndpointI[0];
+ _adapter = null;
+ _identities.clear();
+ }
+
+ @Override
+ public boolean
+ equals(java.lang.Object obj)
+ {
+ if(this == obj)
+ {
+ return true;
+ }
+
+ if(obj instanceof RouterInfo)
+ {
+ return _router.equals(((RouterInfo)obj)._router);
+ }
+
+ return false;
+ }
+
+ @Override
+ public int
+ hashCode()
+ {
+ return _router.hashCode();
+ }
+
+ public Ice.RouterPrx
+ getRouter()
+ {
+ //
+ // No mutex lock necessary, _router is immutable.
+ //
+ return _router;
+ }
+
+ public EndpointI[]
+ getClientEndpoints()
+ {
+ synchronized(this)
+ {
+ if(_clientEndpoints != null) // Lazy initialization.
+ {
+ return _clientEndpoints;
+ }
+ }
+
+ return setClientEndpoints(_router.getClientProxy());
+ }
+
+ public void
+ getClientEndpoints(final GetClientEndpointsCallback callback)
+ {
+ EndpointI[] clientEndpoints = null;
+ synchronized(this)
+ {
+ clientEndpoints = _clientEndpoints;
+ }
+
+ if(clientEndpoints != null)
+ {
+ callback.setEndpoints(clientEndpoints);
+ return;
+ }
+
+ _router.begin_getClientProxy(new Ice.Callback_Router_getClientProxy()
+ {
+ @Override
+ public void
+ response(Ice.ObjectPrx clientProxy)
+ {
+ callback.setEndpoints(setClientEndpoints(clientProxy));
+ }
+
+ @Override
+ public void
+ exception(Ice.LocalException ex)
+ {
+ callback.setException(ex);
+ }
+ });
+ }
+
+ public EndpointI[]
+ getServerEndpoints()
+ {
+ synchronized(this)
+ {
+ if(_serverEndpoints != null) // Lazy initialization.
+ {
+ return _serverEndpoints;
+ }
+ }
+
+ return setServerEndpoints(_router.getServerProxy());
+ }
+
+ public boolean
+ addProxy(final Ice.ObjectPrx proxy, final AddProxyCallback callback)
+ {
+ assert(proxy != null);
+ synchronized(this)
+ {
+ if(_identities.contains(proxy.ice_getIdentity()))
+ {
+ //
+ // Only add the proxy to the router if it's not already in our local map.
+ //
+ return true;
+ }
+ }
+
+ _router.begin_addProxies(new Ice.ObjectPrx[] { proxy },
+ new Ice.Callback_Router_addProxies()
+ {
+ @Override
+ public void
+ response(Ice.ObjectPrx[] evictedProxies)
+ {
+ addAndEvictProxies(proxy, evictedProxies);
+ callback.addedProxy();
+ }
+
+ @Override
+ public void
+ exception(Ice.LocalException ex)
+ {
+ callback.setException(ex);
+ }
+ });
+
+ return false;
+ }
+
+ public synchronized void
+ setAdapter(Ice.ObjectAdapter adapter)
+ {
+ _adapter = adapter;
+ }
+
+ public synchronized Ice.ObjectAdapter
+ getAdapter()
+ {
+ return _adapter;
+ }
+
+ public synchronized void clearCache(Reference ref)
+ {
+ _identities.remove(ref.getIdentity());
+ }
+
+ private synchronized EndpointI[]
+ setClientEndpoints(Ice.ObjectPrx clientProxy)
+ {
+ if(_clientEndpoints == null)
+ {
+ if(clientProxy == null)
+ {
+ //
+ // If getClientProxy() return nil, use router endpoints.
+ //
+ _clientEndpoints = ((Ice.ObjectPrxHelperBase)_router).__reference().getEndpoints();
+ }
+ 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.
+ //
+ if(_router.ice_getConnection() != null)
+ {
+ clientProxy = clientProxy.ice_timeout(_router.ice_getConnection().timeout());
+ }
+
+ _clientEndpoints = ((Ice.ObjectPrxHelperBase)clientProxy).__reference().getEndpoints();
+ }
+ }
+ return _clientEndpoints;
+ }
+
+ private synchronized EndpointI[]
+ setServerEndpoints(Ice.ObjectPrx serverProxy)
+ {
+ if(serverProxy == null)
+ {
+ throw new Ice.NoEndpointException();
+ }
+
+ serverProxy = serverProxy.ice_router(null); // The server proxy cannot be routed.
+ _serverEndpoints = ((Ice.ObjectPrxHelperBase)serverProxy).__reference().getEndpoints();
+ return _serverEndpoints;
+ }
+
+ private synchronized void
+ addAndEvictProxies(Ice.ObjectPrx proxy, Ice.ObjectPrx[] 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.
+ //
+ int index = _evictedIdentities.indexOf(proxy.ice_getIdentity());
+ if(index >= 0)
+ {
+ _evictedIdentities.remove(index);
+ }
+ else
+ {
+ //
+ // If we successfully added the proxy to the router,
+ // we add it to our local map.
+ //
+ _identities.add(proxy.ice_getIdentity());
+ }
+
+ //
+ // We also must remove whatever proxies the router evicted.
+ //
+ for(Ice.ObjectPrx p : evictedProxies)
+ {
+ if(!_identities.remove(p.ice_getIdentity()))
+ {
+ //
+ // It's possible for the proxy to not have been
+ // added yet in the local map if two threads
+ // concurrently call addProxies.
+ //
+ _evictedIdentities.add(p.ice_getIdentity());
+ }
+ }
+ }
+
+ private final Ice.RouterPrx _router;
+ private EndpointI[] _clientEndpoints;
+ private EndpointI[] _serverEndpoints;
+ private Ice.ObjectAdapter _adapter;
+ private java.util.Set<Ice.Identity> _identities = new java.util.HashSet<Ice.Identity>();
+ private java.util.List<Ice.Identity> _evictedIdentities = new java.util.ArrayList<Ice.Identity>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RouterManager.java b/java-compat/src/Ice/src/main/java/IceInternal/RouterManager.java
new file mode 100644
index 00000000000..217c5d86d5d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/RouterManager.java
@@ -0,0 +1,76 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class RouterManager
+{
+ RouterManager()
+ {
+ }
+
+ synchronized void
+ destroy()
+ {
+ for(RouterInfo info : _table.values())
+ {
+ info.destroy();
+ }
+ _table.clear();
+ }
+
+ //
+ // Returns router info for a given router. Automatically creates
+ // the router info if it doesn't exist yet.
+ //
+ public RouterInfo
+ get(Ice.RouterPrx rtr)
+ {
+ if(rtr == null)
+ {
+ return null;
+ }
+
+ //
+ // The router cannot be routed.
+ //
+ Ice.RouterPrx router = Ice.RouterPrxHelper.uncheckedCast(rtr.ice_router(null));
+
+ synchronized(this)
+ {
+ RouterInfo info = _table.get(router);
+ if(info == null)
+ {
+ info = new RouterInfo(router);
+ _table.put(router, info);
+ }
+
+ return info;
+ }
+ }
+
+ public RouterInfo
+ erase(Ice.RouterPrx rtr)
+ {
+ RouterInfo info = null;
+ if(rtr != null)
+ {
+ // The router cannot be routed.
+ Ice.RouterPrx router = Ice.RouterPrxHelper.uncheckedCast(rtr.ice_router(null));
+
+ synchronized(this)
+ {
+ info = _table.remove(router);
+ }
+ }
+ return info;
+ }
+
+ private java.util.HashMap<Ice.RouterPrx, RouterInfo> _table = new java.util.HashMap<Ice.RouterPrx, RouterInfo>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/SOCKSNetworkProxy.java b/java-compat/src/Ice/src/main/java/IceInternal/SOCKSNetworkProxy.java
new file mode 100644
index 00000000000..c2843bdbf6e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/SOCKSNetworkProxy.java
@@ -0,0 +1,128 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class SOCKSNetworkProxy implements NetworkProxy
+{
+ public SOCKSNetworkProxy(String host, int port)
+ {
+ _host = host;
+ _port = port;
+ }
+
+ private SOCKSNetworkProxy(java.net.InetSocketAddress address)
+ {
+ _address = address;
+ }
+
+ @Override
+ public void beginWrite(java.net.InetSocketAddress endpoint, Buffer buf)
+ {
+ final java.net.InetAddress addr = endpoint.getAddress();
+ if(addr == null)
+ {
+ throw new Ice.FeatureNotSupportedException("SOCKS4 does not support domain names");
+ }
+ else if(!(addr instanceof java.net.Inet4Address))
+ {
+ throw new Ice.FeatureNotSupportedException("SOCKS4 only supports IPv4 addresses");
+ }
+
+ //
+ // SOCKS connect request
+ //
+ buf.resize(9, false);
+ final java.nio.ByteOrder order = buf.b.order();
+ buf.b.order(java.nio.ByteOrder.BIG_ENDIAN); // Network byte order.
+ buf.b.position(0);
+ buf.b.put((byte)0x04); // SOCKS version 4.
+ buf.b.put((byte)0x01); // Command, establish a TCP/IP stream connection
+ buf.b.putShort((short)endpoint.getPort()); // Port
+ buf.b.put(addr.getAddress()); // IPv4 address
+ buf.b.put((byte)0x00); // User ID.
+ buf.b.position(0);
+ buf.b.limit(buf.size());
+ buf.b.order(order);
+ }
+
+ @Override
+ public int endWrite(Buffer buf)
+ {
+ // Once the request is sent, read the response
+ return buf.b.hasRemaining() ? SocketOperation.Write : SocketOperation.Read;
+ }
+
+ @Override
+ public void beginRead(Buffer buf)
+ {
+ //
+ // Read the SOCKS4 response whose size is 8 bytes.
+ //
+ if(!buf.b.hasRemaining())
+ {
+ buf.resize(8, true);
+ buf.b.position(0);
+ }
+ }
+
+ @Override
+ public int endRead(Buffer buf)
+ {
+ // We're done once we read the response
+ return buf.b.hasRemaining() ? SocketOperation.Read : SocketOperation.None;
+ }
+
+ @Override
+ public void finish(Buffer readBuffer, Buffer writeBuffer)
+ {
+ readBuffer.b.position(0);
+ byte b1 = readBuffer.b.get();
+ byte b2 = readBuffer.b.get();
+ if(b1 != 0x00 || b2 != 0x5a)
+ {
+ throw new Ice.ConnectFailedException();
+ }
+ }
+
+ @Override
+ public NetworkProxy resolveHost(int protocolSupport)
+ {
+ assert(_host != null);
+ return new SOCKSNetworkProxy(Network.getAddresses(_host,
+ _port,
+ protocolSupport,
+ Ice.EndpointSelectionType.Random,
+ false,
+ true).get(0));
+ }
+
+ @Override
+ public java.net.InetSocketAddress getAddress()
+ {
+ assert(_address != null); // Host must be resolved.
+ return _address;
+ }
+
+ @Override
+ public String getName()
+ {
+ return "SOCKS";
+ }
+
+ @Override
+ public int getProtocolSupport()
+ {
+ return Network.EnableIPv4;
+ }
+
+ private String _host;
+ private int _port;
+ private java.net.InetSocketAddress _address;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Selector.java b/java-compat/src/Ice/src/main/java/IceInternal/Selector.java
new file mode 100644
index 00000000000..ecc4529845e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Selector.java
@@ -0,0 +1,408 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class Selector
+{
+ static final class TimeoutException extends Exception
+ {
+ }
+
+ Selector(Instance instance)
+ {
+ _instance = instance;
+ _selecting = false;
+ _interrupted = false;
+
+ try
+ {
+ _selector = java.nio.channels.Selector.open();
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SyscallException(ex);
+ }
+
+ //
+ // The Selector holds a Set representing the selected keys. The
+ // Set reference doesn't change, so we obtain it once here.
+ //
+ _keys = _selector.selectedKeys();
+ }
+
+ void destroy()
+ {
+ try
+ {
+ _selector.close();
+ }
+ catch(java.io.IOException ex)
+ {
+ }
+ _selector = null;
+ }
+
+ void initialize(EventHandler handler)
+ {
+ if(handler.fd() != null)
+ {
+ updateImpl(handler);
+ }
+ }
+
+ void update(EventHandler handler, int remove, int add)
+ {
+ int previous = handler._registered;
+ handler._registered = handler._registered & ~remove;
+ handler._registered = handler._registered | add;
+ if(previous == handler._registered)
+ {
+ return;
+ }
+
+ if(handler.fd() == null)
+ {
+ return;
+ }
+
+ updateImpl(handler);
+ checkReady(handler);
+ }
+
+ void enable(EventHandler handler, int status)
+ {
+ if(handler.fd() == null || (handler._disabled & status) == 0)
+ {
+ return;
+ }
+ handler._disabled = handler._disabled & ~status;
+
+ if(handler.fd() == null)
+ {
+ return;
+ }
+
+ if(handler._key != null && (handler._registered & status) != 0)
+ {
+ updateImpl(handler); // If registered with the selector, update the registration.
+ }
+ checkReady(handler);
+ }
+
+ void disable(EventHandler handler, int status)
+ {
+ if(handler.fd() == null || (handler._disabled & status) != 0)
+ {
+ return;
+ }
+ handler._disabled = handler._disabled | status;
+
+ if(handler._key != null && (handler._registered & status) != 0)
+ {
+ updateImpl(handler); // If registered with the selector, update the registration.
+ }
+ checkReady(handler);
+ }
+
+ boolean finish(EventHandler handler, boolean closeNow)
+ {
+ handler._registered = 0;
+ if(handler._key != null)
+ {
+ handler._key.cancel();
+ handler._key = null;
+ }
+ _changes.remove(handler);
+ checkReady(handler);
+ return closeNow;
+ }
+
+ void ready(EventHandler handler, int status, boolean value)
+ {
+ if(((handler._ready & status) != 0) == value)
+ {
+ return; // Nothing to do if ready state already correctly set.
+ }
+
+ if(value)
+ {
+ handler._ready |= status;
+ }
+ else
+ {
+ handler._ready &= ~status;
+ }
+ checkReady(handler);
+ }
+
+ void startSelect()
+ {
+ if(!_changes.isEmpty())
+ {
+ updateSelector();
+ }
+ _selecting = true;
+
+ //
+ // If there are ready handlers, don't block in select, just do a non-blocking
+ // select to retrieve new ready handlers from the Java selector.
+ //
+ _selectNow = !_readyHandlers.isEmpty();
+ }
+
+ void finishSelect(java.util.List<EventHandlerOpPair> handlers)
+ {
+ assert(handlers.isEmpty());
+
+ if(_keys.isEmpty() && _readyHandlers.isEmpty() && !_interrupted) // If key set is empty and we weren't woken up.
+ {
+ //
+ // This is necessary to prevent a busy loop in case of a spurious wake-up which
+ // sometime occurs in the client thread pool when the communicator is destroyed.
+ // If there are too many successive spurious wake-ups, we log an error.
+ //
+ try
+ {
+ Thread.sleep(1);
+ }
+ catch(InterruptedException ex)
+ {
+ //
+ // Eat the InterruptedException (as we do in ThreadPool.promoteFollower).
+ //
+ }
+
+ if(++_spuriousWakeUp > 100)
+ {
+ _spuriousWakeUp = 0;
+ _instance.initializationData().logger.warning("spurious selector wake up");
+ }
+ return;
+ }
+ _interrupted = false;
+ _spuriousWakeUp = 0;
+
+ for(java.nio.channels.SelectionKey key : _keys)
+ {
+ EventHandler handler = (EventHandler)key.attachment();
+ try
+ {
+ //
+ // Use the intersection of readyOps and interestOps because we only want to
+ // report the operations in which the handler is still interested.
+ //
+ final int op = fromJavaOps(key.readyOps() & key.interestOps());
+ if(!_readyHandlers.contains(handler)) // Handler will be added by the loop below
+ {
+ handlers.add(new EventHandlerOpPair(handler, op));
+ }
+ }
+ catch(java.nio.channels.CancelledKeyException ex)
+ {
+ assert(handler._registered == 0);
+ }
+ }
+
+ for(EventHandler handler : _readyHandlers)
+ {
+ int op = handler._ready & ~handler._disabled & handler._registered;
+ if(handler._key != null && _keys.contains(handler._key))
+ {
+ op |= fromJavaOps(handler._key.readyOps() & handler._key.interestOps());
+ }
+ if(op > 0)
+ {
+ handlers.add(new EventHandlerOpPair(handler, op));
+ }
+ }
+
+ _keys.clear();
+ _selecting = false;
+ }
+
+ void select(long timeout)
+ throws TimeoutException
+ {
+ while(true)
+ {
+ try
+ {
+ if(_selectNow)
+ {
+ _selector.selectNow();
+ }
+ else if(timeout > 0)
+ {
+ //
+ // NOTE: On some platforms, select() sometime returns slightly before
+ // the timeout (at least according to our monotonic time). To make sure
+ // timeouts are correctly detected, we wait for a little longer than
+ // the configured timeout (10ms).
+ //
+ long before = IceInternal.Time.currentMonotonicTimeMillis();
+ if(_selector.select(timeout * 1000 + 10) == 0)
+ {
+ if(IceInternal.Time.currentMonotonicTimeMillis() - before >= timeout * 1000)
+ {
+ throw new TimeoutException();
+ }
+ }
+ }
+ else
+ {
+ _selector.select();
+ }
+ }
+ catch(java.nio.channels.CancelledKeyException ex)
+ {
+ // This sometime occurs on OS X, ignore.
+ continue;
+ }
+ catch(java.io.IOException ex)
+ {
+ //
+ // Pressing Ctrl-C causes select() to raise an
+ // IOException, which seems like a JDK bug. We trap
+ // for that special case here and ignore it.
+ // Hopefully we're not masking something important!
+ //
+ if(Network.interrupted(ex))
+ {
+ continue;
+ }
+
+ try
+ {
+ String s = "fatal error: selector failed:\n" + ex.getCause().getMessage();
+ _instance.initializationData().logger.error(s);
+ }
+ finally
+ {
+ Runtime.getRuntime().halt(1);
+ }
+ }
+
+ break;
+ }
+ }
+
+ private void updateImpl(EventHandler handler)
+ {
+ _changes.add(handler);
+ wakeup();
+ }
+
+ private void updateSelector()
+ {
+ for(EventHandler handler : _changes)
+ {
+ int status = handler._registered & ~handler._disabled;
+ int ops = toJavaOps(handler, status);
+ if(handler._key == null)
+ {
+ if(handler._registered != 0)
+ {
+ try
+ {
+ handler._key = handler.fd().register(_selector, ops, handler);
+ }
+ catch(java.nio.channels.ClosedChannelException ex)
+ {
+ assert(false);
+ }
+ }
+ }
+ else
+ {
+ handler._key.interestOps(ops);
+ }
+ }
+ _changes.clear();
+ }
+
+ private void checkReady(EventHandler handler)
+ {
+ if((handler._ready & ~handler._disabled & handler._registered) != 0)
+ {
+ _readyHandlers.add(handler);
+ if(_selecting)
+ {
+ wakeup();
+ }
+ }
+ else
+ {
+ _readyHandlers.remove(handler);
+ }
+ }
+
+ private void wakeup()
+ {
+ if(_selecting && !_interrupted)
+ {
+ _selector.wakeup();
+ _interrupted = true;
+ }
+ }
+
+ private int toJavaOps(EventHandler handler, int o)
+ {
+ int op = 0;
+ if((o & SocketOperation.Read) != 0)
+ {
+ if((handler.fd().validOps() & java.nio.channels.SelectionKey.OP_READ) != 0)
+ {
+ op |= java.nio.channels.SelectionKey.OP_READ;
+ }
+ else
+ {
+ op |= java.nio.channels.SelectionKey.OP_ACCEPT;
+ }
+ }
+ if((o & SocketOperation.Write) != 0)
+ {
+ op |= java.nio.channels.SelectionKey.OP_WRITE;
+ }
+ if((o & SocketOperation.Connect) != 0)
+ {
+ op |= java.nio.channels.SelectionKey.OP_CONNECT;
+ }
+ return op;
+ }
+
+ private int fromJavaOps(int o)
+ {
+ int op = 0;
+ if((o & (java.nio.channels.SelectionKey.OP_READ | java.nio.channels.SelectionKey.OP_ACCEPT)) != 0)
+ {
+ op |= SocketOperation.Read;
+ }
+ if((o & java.nio.channels.SelectionKey.OP_WRITE) != 0)
+ {
+ op |= SocketOperation.Write;
+ }
+ if((o & java.nio.channels.SelectionKey.OP_CONNECT) != 0)
+ {
+ op |= SocketOperation.Connect;
+ }
+ return op;
+ }
+
+ final private Instance _instance;
+
+ private java.nio.channels.Selector _selector;
+ private java.util.Set<java.nio.channels.SelectionKey> _keys;
+ private java.util.HashSet<EventHandler> _changes = new java.util.HashSet<EventHandler>();
+ private java.util.HashSet<EventHandler> _readyHandlers = new java.util.HashSet<EventHandler>();
+ private boolean _selecting;
+ private boolean _selectNow;
+ private boolean _interrupted;
+ private int _spuriousWakeUp;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/SequencePatcher.java b/java-compat/src/Ice/src/main/java/IceInternal/SequencePatcher.java
new file mode 100644
index 00000000000..ca11b14d21c
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/SequencePatcher.java
@@ -0,0 +1,41 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class SequencePatcher implements Ice.ReadValueCallback
+{
+ public SequencePatcher(java.lang.Object[] seq, Class<?> cls, int index)
+ {
+ _seq = seq;
+ _cls = cls;
+ _index = index;
+ }
+
+ public void valueReady(Ice.Object v)
+ {
+ if(v != null)
+ {
+ //
+ // Raise ClassCastException if the element doesn't match the expected type.
+ //
+ if(!_cls.isInstance(v))
+ {
+ throw new ClassCastException("expected element of type " + _cls.getName() + " but received " +
+ v.getClass().getName());
+ }
+ }
+
+ _seq[_index] = v;
+ }
+
+ private java.lang.Object[] _seq;
+ private Class<?> _cls;
+ private int _index;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ServantError.java b/java-compat/src/Ice/src/main/java/IceInternal/ServantError.java
new file mode 100644
index 00000000000..8823aae9ea9
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ServantError.java
@@ -0,0 +1,28 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final public class ServantError extends java.lang.Error
+{
+ public ServantError(String reason)
+ {
+ super(reason);
+ }
+
+ public ServantError(String reason, Throwable cause)
+ {
+ super(reason, cause);
+ }
+
+ public ServantError(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java b/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java
new file mode 100644
index 00000000000..2789304f276
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java
@@ -0,0 +1,322 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class ServantManager
+{
+ public synchronized void
+ addServant(Ice.Object servant, Ice.Identity ident, String facet)
+ {
+ assert(_instance != null); // Must not be called after destruction.
+
+ if(facet == null)
+ {
+ facet = "";
+ }
+
+ java.util.Map<String, Ice.Object> m = _servantMapMap.get(ident);
+ if(m == null)
+ {
+ m = new java.util.HashMap<String, Ice.Object>();
+ _servantMapMap.put(ident, m);
+ }
+ else
+ {
+ if(m.containsKey(facet))
+ {
+ Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException();
+ ex.id = Ice.Util.identityToString(ident);
+ ex.kindOfObject = "servant";
+ if(facet.length() > 0)
+ {
+ ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, "");
+ }
+ throw ex;
+ }
+ }
+
+ m.put(facet, servant);
+ }
+
+ public synchronized void
+ addDefaultServant(Ice.Object servant, String category)
+ {
+ assert(_instance != null); // Must not be called after destruction
+
+ Ice.Object obj = _defaultServantMap.get(category);
+ if(obj != null)
+ {
+ Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException();
+ ex.kindOfObject = "default servant";
+ ex.id = category;
+ throw ex;
+ }
+
+ _defaultServantMap.put(category, servant);
+ }
+
+ public synchronized Ice.Object
+ removeServant(Ice.Identity ident, String facet)
+ {
+ assert(_instance != null); // Must not be called after destruction.
+
+ if(facet == null)
+ {
+ facet = "";
+ }
+
+ java.util.Map<String, Ice.Object> m = _servantMapMap.get(ident);
+ Ice.Object obj = null;
+ if(m == null || (obj = m.remove(facet)) == null)
+ {
+ Ice.NotRegisteredException ex = new Ice.NotRegisteredException();
+ ex.id = Ice.Util.identityToString(ident);
+ ex.kindOfObject = "servant";
+ if(facet.length() > 0)
+ {
+ ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, "");
+ }
+ throw ex;
+ }
+
+ if(m.isEmpty())
+ {
+ _servantMapMap.remove(ident);
+ }
+ return obj;
+ }
+
+ public synchronized Ice.Object
+ removeDefaultServant(String category)
+ {
+ assert(_instance != null); // Must not be called after destruction.
+
+ Ice.Object obj = _defaultServantMap.get(category);
+ if(obj == null)
+ {
+ Ice.NotRegisteredException ex = new Ice.NotRegisteredException();
+ ex.kindOfObject = "default servant";
+ ex.id = category;
+ throw ex;
+ }
+
+ _defaultServantMap.remove(category);
+ return obj;
+ }
+
+ public synchronized java.util.Map<String, Ice.Object>
+ removeAllFacets(Ice.Identity ident)
+ {
+ assert(_instance != null); // Must not be called after destruction.
+
+ java.util.Map<String, Ice.Object> m = _servantMapMap.get(ident);
+ if(m == null)
+ {
+ Ice.NotRegisteredException ex = new Ice.NotRegisteredException();
+ ex.id = Ice.Util.identityToString(ident);
+ ex.kindOfObject = "servant";
+ throw ex;
+ }
+
+ _servantMapMap.remove(ident);
+
+ return m;
+ }
+
+ public synchronized Ice.Object
+ findServant(Ice.Identity ident, String 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.
+ //
+ //assert(_instance != null); // Must not be called after destruction.
+
+ if(facet == null)
+ {
+ facet = "";
+ }
+
+ java.util.Map<String, Ice.Object> m = _servantMapMap.get(ident);
+ Ice.Object obj = null;
+ if(m == null)
+ {
+ obj = _defaultServantMap.get(ident.category);
+ if(obj == null)
+ {
+ obj = _defaultServantMap.get("");
+ }
+ }
+ else
+ {
+ obj = m.get(facet);
+ }
+
+ return obj;
+ }
+
+ public synchronized Ice.Object
+ findDefaultServant(String category)
+ {
+ assert(_instance != null); // Must not be called after destruction.
+
+ return _defaultServantMap.get(category);
+ }
+
+ public synchronized java.util.Map<String, Ice.Object>
+ findAllFacets(Ice.Identity ident)
+ {
+ assert(_instance != null); // Must not be called after destruction.
+
+ java.util.Map<String, Ice.Object> m = _servantMapMap.get(ident);
+ if(m != null)
+ {
+ return new java.util.HashMap<String, Ice.Object>(m);
+ }
+
+ return new java.util.HashMap<String, Ice.Object>();
+ }
+
+ public synchronized boolean
+ hasServant(Ice.Identity 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.
+ //
+ //assert(_instance != null); // Must not be called after destruction.
+
+ java.util.Map<String, Ice.Object> m = _servantMapMap.get(ident);
+ if(m == null)
+ {
+ return false;
+ }
+ else
+ {
+ assert(!m.isEmpty());
+ return true;
+ }
+ }
+
+ public synchronized void
+ addServantLocator(Ice.ServantLocator locator, String category)
+ {
+ assert(_instance != null); // Must not be called after destruction.
+
+ Ice.ServantLocator l = _locatorMap.get(category);
+ if(l != null)
+ {
+ Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException();
+ ex.id = IceUtilInternal.StringUtil.escapeString(category, "");
+ ex.kindOfObject = "servant locator";
+ throw ex;
+ }
+
+ _locatorMap.put(category, locator);
+ }
+
+ public synchronized Ice.ServantLocator
+ removeServantLocator(String category)
+ {
+ Ice.ServantLocator l = null;
+ assert(_instance != null); // Must not be called after destruction.
+
+ l = _locatorMap.remove(category);
+ if(l == null)
+ {
+ Ice.NotRegisteredException ex = new Ice.NotRegisteredException();
+ ex.id = IceUtilInternal.StringUtil.escapeString(category, "");
+ ex.kindOfObject = "servant locator";
+ throw ex;
+ }
+ return l;
+ }
+
+ public synchronized Ice.ServantLocator
+ findServantLocator(String 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.
+ //
+ //assert(_instance != null); // Must not be called after destruction.
+
+ return _locatorMap.get(category);
+ }
+
+ //
+ // Only for use by Ice.ObjectAdatperI.
+ //
+ public
+ ServantManager(Instance instance, String adapterName)
+ {
+ _instance = instance;
+ _adapterName = adapterName;
+ }
+
+ //
+ // Only for use by Ice.ObjectAdapterI.
+ //
+ public void
+ destroy()
+ {
+ java.util.Map<String, Ice.ServantLocator> locatorMap = new java.util.HashMap<String, Ice.ServantLocator>();
+ Ice.Logger logger = null;
+ synchronized(this)
+ {
+ //
+ // If the ServantManager has already been destroyed, we're done.
+ //
+ if(_instance == null)
+ {
+ return;
+ }
+
+ logger = _instance.initializationData().logger;
+
+ _servantMapMap.clear();
+
+ _defaultServantMap.clear();
+
+ locatorMap.putAll(_locatorMap);
+ _locatorMap.clear();
+
+ _instance = null;
+ }
+
+ for(java.util.Map.Entry<String, Ice.ServantLocator> p : locatorMap.entrySet())
+ {
+ Ice.ServantLocator locator = p.getValue();
+ try
+ {
+ locator.deactivate(p.getKey());
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception during locator deactivation:\n" + "object adapter: `" + _adapterName + "'\n" +
+ "locator category: `" + p.getKey() + "'\n" + Ex.toString(ex);
+ logger.error(s);
+ }
+ }
+ }
+
+ private Instance _instance;
+ final private String _adapterName;
+ private java.util.Map<Ice.Identity, java.util.Map<String, Ice.Object> > _servantMapMap =
+ new java.util.HashMap<Ice.Identity, java.util.Map<String, Ice.Object> >();
+ private java.util.Map<String, Ice.Object> _defaultServantMap = new java.util.HashMap<String, Ice.Object>();
+ private java.util.Map<String, Ice.ServantLocator> _locatorMap = new java.util.HashMap<String, Ice.ServantLocator>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/SocketOperation.java b/java-compat/src/Ice/src/main/java/IceInternal/SocketOperation.java
new file mode 100644
index 00000000000..030d5d32bfd
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/SocketOperation.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.nio.channels.SelectionKey;
+
+public class SocketOperation
+{
+ public static final int None = 0;
+ public static final int Read = SelectionKey.OP_READ;
+ public static final int Write = SelectionKey.OP_WRITE;
+ public static final int Connect = SelectionKey.OP_CONNECT;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/StreamSocket.java b/java-compat/src/Ice/src/main/java/IceInternal/StreamSocket.java
new file mode 100644
index 00000000000..03cd265e0e6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/StreamSocket.java
@@ -0,0 +1,329 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class StreamSocket
+{
+ public StreamSocket(ProtocolInstance instance,
+ NetworkProxy proxy,
+ java.net.InetSocketAddress addr,
+ java.net.InetSocketAddress sourceAddr)
+ {
+ _instance = instance;
+ _proxy = proxy;
+ _addr = addr;
+ _fd = Network.createTcpSocket();
+ _state = StateNeedConnect;
+
+ try
+ {
+ init();
+ if(Network.doConnect(_fd, _proxy != null ? _proxy.getAddress() : _addr, sourceAddr))
+ {
+ _state = _proxy != null ? StateProxyWrite : StateConnected;
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ assert(!_fd.isOpen());
+ _fd = null; // Necessary for the finalizer
+ throw ex;
+ }
+
+ _desc = Network.fdToString(_fd, _proxy, _addr);
+ }
+
+ public StreamSocket(ProtocolInstance instance, java.nio.channels.SocketChannel fd)
+ {
+ _instance = instance;
+ _proxy = null;
+ _addr = null;
+ _fd = fd;
+ _state = StateConnected;
+
+ try
+ {
+ init();
+ }
+ catch(Ice.LocalException ex)
+ {
+ assert(!_fd.isOpen());
+ _fd = null; // Necessary for the finalizer
+ throw ex;
+ }
+
+ _desc = Network.fdToString(_fd);
+ }
+
+ @Override
+ protected synchronized void finalize()
+ throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_fd == null);
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ public void setBufferSize(int rcvSize, int sndSize)
+ {
+ Network.setTcpBufSize(_fd, rcvSize, sndSize, _instance);
+ }
+
+ public int connect(Buffer readBuffer, Buffer writeBuffer)
+ {
+ if(_state == StateNeedConnect)
+ {
+ _state = StateConnectPending;
+ return SocketOperation.Connect;
+ }
+ else if(_state <= StateConnectPending)
+ {
+ Network.doFinishConnect(_fd);
+ _desc = Network.fdToString(_fd, _proxy, _addr);
+ _state = _proxy != null ? StateProxyWrite : StateConnected;
+ }
+
+ if(_state == StateProxyWrite)
+ {
+ _proxy.beginWrite(_addr, writeBuffer);
+ return SocketOperation.Write;
+ }
+ else if(_state == StateProxyRead)
+ {
+ _proxy.beginRead(readBuffer);
+ return SocketOperation.Read;
+ }
+ else if(_state == StateProxyConnected)
+ {
+ _proxy.finish(readBuffer, writeBuffer);
+
+ readBuffer.clear();
+ writeBuffer.clear();
+
+ _state = StateConnected;
+ }
+
+ assert(_state == StateConnected);
+ return SocketOperation.None;
+ }
+
+ public boolean isConnected()
+ {
+ return _state == StateConnected;
+ }
+
+ public java.nio.channels.SocketChannel fd()
+ {
+ return _fd;
+ }
+
+ public int read(Buffer buf)
+ {
+ if(_state == StateProxyRead)
+ {
+ while(true)
+ {
+ int ret = read(buf.b);
+ if(ret == 0)
+ {
+ return SocketOperation.Read;
+ }
+ _state = toState(_proxy.endRead(buf));
+ if(_state != StateProxyRead)
+ {
+ return SocketOperation.None;
+ }
+ }
+ }
+ read(buf.b);
+ return buf.b.hasRemaining() ? SocketOperation.Read : SocketOperation.None;
+ }
+
+ public int write(Buffer buf)
+ {
+ if(_state == StateProxyWrite)
+ {
+ while(true)
+ {
+ int ret = write(buf.b);
+ if(ret == 0)
+ {
+ return SocketOperation.Write;
+ }
+ _state = toState(_proxy.endWrite(buf));
+ if(_state != StateProxyWrite)
+ {
+ return SocketOperation.None;
+ }
+ }
+ }
+ write(buf.b);
+ return buf.b.hasRemaining() ? SocketOperation.Write : SocketOperation.None;
+ }
+
+ public int read(java.nio.ByteBuffer buf)
+ {
+ assert(_fd != null);
+
+ int read = 0;
+
+ while(buf.hasRemaining())
+ {
+ try
+ {
+ int ret = _fd.read(buf);
+ if(ret == -1)
+ {
+ throw new Ice.ConnectionLostException();
+ }
+ else if(ret == 0)
+ {
+ return read;
+ }
+
+ read += ret;
+ }
+ catch(java.io.InterruptedIOException ex)
+ {
+ continue;
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.ConnectionLostException(ex);
+ }
+ }
+ return read;
+ }
+
+ public int write(java.nio.ByteBuffer buf)
+ {
+ assert(_fd != null);
+
+ int sent = 0;
+ while(buf.hasRemaining())
+ {
+ try
+ {
+ int ret;
+ if(_maxSendPacketSize > 0 && buf.remaining() > _maxSendPacketSize)
+ {
+ int previous = buf.limit();
+ buf.limit(buf.position() + _maxSendPacketSize);
+ ret = _fd.write(buf);
+ buf.limit(previous);
+ }
+ else
+ {
+ ret = _fd.write(buf);
+ }
+
+ if(ret == -1)
+ {
+ throw new Ice.ConnectionLostException();
+ }
+ else if(ret == 0)
+ {
+ return sent;
+ }
+ sent += ret;
+ }
+ catch(java.io.InterruptedIOException ex)
+ {
+ continue;
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+ return sent;
+ }
+
+ public void close()
+ {
+ assert(_fd != null);
+ try
+ {
+ _fd.close();
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ finally
+ {
+ _fd = null;
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return _desc;
+ }
+
+ private void init()
+ {
+ Network.setBlock(_fd, false);
+ Network.setTcpBufSize(_fd, _instance);
+
+ if(System.getProperty("os.name").startsWith("Windows"))
+ {
+ //
+ // On Windows, limiting the buffer size is important to prevent
+ // poor throughput performances when sending large amount of
+ // data. See Microsoft KB article KB823764.
+ //
+ _maxSendPacketSize = java.lang.Math.max(512, Network.getSendBufferSize(_fd) / 2);
+ }
+ else
+ {
+ _maxSendPacketSize = 0;
+ }
+ }
+
+ private int toState(int operation)
+ {
+ switch(operation)
+ {
+ case SocketOperation.Read:
+ return StateProxyRead;
+ case SocketOperation.Write:
+ return StateProxyWrite;
+ default:
+ return StateProxyConnected;
+ }
+ }
+
+ private final ProtocolInstance _instance;
+
+ final private NetworkProxy _proxy;
+ final private java.net.InetSocketAddress _addr;
+
+ private java.nio.channels.SocketChannel _fd;
+ private int _maxSendPacketSize;
+ private int _state;
+ private String _desc;
+
+ private static final int StateNeedConnect = 0;
+ private static final int StateConnectPending = 1;
+ private static final int StateProxyRead = 2;
+ private static final int StateProxyWrite = 3;
+ private static final int StateProxyConnected = 4;
+ private static final int StateConnected = 5;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/TcpAcceptor.java b/java-compat/src/Ice/src/main/java/IceInternal/TcpAcceptor.java
new file mode 100644
index 00000000000..27418ca2bad
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/TcpAcceptor.java
@@ -0,0 +1,150 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+class TcpAcceptor implements Acceptor
+{
+ @Override
+ public java.nio.channels.ServerSocketChannel fd()
+ {
+ return _fd;
+ }
+
+ @Override
+ public void setReadyCallback(ReadyCallback callback)
+ {
+ // No need to for the ready callback.
+ }
+
+ @Override
+ public void close()
+ {
+ if(_fd != null)
+ {
+ Network.closeSocketNoThrow(_fd);
+ _fd = null;
+ }
+ }
+
+ @Override
+ public EndpointI listen()
+ {
+ try
+ {
+ _addr = Network.doBind(_fd, _addr, _backlog);
+ }
+ catch(Ice.Exception ex)
+ {
+ _fd = null;
+ throw ex;
+ }
+ _endpoint = _endpoint.endpoint(this);
+ return _endpoint;
+ }
+
+ @Override
+ public Transceiver accept()
+ {
+ return new TcpTransceiver(_instance, new StreamSocket(_instance, Network.doAccept(_fd)));
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public String toString()
+ {
+ return Network.addrToString(_addr);
+ }
+
+ @Override
+ public String toDetailedString()
+ {
+ StringBuffer s = new StringBuffer("local address = ");
+ s.append(toString());
+
+ java.util.List<String> intfs =
+ Network.getHostsForEndpointExpand(_addr.getAddress().getHostAddress(), _instance.protocolSupport(), true);
+ if(!intfs.isEmpty())
+ {
+ s.append("\nlocal interfaces = ");
+ s.append(IceUtilInternal.StringUtil.joinString(intfs, ", "));
+ }
+ return s.toString();
+ }
+
+ int effectivePort()
+ {
+ return _addr.getPort();
+ }
+
+ TcpAcceptor(TcpEndpointI endpoint, ProtocolInstance instance, String host, int port)
+ {
+ _endpoint = endpoint;
+ _instance = instance;
+ _backlog = instance.properties().getPropertyAsIntWithDefault("Ice.TCP.Backlog", 511);
+
+ try
+ {
+ _fd = Network.createTcpServerSocket();
+ Network.setBlock(_fd, false);
+ Network.setTcpBufSize(_fd, instance);
+ if(!System.getProperty("os.name").startsWith("Windows"))
+ {
+ //
+ // Enable SO_REUSEADDR on Unix platforms to allow re-using the
+ // socket even if it's in the TIME_WAIT state. On Windows,
+ // this doesn't appear to be necessary and enabling
+ // SO_REUSEADDR would actually not be a good thing since it
+ // allows a second process to bind to an address even it's
+ // already bound by another process.
+ //
+ // TODO: using SO_EXCLUSIVEADDRUSE on Windows would probably
+ // be better but it's only supported by recent Windows
+ // versions (XP SP2, Windows Server 2003).
+ //
+ Network.setReuseAddress(_fd, true);
+ }
+
+ _addr = Network.getAddressForServer(host, port, instance.protocolSupport(), instance.preferIPv6());
+ }
+ catch(RuntimeException ex)
+ {
+ _fd = null;
+ throw ex;
+ }
+ }
+
+ @Override
+ protected synchronized void finalize()
+ throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_fd == null);
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ private TcpEndpointI _endpoint;
+ private ProtocolInstance _instance;
+ private java.nio.channels.ServerSocketChannel _fd;
+ private int _backlog;
+ private java.net.InetSocketAddress _addr;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/TcpConnector.java b/java-compat/src/Ice/src/main/java/IceInternal/TcpConnector.java
new file mode 100644
index 00000000000..64ab2c3b515
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/TcpConnector.java
@@ -0,0 +1,101 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class TcpConnector implements Connector
+{
+ @Override
+ public Transceiver connect()
+ {
+ return new TcpTransceiver(_instance, new StreamSocket(_instance, _proxy, _addr, _sourceAddr));
+ }
+
+ @Override
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ @Override
+ public String toString()
+ {
+ return Network.addrToString(_proxy == null ? _addr : _proxy.getAddress());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return _hashCode;
+ }
+
+ //
+ // Only for use by TcpEndpoint
+ //
+ TcpConnector(ProtocolInstance instance, java.net.InetSocketAddress addr, NetworkProxy proxy,
+ java.net.InetSocketAddress sourceAddr, int timeout, String connectionId)
+ {
+ _instance = instance;
+ _addr = addr;
+ _proxy = proxy;
+ _sourceAddr = sourceAddr;
+ _timeout = timeout;
+ _connectionId = connectionId;
+
+ _hashCode = 5381;
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _addr.getAddress().getHostAddress());
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _addr.getPort());
+ if(_sourceAddr != null)
+ {
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _sourceAddr.getAddress().getHostAddress());
+ }
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _timeout);
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _connectionId);
+ }
+
+ @Override
+ public boolean equals(java.lang.Object obj)
+ {
+ if(!(obj instanceof TcpConnector))
+ {
+ return false;
+ }
+
+ if(this == obj)
+ {
+ return true;
+ }
+
+ TcpConnector p = (TcpConnector)obj;
+ if(_timeout != p._timeout)
+ {
+ return false;
+ }
+
+ if(!_connectionId.equals(p._connectionId))
+ {
+ return false;
+ }
+
+ if(Network.compareAddress(_sourceAddr, p._sourceAddr) != 0)
+ {
+ return false;
+ }
+
+ return Network.compareAddress(_addr, p._addr) == 0;
+ }
+
+ private ProtocolInstance _instance;
+ private java.net.InetSocketAddress _addr;
+ private NetworkProxy _proxy;
+ private java.net.InetSocketAddress _sourceAddr;
+ private int _timeout;
+ private String _connectionId = "";
+ private int _hashCode;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/TcpEndpointFactory.java b/java-compat/src/Ice/src/main/java/IceInternal/TcpEndpointFactory.java
new file mode 100644
index 00000000000..9211951ca59
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/TcpEndpointFactory.java
@@ -0,0 +1,58 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class TcpEndpointFactory implements EndpointFactory
+{
+ TcpEndpointFactory(ProtocolInstance instance)
+ {
+ _instance = instance;
+ }
+
+ @Override
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public EndpointI create(java.util.ArrayList<String> args, boolean oaEndpoint)
+ {
+ IPEndpointI endpt = new TcpEndpointI(_instance);
+ endpt.initWithOptions(args, oaEndpoint);
+ return endpt;
+ }
+
+ @Override
+ public EndpointI read(Ice.InputStream s)
+ {
+ return new TcpEndpointI(_instance, s);
+ }
+
+ @Override
+ public void destroy()
+ {
+ _instance = null;
+ }
+
+ @Override
+ public EndpointFactory clone(ProtocolInstance instance, EndpointFactory delegate)
+ {
+ return new TcpEndpointFactory(instance);
+ }
+
+ private ProtocolInstance _instance;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/TcpEndpointI.java b/java-compat/src/Ice/src/main/java/IceInternal/TcpEndpointI.java
new file mode 100644
index 00000000000..f038da63a2d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/TcpEndpointI.java
@@ -0,0 +1,317 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class TcpEndpointI extends IPEndpointI
+{
+ public TcpEndpointI(ProtocolInstance instance, String ho, int po, java.net.InetSocketAddress sourceAddr, int ti,
+ String conId, boolean co)
+ {
+ super(instance, ho, po, sourceAddr, conId);
+ _timeout = ti;
+ _compress = co;
+ }
+
+ public TcpEndpointI(ProtocolInstance instance)
+ {
+ super(instance);
+ _timeout = _instance.defaultTimeout();
+ _compress = false;
+ }
+
+ public TcpEndpointI(ProtocolInstance instance, Ice.InputStream s)
+ {
+ super(instance, s);
+ _timeout = s.readInt();
+ _compress = s.readBool();
+ }
+
+ //
+ // Return the endpoint information.
+ //
+ @Override
+ public Ice.EndpointInfo getInfo()
+ {
+ Ice.TCPEndpointInfo info = new Ice.TCPEndpointInfo()
+ {
+ @Override
+ public short type()
+ {
+ return TcpEndpointI.this.type();
+ }
+
+ @Override
+ public boolean datagram()
+ {
+ return TcpEndpointI.this.datagram();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return TcpEndpointI.this.secure();
+ }
+ };
+ fillEndpointInfo(info);
+ return info;
+ }
+
+ //
+ // Return the timeout for the endpoint in milliseconds. 0 means
+ // non-blocking, -1 means no timeout.
+ //
+ @Override
+ public int timeout()
+ {
+ return _timeout;
+ }
+
+ //
+ // Return a new endpoint with a different timeout value, provided
+ // that timeouts are supported by the endpoint. Otherwise the same
+ // endpoint is returned.
+ //
+ @Override
+ public EndpointI timeout(int timeout)
+ {
+ if(timeout == _timeout)
+ {
+ return this;
+ }
+ else
+ {
+ return new TcpEndpointI(_instance, _host, _port, _sourceAddr, timeout, _connectionId, _compress);
+ }
+ }
+
+ //
+ // Return true if the endpoints support bzip2 compress, or false
+ // otherwise.
+ //
+ @Override
+ public boolean compress()
+ {
+ return _compress;
+ }
+
+ //
+ // Return a new endpoint with a different compression value,
+ // provided that compression is supported by the
+ // endpoint. Otherwise the same endpoint is returned.
+ //
+ @Override
+ public EndpointI compress(boolean compress)
+ {
+ if(compress == _compress)
+ {
+ return this;
+ }
+ else
+ {
+ return new TcpEndpointI(_instance, _host, _port, _sourceAddr, _timeout, _connectionId, compress);
+ }
+ }
+
+ //
+ // Return true if the endpoint is datagram-based.
+ //
+ @Override
+ public boolean datagram()
+ {
+ return false;
+ }
+
+ //
+ // Return a server side transceiver for this endpoint, or null if a
+ // transceiver can only be created by an acceptor.
+ //
+ @Override
+ public Transceiver transceiver()
+ {
+ return null;
+ }
+
+ //
+ // Return an acceptor for this endpoint, or null if no acceptors
+ // is available.
+ //
+ @Override
+ public Acceptor acceptor(String adapterName)
+ {
+ return new TcpAcceptor(this, _instance, _host, _port);
+ }
+
+ public TcpEndpointI endpoint(TcpAcceptor acceptor)
+ {
+ return new TcpEndpointI(_instance, _host, acceptor.effectivePort(), _sourceAddr, _timeout,
+ _connectionId, _compress);
+ }
+
+ @Override
+ public String options()
+ {
+ //
+ // 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.
+ //
+ String s = super.options();
+
+ if(_timeout == -1)
+ {
+ s += " -t infinite";
+ }
+ else
+ {
+ s += " -t " + _timeout;
+ }
+
+ if(_compress)
+ {
+ s += " -z";
+ }
+
+ return s;
+ }
+
+ //
+ // Compare endpoints for sorting purposes
+ //
+ @Override
+ public int compareTo(EndpointI obj) // From java.lang.Comparable
+ {
+ if(!(obj instanceof TcpEndpointI))
+ {
+ return type() < obj.type() ? -1 : 1;
+ }
+
+ TcpEndpointI p = (TcpEndpointI)obj;
+ if(this == p)
+ {
+ return 0;
+ }
+
+ if(_timeout < p._timeout)
+ {
+ return -1;
+ }
+ else if(p._timeout < _timeout)
+ {
+ return 1;
+ }
+
+ if(!_compress && p._compress)
+ {
+ return -1;
+ }
+ else if(!p._compress && _compress)
+ {
+ return 1;
+ }
+
+ return super.compareTo(obj);
+ }
+
+ @Override
+ public void streamWriteImpl(Ice.OutputStream s)
+ {
+ super.streamWriteImpl(s);
+ s.writeInt(_timeout);
+ s.writeBool(_compress);
+ }
+
+ @Override
+ public int hashInit(int h)
+ {
+ h = super.hashInit(h);
+ h = IceInternal.HashUtil.hashAdd(h, _timeout);
+ h = IceInternal.HashUtil.hashAdd(h, _compress);
+ return h;
+ }
+
+ @Override
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ if(super.checkOption(option, argument, endpoint))
+ {
+ return true;
+ }
+
+ switch(option.charAt(1))
+ {
+ case 't':
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -t option in endpoint " + endpoint);
+ }
+
+ if(argument.equals("infinite"))
+ {
+ _timeout = -1;
+ }
+ else
+ {
+ try
+ {
+ _timeout = Integer.parseInt(argument);
+ if(_timeout < 1)
+ {
+ throw new Ice.EndpointParseException("invalid timeout value `" + argument +
+ "' in endpoint " + endpoint);
+ }
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid timeout value `" + argument +
+ "' in endpoint " + endpoint);
+ }
+ }
+
+ return true;
+ }
+
+ case 'z':
+ {
+ if(argument != null)
+ {
+ throw new Ice.EndpointParseException("unexpected argument `" + argument +
+ "' provided for -z option in " + endpoint);
+ }
+
+ _compress = true;
+
+ return true;
+ }
+
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ protected Connector createConnector(java.net.InetSocketAddress addr, NetworkProxy proxy)
+ {
+ return new TcpConnector(_instance, addr, proxy, _sourceAddr, _timeout, _connectionId);
+ }
+
+ @Override
+ protected IPEndpointI createEndpoint(String host, int port, String connectionId)
+ {
+ return new TcpEndpointI(_instance, host, port, _sourceAddr, _timeout, connectionId, _compress);
+ }
+
+ private int _timeout;
+ private boolean _compress;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/TcpTransceiver.java b/java-compat/src/Ice/src/main/java/IceInternal/TcpTransceiver.java
new file mode 100644
index 00000000000..069e79a3408
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/TcpTransceiver.java
@@ -0,0 +1,126 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class TcpTransceiver implements Transceiver
+{
+ @Override
+ public java.nio.channels.SelectableChannel fd()
+ {
+ assert(_stream != null);
+ return _stream.fd();
+ }
+
+ @Override
+ public void setReadyCallback(ReadyCallback callback)
+ {
+ // No need of the callback
+ }
+
+ @Override
+ public int initialize(Buffer readBuffer, Buffer writeBuffer)
+ {
+ return _stream.connect(readBuffer, writeBuffer);
+ }
+
+ @Override
+ public int closing(boolean initiator, Ice.LocalException ex)
+ {
+ // If we are initiating the connection closure, wait for the peer
+ // to close the TCP/IP connection. Otherwise, close immediately.
+ return initiator ? SocketOperation.Read : SocketOperation.None;
+ }
+
+ @Override
+ public void close()
+ {
+ _stream.close();
+ }
+
+ @Override
+ public EndpointI bind()
+ {
+ assert(false);
+ return null;
+ }
+
+ @Override
+ public int write(Buffer buf)
+ {
+ return _stream.write(buf);
+ }
+
+ @Override
+ public int read(Buffer buf)
+ {
+ return _stream.read(buf);
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public String toString()
+ {
+ return _stream.toString();
+ }
+
+ @Override
+ public String toDetailedString()
+ {
+ return toString();
+ }
+
+ @Override
+ public Ice.ConnectionInfo getInfo()
+ {
+ Ice.TCPConnectionInfo info = new Ice.TCPConnectionInfo();
+ if(_stream.fd() != null)
+ {
+ java.net.Socket socket = _stream.fd().socket();
+ info.localAddress = socket.getLocalAddress().getHostAddress();
+ info.localPort = socket.getLocalPort();
+ if(socket.getInetAddress() != null)
+ {
+ info.remoteAddress = socket.getInetAddress().getHostAddress();
+ info.remotePort = socket.getPort();
+ }
+ if(!socket.isClosed())
+ {
+ info.rcvSize = Network.getRecvBufferSize(_stream.fd());
+ info.sndSize = Network.getSendBufferSize(_stream.fd());
+ }
+ }
+ return info;
+ }
+
+ @Override
+ public void checkSendSize(Buffer buf)
+ {
+ }
+
+ @Override
+ public void setBufferSize(int rcvSize, int sndSize)
+ {
+ _stream.setBufferSize(rcvSize, sndSize);
+ }
+
+ TcpTransceiver(ProtocolInstance instance, StreamSocket stream)
+ {
+ _instance = instance;
+ _stream = stream;
+ }
+
+ final private ProtocolInstance _instance;
+ final private StreamSocket _stream;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ThreadObserverI.java b/java-compat/src/Ice/src/main/java/IceInternal/ThreadObserverI.java
new file mode 100644
index 00000000000..553e46840bf
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ThreadObserverI.java
@@ -0,0 +1,68 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ThreadObserverI
+ extends IceMX.ObserverWithDelegate<IceMX.ThreadMetrics, Ice.Instrumentation.ThreadObserver>
+ implements Ice.Instrumentation.ThreadObserver
+{
+ @Override
+ public void
+ stateChanged(final Ice.Instrumentation.ThreadState oldState, final Ice.Instrumentation.ThreadState newState)
+ {
+ _oldState = oldState;
+ _newState = newState;
+ forEach(_threadStateUpdate);
+ if(_delegate != null)
+ {
+ _delegate.stateChanged(oldState, newState);
+ }
+ }
+
+ private MetricsUpdate<IceMX.ThreadMetrics> _threadStateUpdate = new MetricsUpdate<IceMX.ThreadMetrics>()
+ {
+ @Override
+ public void
+ update(IceMX.ThreadMetrics v)
+ {
+ switch(_oldState)
+ {
+ case ThreadStateInUseForIO:
+ --v.inUseForIO;
+ break;
+ case ThreadStateInUseForUser:
+ --v.inUseForUser;
+ break;
+ case ThreadStateInUseForOther:
+ --v.inUseForOther;
+ break;
+ default:
+ break;
+ }
+ switch(_newState)
+ {
+ case ThreadStateInUseForIO:
+ ++v.inUseForIO;
+ break;
+ case ThreadStateInUseForUser:
+ ++v.inUseForUser;
+ break;
+ case ThreadStateInUseForOther:
+ ++v.inUseForOther;
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ private Ice.Instrumentation.ThreadState _oldState;
+ private Ice.Instrumentation.ThreadState _newState;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ThreadPool.java b/java-compat/src/Ice/src/main/java/IceInternal/ThreadPool.java
new file mode 100644
index 00000000000..9dc5f1ec92a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ThreadPool.java
@@ -0,0 +1,823 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class ThreadPool
+{
+ final class ShutdownWorkItem implements ThreadPoolWorkItem
+ {
+ @Override
+ public void execute(ThreadPoolCurrent current)
+ {
+ current.ioCompleted();
+ try
+ {
+ _instance.objectAdapterFactory().shutdown();
+ }
+ catch(Ice.CommunicatorDestroyedException ex)
+ {
+ }
+ }
+ }
+
+ static final class FinishedWorkItem implements ThreadPoolWorkItem
+ {
+ public
+ FinishedWorkItem(EventHandler handler, boolean close)
+ {
+ _handler = handler;
+ _close = close;
+ }
+
+ @Override
+ public void execute(ThreadPoolCurrent current)
+ {
+ _handler.finished(current, _close);
+ }
+
+ private final EventHandler _handler;
+ private final boolean _close;
+ }
+
+ static final class JoinThreadWorkItem implements ThreadPoolWorkItem
+ {
+ public
+ JoinThreadWorkItem(EventHandlerThread thread)
+ {
+ _thread = thread;
+ }
+
+ @Override
+ public void execute(ThreadPoolCurrent current)
+ {
+ // No call to ioCompleted, this shouldn't block (and we don't want to cause
+ // a new thread to be started).
+ try
+ {
+ _thread.join();
+ }
+ catch (InterruptedException e)
+ {
+ // Ignore.
+ }
+ }
+
+ private final EventHandlerThread _thread;
+ }
+
+ static final class InterruptWorkItem implements ThreadPoolWorkItem
+ {
+ @Override
+ public void execute(ThreadPoolCurrent current)
+ {
+ // Nothing to do, this is just used to interrupt the thread pool selector.
+ }
+ }
+
+ private static ThreadPoolWorkItem _interruptWorkItem = new InterruptWorkItem();
+
+ //
+ // Exception raised by the thread pool work queue when the thread pool
+ // is destroyed.
+ //
+ static final class DestroyedException extends RuntimeException
+ {
+ }
+
+ public
+ ThreadPool(Instance instance, String prefix, int timeout)
+ {
+ Ice.Properties properties = instance.initializationData().properties;
+
+ _instance = instance;
+ _dispatcher = instance.initializationData().dispatcher;
+ _destroyed = false;
+ _prefix = prefix;
+ _selector = new Selector(instance);
+ _threadIndex = 0;
+ _inUse = 0;
+ _inUseIO = 0;
+ _promote = true;
+ _serialize = properties.getPropertyAsInt(_prefix + ".Serialize") > 0;
+ _serverIdleTime = timeout;
+ _threadPrefix = Util.createThreadName(properties, _prefix);
+
+ int nProcessors = Runtime.getRuntime().availableProcessors();
+
+ //
+ // We use just one thread as the default. This is the fastest
+ // possible setting, still allows one level of nesting, and
+ // doesn't require to make the servants thread safe.
+ //
+ int size = properties.getPropertyAsIntWithDefault(_prefix + ".Size", 1);
+ if(size < 1)
+ {
+ String s = _prefix + ".Size < 1; Size adjusted to 1";
+ _instance.initializationData().logger.warning(s);
+ size = 1;
+ }
+
+ int sizeMax = properties.getPropertyAsIntWithDefault(_prefix + ".SizeMax", size);
+ if(sizeMax == -1)
+ {
+ sizeMax = nProcessors;
+ }
+ if(sizeMax < size)
+ {
+ String s = _prefix + ".SizeMax < " + _prefix + ".Size; SizeMax adjusted to Size (" + size + ")";
+ _instance.initializationData().logger.warning(s);
+ sizeMax = size;
+ }
+
+ int sizeWarn = properties.getPropertyAsInt(_prefix + ".SizeWarn");
+ if(sizeWarn != 0 && sizeWarn < size)
+ {
+ String s = _prefix + ".SizeWarn < " + _prefix + ".Size; adjusted SizeWarn to Size (" + size + ")";
+ _instance.initializationData().logger.warning(s);
+ sizeWarn = size;
+ }
+ else if(sizeWarn > sizeMax)
+ {
+ String s = _prefix + ".SizeWarn > " + _prefix + ".SizeMax; adjusted SizeWarn to SizeMax (" + sizeMax + ")";
+ _instance.initializationData().logger.warning(s);
+ sizeWarn = sizeMax;
+ }
+
+ int threadIdleTime = properties.getPropertyAsIntWithDefault(_prefix + ".ThreadIdleTime", 60);
+ if(threadIdleTime < 0)
+ {
+ String s = _prefix + ".ThreadIdleTime < 0; ThreadIdleTime adjusted to 0";
+ _instance.initializationData().logger.warning(s);
+ threadIdleTime = 0;
+ }
+
+ _size = size;
+ _sizeMax = sizeMax;
+ _sizeWarn = sizeWarn;
+ _sizeIO = Math.min(sizeMax, nProcessors);
+ _threadIdleTime = threadIdleTime;
+
+ int stackSize = properties.getPropertyAsInt( _prefix + ".StackSize");
+ if(stackSize < 0)
+ {
+ String s = _prefix + ".StackSize < 0; Size adjusted to JRE default";
+ _instance.initializationData().logger.warning(s);
+ stackSize = 0;
+ }
+ _stackSize = stackSize;
+
+ boolean hasPriority = properties.getProperty(_prefix + ".ThreadPriority").length() > 0;
+ int priority = properties.getPropertyAsInt(_prefix + ".ThreadPriority");
+ if(!hasPriority)
+ {
+ hasPriority = properties.getProperty("Ice.ThreadPriority").length() > 0;
+ priority = properties.getPropertyAsInt("Ice.ThreadPriority");
+ }
+ _hasPriority = hasPriority;
+ _priority = priority;
+
+ _workQueue = new ThreadPoolWorkQueue(_instance, this, _selector);
+ _nextHandler = _handlers.iterator();
+
+ if(_instance.traceLevels().threadPool >= 1)
+ {
+ String s = "creating " + _prefix + ": Size = " + _size + ", SizeMax = " + _sizeMax + ", SizeWarn = " +
+ _sizeWarn;
+ _instance.initializationData().logger.trace(_instance.traceLevels().threadPoolCat, s);
+ }
+
+ try
+ {
+ for(int i = 0; i < _size; i++)
+ {
+ EventHandlerThread thread = new EventHandlerThread(_threadPrefix + "-" + _threadIndex++);
+ if(_hasPriority)
+ {
+ thread.start(_priority);
+ }
+ else
+ {
+ thread.start(java.lang.Thread.NORM_PRIORITY);
+ }
+ _threads.add(thread);
+ }
+ }
+ catch(RuntimeException ex)
+ {
+ String s = "cannot create thread for `" + _prefix + "':\n" + Ex.toString(ex);
+ _instance.initializationData().logger.error(s);
+
+ destroy();
+ try
+ {
+ joinWithAllThreads();
+ }
+ catch (InterruptedException e)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ throw ex;
+ }
+ }
+
+ @Override
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_destroyed);
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ public synchronized void
+ destroy()
+ {
+ if(_destroyed)
+ {
+ return;
+ }
+
+ _destroyed = true;
+ _workQueue.destroy();
+ }
+
+ public synchronized void
+ updateObservers()
+ {
+ for(EventHandlerThread thread : _threads)
+ {
+ thread.updateObserver();
+ }
+ }
+
+ public synchronized void
+ initialize(final EventHandler handler)
+ {
+ assert(!_destroyed);
+ _selector.initialize(handler);
+
+ handler.setReadyCallback(
+ new ReadyCallback()
+ {
+ public void ready(int op, boolean value)
+ {
+ synchronized(ThreadPool.this)
+ {
+ if(_destroyed)
+ {
+ return;
+ }
+ _selector.ready(handler, op, value);
+ }
+ }
+ });
+ }
+
+ public void
+ register(EventHandler handler, int op)
+ {
+ update(handler, SocketOperation.None, op);
+ }
+
+ public synchronized void
+ update(EventHandler handler, int remove, int add)
+ {
+ assert(!_destroyed);
+
+ // Don't remove what needs to be added
+ remove &= ~add;
+
+ // Don't remove/add if already un-registered or registered
+ remove = handler._registered & remove;
+ add = ~handler._registered & add;
+ if(remove == add)
+ {
+ return;
+ }
+ _selector.update(handler, remove, add);
+ }
+
+ public void
+ unregister(EventHandler handler, int op)
+ {
+ update(handler, op, SocketOperation.None);
+ }
+
+ public synchronized boolean
+ finish(EventHandler handler, boolean closeNow)
+ {
+ assert(!_destroyed);
+ closeNow = _selector.finish(handler, closeNow);
+ _workQueue.queue(new FinishedWorkItem(handler, !closeNow));
+ return closeNow;
+ }
+
+ public void
+ dispatchFromThisThread(DispatchWorkItem workItem)
+ {
+ if(_dispatcher != null)
+ {
+ try
+ {
+ _dispatcher.dispatch(workItem, workItem.getConnection());
+ }
+ catch(java.lang.Exception ex)
+ {
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 1)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ _instance.initializationData().logger.warning("dispatch exception:\n" + sw.toString());
+ }
+ }
+ }
+ else
+ {
+ workItem.run();
+ }
+ }
+
+ synchronized public void
+ dispatch(DispatchWorkItem workItem)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.CommunicatorDestroyedException();
+ }
+ _workQueue.queue(workItem);
+ }
+
+ public void
+ joinWithAllThreads()
+ throws InterruptedException
+ {
+ //
+ // _threads is immutable after destroy() has been called,
+ // therefore no synchronization is needed. (Synchronization
+ // wouldn't be possible here anyway, because otherwise the
+ // other threads would never terminate.)
+ //
+ for(EventHandlerThread thread : _threads)
+ {
+ thread.join();
+ }
+
+ //
+ // Destroy the selector
+ //
+ _selector.destroy();
+ }
+
+ private void
+ run(EventHandlerThread thread)
+ {
+ ThreadPoolCurrent current = new ThreadPoolCurrent(_instance, this, thread);
+ boolean select = false;
+ while(true)
+ {
+ if(current._handler != null)
+ {
+ try
+ {
+ current._handler.message(current);
+ }
+ catch(DestroyedException ex)
+ {
+ return;
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception in `" + _prefix + "':\n" + Ex.toString(ex);
+ s += "\nevent handler: " + current._handler.toString();
+ _instance.initializationData().logger.error(s);
+ }
+ }
+ else if(select)
+ {
+ try
+ {
+ _selector.select(_serverIdleTime);
+ }
+ catch(Selector.TimeoutException ex)
+ {
+ synchronized(this)
+ {
+ if(!_destroyed && _inUse == 0)
+ {
+ _workQueue.queue(new ShutdownWorkItem()); // Select timed-out.
+ }
+ continue;
+ }
+ }
+ }
+
+ synchronized(this)
+ {
+ if(current._handler == null)
+ {
+ if(select)
+ {
+ _selector.finishSelect(_handlers);
+ select = false;
+ _nextHandler = _handlers.iterator();
+ }
+ else if(!current._leader && followerWait(current))
+ {
+ return; // Wait timed-out.
+ }
+ }
+ else if(_sizeMax > 1)
+ {
+ if(!current._ioCompleted)
+ {
+ //
+ // The handler didn't call ioCompleted() so we take care of decreasing
+ // the IO thread count now.
+ //
+ --_inUseIO;
+ }
+ else
+ {
+ //
+ // If the handler called ioCompleted(), we re-enable the handler in
+ // case it was disabled and we decrease the number of thread in use.
+ //
+ if(_serialize)
+ {
+ _selector.enable(current._handler, current.operation);
+ }
+ assert(_inUse > 0);
+ --_inUse;
+ }
+
+ if(!current._leader && followerWait(current))
+ {
+ return; // Wait timed-out.
+ }
+ }
+
+ //
+ // Get the next ready handler.
+ //
+ current._handler = null;
+ while(_nextHandler.hasNext())
+ {
+ EventHandlerOpPair n = _nextHandler.next();
+ int op = n.op & ~n.handler._disabled & n.handler._registered;
+ if(op != 0)
+ {
+ current._ioCompleted = false;
+ current._handler = n.handler;
+ current.operation = op;
+ thread.setState(Ice.Instrumentation.ThreadState.ThreadStateInUseForIO);
+ break;
+ }
+ }
+
+ if(current._handler == null)
+ {
+ //
+ // If there are no more ready handlers and there are still threads busy performing
+ // IO, we give up leadership and promote another follower (which will perform the
+ // select() only once all the IOs are completed). Otherwise, if there's no more
+ // threads peforming IOs, it's time to do another select().
+ //
+ if(_inUseIO > 0)
+ {
+ promoteFollower(current);
+ }
+ else
+ {
+ _handlers.clear();
+ _selector.startSelect();
+ select = true;
+ thread.setState(Ice.Instrumentation.ThreadState.ThreadStateIdle);
+ }
+ }
+ else if(_sizeMax > 1)
+ {
+ //
+ // Increment the IO thread count and if there's still threads available
+ // to perform IO and more handlers ready, we promote a follower.
+ //
+ ++_inUseIO;
+ if(_nextHandler.hasNext() && _inUseIO < _sizeIO)
+ {
+ promoteFollower(current);
+ }
+ }
+ }
+ }
+ }
+
+ synchronized void
+ ioCompleted(ThreadPoolCurrent current)
+ {
+ current._ioCompleted = true; // Set the IO completed flag to specify that ioCompleted() has been called.
+
+ current._thread.setState(Ice.Instrumentation.ThreadState.ThreadStateInUseForUser);
+
+ if(_sizeMax > 1)
+ {
+ --_inUseIO;
+
+ if(!_destroyed)
+ {
+ if(_serialize)
+ {
+ _selector.disable(current._handler, current.operation);
+ }
+ }
+
+ if(current._leader)
+ {
+ //
+ // If this thread is still the leader, it's time to promote a new leader.
+ //
+ promoteFollower(current);
+ }
+ else if(_promote && (_nextHandler.hasNext() || _inUseIO == 0))
+ {
+ notify();
+ }
+
+ assert(_inUse >= 0);
+ ++_inUse;
+
+ if(_inUse == _sizeWarn)
+ {
+ String s = "thread pool `" + _prefix + "' is running low on threads\n"
+ + "Size=" + _size + ", " + "SizeMax=" + _sizeMax + ", " + "SizeWarn=" + _sizeWarn;
+ _instance.initializationData().logger.warning(s);
+ }
+
+ if(!_destroyed)
+ {
+ assert(_inUse <= _threads.size());
+ if(_inUse < _sizeMax && _inUse == _threads.size())
+ {
+ if(_instance.traceLevels().threadPool >= 1)
+ {
+ String s = "growing " + _prefix + ": Size=" + (_threads.size() + 1);
+ _instance.initializationData().logger.trace(_instance.traceLevels().threadPoolCat, s);
+ }
+
+ try
+ {
+ EventHandlerThread thread = new EventHandlerThread(_threadPrefix + "-" + _threadIndex++);
+ _threads.add(thread);
+ if(_hasPriority)
+ {
+ thread.start(_priority);
+ }
+ else
+ {
+ thread.start(java.lang.Thread.NORM_PRIORITY);
+ }
+ }
+ catch(RuntimeException ex)
+ {
+ String s = "cannot create thread for `" + _prefix + "':\n" + Ex.toString(ex);
+ _instance.initializationData().logger.error(s);
+ }
+ }
+ }
+ }
+ }
+
+ private synchronized void
+ promoteFollower(ThreadPoolCurrent current)
+ {
+ assert(!_promote && current._leader);
+ _promote = true;
+ if(_inUseIO < _sizeIO && (_nextHandler.hasNext() || _inUseIO == 0))
+ {
+ notify();
+ }
+ current._leader = false;
+ }
+
+ private synchronized boolean
+ followerWait(ThreadPoolCurrent current)
+ {
+ assert(!current._leader);
+
+ current._thread.setState(Ice.Instrumentation.ThreadState.ThreadStateIdle);
+
+ //
+ // It's important to clear the handler before waiting to make sure that
+ // resources for the handler are released now if it's finished. We also
+ // clear the per-thread stream.
+ //
+ current._handler = null;
+ current.stream.reset();
+
+ //
+ // Wait to be promoted and for all the IO threads to be done.
+ //
+ while(!_promote || _inUseIO == _sizeIO || (!_nextHandler.hasNext() && _inUseIO > 0))
+ {
+ if(_threadIdleTime > 0)
+ {
+ long before = IceInternal.Time.currentMonotonicTimeMillis();
+ boolean interrupted = false;
+ try
+ {
+ //
+ // If the wait is interrupted then we'll let the thread die as if it timed out.
+ //
+ wait(_threadIdleTime * 1000);
+ }
+ catch (InterruptedException e)
+ {
+ interrupted = true;
+ }
+ if(interrupted || IceInternal.Time.currentMonotonicTimeMillis() - before >= _threadIdleTime * 1000)
+ {
+ if(!_destroyed && (!_promote || _inUseIO == _sizeIO || (!_nextHandler.hasNext() && _inUseIO > 0)))
+ {
+ if(_instance.traceLevels().threadPool >= 1)
+ {
+ String s = "shrinking " + _prefix + ": Size=" + (_threads.size() - 1);
+ _instance.initializationData().logger.trace(_instance.traceLevels().threadPoolCat, s);
+ }
+ assert(_threads.size() > 1); // Can only be called by a waiting follower thread.
+ _threads.remove(current._thread);
+ _workQueue.queue(new JoinThreadWorkItem(current._thread));
+ return true;
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ wait();
+ }
+ catch (InterruptedException e)
+ {
+ //
+ // Eat the InterruptedException.
+ //
+ }
+ }
+ }
+ current._leader = true; // The current thread has become the leader.
+ _promote = false;
+ return false;
+ }
+
+ private final Instance _instance;
+ private final Ice.Dispatcher _dispatcher;
+ private final ThreadPoolWorkQueue _workQueue;
+ private boolean _destroyed;
+ private final String _prefix;
+ private final String _threadPrefix;
+ private final Selector _selector;
+
+ final class EventHandlerThread implements Runnable
+ {
+ EventHandlerThread(String name)
+ {
+ _name = name;
+ _state = Ice.Instrumentation.ThreadState.ThreadStateIdle;
+ updateObserver();
+ }
+
+ public void
+ updateObserver()
+ {
+ // Must be called with the thread pool mutex locked
+ Ice.Instrumentation.CommunicatorObserver obsv = _instance.initializationData().observer;
+ if(obsv != null)
+ {
+ _observer = obsv.getThreadObserver(_prefix, _name, _state, _observer);
+ if(_observer != null)
+ {
+ _observer.attach();
+ }
+ }
+ }
+
+ public void
+ setState(Ice.Instrumentation.ThreadState s)
+ {
+ // Must be called with the thread pool mutex locked
+ if(_observer != null)
+ {
+ if(_state != s)
+ {
+ _observer.stateChanged(_state, s);
+ }
+ }
+ _state = s;
+ }
+
+ public void
+ join()
+ throws InterruptedException
+ {
+ _thread.join();
+ }
+
+ public void
+ start(int priority)
+ {
+ _thread = new Thread(null, this, _name, _stackSize);
+ _thread.setPriority(priority);
+ _thread.start();
+ }
+
+ @Override
+ public void
+ run()
+ {
+ if(_instance.initializationData().threadHook != null)
+ {
+ try
+ {
+ _instance.initializationData().threadHook.start();
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "thread hook start() method raised an unexpected exception in `";
+ s += _prefix + "' thread " + _name + ":\n" + Ex.toString(ex);
+ _instance.initializationData().logger.error(s);
+ }
+ }
+
+ try
+ {
+ ThreadPool.this.run(this);
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception in `" + _prefix + "' thread " + _name + ":\n" + Ex.toString(ex);
+ _instance.initializationData().logger.error(s);
+ }
+
+ if(_observer != null)
+ {
+ _observer.detach();
+ }
+
+ if(_instance.initializationData().threadHook != null)
+ {
+ try
+ {
+ _instance.initializationData().threadHook.stop();
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "thread hook stop() method raised an unexpected exception in `";
+ s += _prefix + "' thread " + _name + ":\n" + Ex.toString(ex);
+ _instance.initializationData().logger.error(s);
+ }
+ }
+ }
+
+ final private String _name;
+ private Thread _thread;
+ private Ice.Instrumentation.ThreadState _state;
+ private Ice.Instrumentation.ThreadObserver _observer;
+ }
+
+ private final int _size; // Number of threads that are pre-created.
+ private final int _sizeIO; // Number of threads that can concurrently perform IO.
+ private final int _sizeMax; // Maximum number of threads.
+ private final int _sizeWarn; // If _inUse reaches _sizeWarn, a "low on threads" warning will be printed.
+ private final boolean _serialize; // True if requests need to be serialized over the connection.
+ private final int _priority;
+ private final boolean _hasPriority;
+ private final long _serverIdleTime;
+ private final long _threadIdleTime;
+ private final int _stackSize;
+
+ private java.util.List<EventHandlerThread> _threads = new java.util.ArrayList<EventHandlerThread>();
+ private int _threadIndex; // For assigning thread names.
+ private int _inUse; // Number of threads that are currently in use.
+ private int _inUseIO; // Number of threads that are currently performing IO.
+
+ private java.util.List<EventHandlerOpPair> _handlers = new java.util.ArrayList<EventHandlerOpPair>();
+ private java.util.Iterator<EventHandlerOpPair> _nextHandler;
+
+ private boolean _promote;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolCurrent.java b/java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolCurrent.java
new file mode 100644
index 00000000000..cdd5b9fe2bc
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolCurrent.java
@@ -0,0 +1,51 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class ThreadPoolCurrent
+{
+ ThreadPoolCurrent(Instance instance, ThreadPool threadPool, ThreadPool.EventHandlerThread thread)
+ {
+ operation = SocketOperation.None;
+ stream = new Ice.InputStream(instance, Protocol.currentProtocolEncoding);
+
+ _threadPool = threadPool;
+ _thread = thread;
+ _ioCompleted = false;
+ _leader = false;
+ }
+
+ public int operation;
+ public Ice.InputStream stream; // A per-thread stream to be used by event handlers for optimization.
+
+ public boolean
+ ioReady()
+ {
+ return (_handler._registered & operation) > 0;
+ }
+
+ public void
+ ioCompleted()
+ {
+ _threadPool.ioCompleted(this);
+ }
+
+ public void
+ dispatchFromThisThread(DispatchWorkItem workItem)
+ {
+ _threadPool.dispatchFromThisThread(workItem);
+ }
+
+ final ThreadPool _threadPool;
+ final ThreadPool.EventHandlerThread _thread;
+ EventHandler _handler;
+ boolean _ioCompleted;
+ boolean _leader;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolWorkItem.java b/java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolWorkItem.java
new file mode 100644
index 00000000000..27f06f9366b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolWorkItem.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface ThreadPoolWorkItem
+{
+ void execute(ThreadPoolCurrent current);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolWorkQueue.java b/java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolWorkQueue.java
new file mode 100644
index 00000000000..ae838d61cdf
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ThreadPoolWorkQueue.java
@@ -0,0 +1,116 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.util.List;
+
+final class ThreadPoolWorkQueue extends EventHandler
+{
+ ThreadPoolWorkQueue(Instance instance, ThreadPool threadPool, Selector selector)
+ {
+ _threadPool = threadPool;
+ _selector = selector;
+ _destroyed = false;
+ _registered = SocketOperation.Read;
+ }
+
+ @Override
+ protected synchronized void finalize() throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_destroyed);
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ void destroy()
+ {
+ // Called with the thread pool locked
+ assert(!_destroyed);
+ _destroyed = true;
+ _selector.ready(this, SocketOperation.Read, true);
+ }
+
+ void queue(ThreadPoolWorkItem item)
+ {
+ // Called with the thread pool locked
+ assert(item != null);
+ _workItems.add(item);
+ if(_workItems.size() == 1)
+ {
+ _selector.ready(this, SocketOperation.Read, true);
+ }
+ }
+
+ @Override
+ public void message(ThreadPoolCurrent current)
+ {
+ ThreadPoolWorkItem workItem = null;
+ synchronized(_threadPool)
+ {
+ if(!_workItems.isEmpty())
+ {
+ workItem = _workItems.removeFirst();
+ assert(workItem != null);
+ }
+ if(_workItems.isEmpty() && !_destroyed)
+ {
+ _selector.ready(this, SocketOperation.Read, false);
+ }
+ }
+
+ if(workItem != null)
+ {
+ workItem.execute(current);
+ }
+ else
+ {
+ assert(_destroyed);
+ _threadPool.ioCompleted(current);
+ throw new ThreadPool.DestroyedException();
+ }
+ }
+
+ @Override
+ public void finished(ThreadPoolCurrent current, boolean close)
+ {
+ assert(false);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "work queue";
+ }
+
+ @Override
+ public java.nio.channels.SelectableChannel fd()
+ {
+ return null;
+ }
+
+ @Override
+ public void setReadyCallback(ReadyCallback callback)
+ {
+ // Ignore, we don't use the ready callback.
+ }
+
+ private final ThreadPool _threadPool;
+ private boolean _destroyed;
+ private Selector _selector;
+ private java.util.LinkedList<ThreadPoolWorkItem> _workItems = new java.util.LinkedList<ThreadPoolWorkItem>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Time.java b/java-compat/src/Ice/src/main/java/IceInternal/Time.java
new file mode 100644
index 00000000000..e1547f9e552
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Time.java
@@ -0,0 +1,19 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final public class Time
+{
+ static public long
+ currentMonotonicTimeMillis()
+ {
+ return System.nanoTime() / 1000000;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/TraceLevels.java b/java-compat/src/Ice/src/main/java/IceInternal/TraceLevels.java
new file mode 100644
index 00000000000..8273966cdad
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/TraceLevels.java
@@ -0,0 +1,45 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class TraceLevels
+{
+ TraceLevels(Ice.Properties properties)
+ {
+ networkCat = "Network";
+ protocolCat = "Protocol";
+ retryCat = "Retry";
+ locationCat = "Locator";
+ slicingCat = "Slicing";
+ threadPoolCat = "ThreadPool";
+
+ final String keyBase = "Ice.Trace.";
+
+ network = properties.getPropertyAsInt(keyBase + networkCat);
+ protocol = properties.getPropertyAsInt(keyBase + protocolCat);
+ retry = properties.getPropertyAsInt(keyBase + retryCat);
+ location = properties.getPropertyAsInt(keyBase + locationCat);
+ slicing = properties.getPropertyAsInt(keyBase + slicingCat);
+ threadPool = properties.getPropertyAsInt(keyBase + threadPoolCat);
+ }
+
+ final public int network;
+ final public String networkCat;
+ final public int protocol;
+ final public String protocolCat;
+ final public int retry;
+ final public String retryCat;
+ final public int location;
+ final public String locationCat;
+ final public int slicing;
+ final public String threadPoolCat;
+ final public int threadPool;
+ final public String slicingCat;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java b/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java
new file mode 100644
index 00000000000..2ff165c475d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java
@@ -0,0 +1,514 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class TraceUtil
+{
+ public static void
+ traceSend(Ice.OutputStream str, Ice.Logger logger, TraceLevels tl)
+ {
+ if(tl.protocol >= 1)
+ {
+ int p = str.pos();
+ Ice.InputStream is = new Ice.InputStream(str.instance(), str.getEncoding(), str.getBuffer(), false);
+ is.pos(0);
+
+ java.io.StringWriter s = new java.io.StringWriter();
+ byte type = printMessage(s, is);
+
+ logger.trace(tl.protocolCat, "sending " + getMessageTypeAsString(type) + " " + s.toString());
+
+ str.pos(p);
+ }
+ }
+
+ public static void
+ traceRecv(Ice.InputStream str, Ice.Logger logger, TraceLevels tl)
+ {
+ if(tl.protocol >= 1)
+ {
+ int p = str.pos();
+ str.pos(0);
+
+ java.io.StringWriter s = new java.io.StringWriter();
+ byte type = printMessage(s, str);
+
+ logger.trace(tl.protocolCat, "received " + getMessageTypeAsString(type) + " " + s.toString());
+
+ str.pos(p);
+ }
+ }
+
+ public static void
+ trace(String heading, Ice.OutputStream str, Ice.Logger logger, TraceLevels tl)
+ {
+ if(tl.protocol >= 1)
+ {
+ int p = str.pos();
+ Ice.InputStream is = new Ice.InputStream(str.instance(), str.getEncoding(), str.getBuffer(), false);
+ is.pos(0);
+
+ java.io.StringWriter s = new java.io.StringWriter();
+ s.write(heading);
+ printMessage(s, is);
+
+ logger.trace(tl.protocolCat, s.toString());
+ str.pos(p);
+ }
+ }
+
+ public static void
+ trace(String heading, Ice.InputStream str, Ice.Logger logger, TraceLevels tl)
+ {
+ if(tl.protocol >= 1)
+ {
+ int p = str.pos();
+ str.pos(0);
+
+ java.io.StringWriter s = new java.io.StringWriter();
+ s.write(heading);
+ printMessage(s, str);
+
+ logger.trace(tl.protocolCat, s.toString());
+ str.pos(p);
+ }
+ }
+
+ private static java.util.Set<String> slicingIds = new java.util.HashSet<String>();
+
+ public synchronized static void
+ traceSlicing(String kind, String typeId, String slicingCat, Ice.Logger logger)
+ {
+ if(slicingIds.add(typeId))
+ {
+ java.io.StringWriter s = new java.io.StringWriter();
+ s.write("unknown " + kind + " type `" + typeId + "'");
+ logger.trace(slicingCat, s.toString());
+ }
+ }
+
+ public static void
+ dumpStream(Ice.InputStream stream)
+ {
+ int pos = stream.pos();
+ stream.pos(0);
+
+ byte[] data = stream.readBlob(stream.size());
+ dumpOctets(data);
+
+ stream.pos(pos);
+ }
+
+ public static void
+ dumpOctets(byte[] data)
+ {
+ final int inc = 8;
+
+ for(int i = 0; i < data.length; i += inc)
+ {
+ for(int j = i; j - i < inc; j++)
+ {
+ if(j < data.length)
+ {
+ int n = data[j];
+ if(n < 0)
+ {
+ n += 256;
+ }
+ String s;
+ if(n < 10)
+ {
+ s = " " + n;
+ }
+ else if(n < 100)
+ {
+ s = " " + n;
+ }
+ else
+ {
+ s = "" + n;
+ }
+ System.out.print(s + " ");
+ }
+ else
+ {
+ System.out.print(" ");
+ }
+ }
+
+ System.out.print('"');
+
+ for(int j = i; j < data.length && j - i < inc; j++)
+ {
+ if(data[j] >= (byte)32 && data[j] < (byte)127)
+ {
+ System.out.print((char)data[j]);
+ }
+ else
+ {
+ System.out.print('.');
+ }
+ }
+
+ System.out.println('"');
+ }
+ }
+
+ private static void
+ printIdentityFacetOperation(java.io.Writer out, Ice.InputStream stream)
+ {
+ try
+ {
+ Ice.Identity identity = new Ice.Identity();
+ identity.__read(stream);
+ out.write("\nidentity = " + Ice.Util.identityToString(identity));
+
+ String[] facet = stream.readStringSeq();
+ out.write("\nfacet = ");
+ if(facet.length > 0)
+ {
+ out.write(IceUtilInternal.StringUtil.escapeString(facet[0], ""));
+ }
+
+ String operation = stream.readString();
+ out.write("\noperation = " + operation);
+ }
+ catch(java.io.IOException ex)
+ {
+ assert(false);
+ }
+ }
+
+ private static void
+ printRequest(java.io.StringWriter s, Ice.InputStream str)
+ {
+ int requestId = str.readInt();
+ s.write("\nrequest id = " + requestId);
+ if(requestId == 0)
+ {
+ s.write(" (oneway)");
+ }
+
+ printRequestHeader(s, str);
+ }
+
+ private static void
+ printBatchRequest(java.io.StringWriter s, Ice.InputStream str)
+ {
+ int batchRequestNum = str.readInt();
+ s.write("\nnumber of requests = " + batchRequestNum);
+
+ for(int i = 0; i < batchRequestNum; ++i)
+ {
+ s.write("\nrequest #" + i + ':');
+ printRequestHeader(s, str);
+ }
+ }
+
+ private static void
+ printReply(java.io.StringWriter s, Ice.InputStream str)
+ {
+ int requestId = str.readInt();
+ s.write("\nrequest id = " + requestId);
+
+ byte replyStatus = str.readByte();
+ s.write("\nreply status = " + (int)replyStatus + ' ');
+
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyOK:
+ {
+ s.write("(ok)");
+ break;
+ }
+
+ case ReplyStatus.replyUserException:
+ {
+ s.write("(user exception)");
+ break;
+ }
+
+ case ReplyStatus.replyObjectNotExist:
+ case ReplyStatus.replyFacetNotExist:
+ case ReplyStatus.replyOperationNotExist:
+ {
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyObjectNotExist:
+ {
+ s.write("(object not exist)");
+ break;
+ }
+
+ case ReplyStatus.replyFacetNotExist:
+ {
+ s.write("(facet not exist)");
+ break;
+ }
+
+ case ReplyStatus.replyOperationNotExist:
+ {
+ s.write("(operation not exist)");
+ break;
+ }
+
+ default:
+ {
+ assert(false);
+ break;
+ }
+ }
+
+ printIdentityFacetOperation(s, str);
+ break;
+ }
+
+ case ReplyStatus.replyUnknownException:
+ case ReplyStatus.replyUnknownLocalException:
+ case ReplyStatus.replyUnknownUserException:
+ {
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyUnknownException:
+ {
+ s.write("(unknown exception)");
+ break;
+ }
+
+ case ReplyStatus.replyUnknownLocalException:
+ {
+ s.write("(unknown local exception)");
+ break;
+ }
+
+ case ReplyStatus.replyUnknownUserException:
+ {
+ s.write("(unknown user exception)");
+ break;
+ }
+
+ default:
+ {
+ assert(false);
+ break;
+ }
+ }
+
+ String unknown = str.readString();
+ s.write("\nunknown = " + unknown);
+ break;
+ }
+
+ default:
+ {
+ s.write("(unknown)");
+ break;
+ }
+ }
+
+ if(replyStatus == ReplyStatus.replyOK || replyStatus == ReplyStatus.replyUserException)
+ {
+ Ice.EncodingVersion v = str.skipEncapsulation();
+ if(!v.equals(Ice.Util.Encoding_1_0))
+ {
+ s.write("\nencoding = ");
+ s.write(Ice.Util.encodingVersionToString(v));
+ }
+ }
+ }
+
+ private static void
+ printRequestHeader(java.io.Writer out, Ice.InputStream stream)
+ {
+ printIdentityFacetOperation(out, stream);
+
+ try
+ {
+ byte mode = stream.readByte();
+ out.write("\nmode = " + (int) mode + ' ');
+ switch(Ice.OperationMode.values()[mode])
+ {
+ case Normal:
+ {
+ out.write("(normal)");
+ break;
+ }
+
+ case Nonmutating:
+ {
+ out.write("(nonmutating)");
+ break;
+ }
+
+ case Idempotent:
+ {
+ out.write("(idempotent)");
+ break;
+ }
+
+ default:
+ {
+ out.write("(unknown)");
+ break;
+ }
+ }
+
+ int sz = stream.readSize();
+ out.write("\ncontext = ");
+ while(sz-- > 0)
+ {
+ String key = stream.readString();
+ String value = stream.readString();
+ out.write(key + '/' + value);
+ if(sz > 0)
+ {
+ out.write(", ");
+ }
+ }
+
+ Ice.EncodingVersion v = stream.skipEncapsulation();
+ if(!v.equals(Ice.Util.Encoding_1_0))
+ {
+ out.write("\nencoding = ");
+ out.write(Ice.Util.encodingVersionToString(v));
+ }
+ }
+ catch(java.io.IOException ex)
+ {
+ assert(false);
+ }
+ }
+
+ private static byte
+ printHeader(java.io.Writer out, Ice.InputStream stream)
+ {
+ stream.readByte(); // Don't bother printing the magic number
+ stream.readByte();
+ stream.readByte();
+ stream.readByte();
+
+// byte pMajor = stream.readByte();
+// byte pMinor = stream.readByte();
+// out.write("\nprotocol version = " + (int)pMajor + "." + (int)pMinor);
+ stream.readByte(); // major
+ stream.readByte(); // minor
+
+// byte eMajor = stream.readByte();
+// byte eMinor = stream.readByte();
+// out.write("\nencoding version = " + (int)eMajor + "." + (int)eMinor);
+ stream.readByte(); // major
+ stream.readByte(); // minor
+
+ byte type = stream.readByte();
+
+ try
+ {
+ out.write("\nmessage type = " + (int)type + " (" + getMessageTypeAsString(type) + ')');
+ byte compress = stream.readByte();
+ out.write("\ncompression status = " + (int)compress + ' ');
+ switch(compress)
+ {
+ case (byte)0:
+ {
+ out.write("(not compressed; do not compress response, if any)");
+ break;
+ }
+
+ case (byte)1:
+ {
+ out.write("(not compressed; compress response, if any)");
+ break;
+ }
+
+ case (byte)2:
+ {
+ out.write("(compressed; compress response, if any)");
+ break;
+ }
+
+ default:
+ {
+ out.write("(unknown)");
+ break;
+ }
+ }
+
+ int size = stream.readInt();
+ out.write("\nmessage size = " + size);
+ return type;
+ }
+ catch(java.io.IOException ex)
+ {
+ assert(false);
+ return 0;
+ }
+ }
+
+ static private byte
+ printMessage(java.io.StringWriter s, Ice.InputStream str)
+ {
+ byte type = printHeader(s, str);
+
+ switch(type)
+ {
+ case Protocol.closeConnectionMsg:
+ case Protocol.validateConnectionMsg:
+ {
+ // We're done.
+ break;
+ }
+
+ case Protocol.requestMsg:
+ {
+ printRequest(s, str);
+ break;
+ }
+
+ case Protocol.requestBatchMsg:
+ {
+ printBatchRequest(s, str);
+ break;
+ }
+
+ case Protocol.replyMsg:
+ {
+ printReply(s, str);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ return type;
+ }
+
+ static private String
+ getMessageTypeAsString(byte 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";
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Transceiver.java b/java-compat/src/Ice/src/main/java/IceInternal/Transceiver.java
new file mode 100644
index 00000000000..c62c00984b6
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Transceiver.java
@@ -0,0 +1,32 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface Transceiver
+{
+ java.nio.channels.SelectableChannel fd();
+ void setReadyCallback(ReadyCallback callback);
+
+ int initialize(Buffer readBuffer, Buffer writeBuffer);
+ int closing(boolean initiator, Ice.LocalException ex);
+ void close();
+
+ EndpointI bind();
+ int write(Buffer buf);
+ int read(Buffer buf);
+
+ String protocol();
+ @Override
+ String toString();
+ String toDetailedString();
+ Ice.ConnectionInfo getInfo();
+ void checkSendSize(Buffer buf);
+ void setBufferSize(int rcvSize, int sndSize);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/TwowayCallback.java b/java-compat/src/Ice/src/main/java/IceInternal/TwowayCallback.java
new file mode 100644
index 00000000000..713f965d848
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/TwowayCallback.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public abstract class TwowayCallback extends CallbackBase implements Ice.TwowayCallback
+{
+ public void sent(boolean sentSynchronously)
+ {
+ }
+
+ @Override
+ public void exception(Ice.SystemException __ex)
+ {
+ exception(new Ice.UnknownException(__ex));
+ }
+
+ @Override
+ public final void __sent(Ice.AsyncResult __result)
+ {
+ sent(__result.sentSynchronously());
+ }
+
+ @Override
+ public final boolean __hasSentCallback()
+ {
+ return true;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/UdpConnector.java b/java-compat/src/Ice/src/main/java/IceInternal/UdpConnector.java
new file mode 100644
index 00000000000..ad91ec7fba2
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/UdpConnector.java
@@ -0,0 +1,113 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class UdpConnector implements Connector
+{
+ @Override
+ public Transceiver connect()
+ {
+ return new UdpTransceiver(_instance, _addr, _sourceAddr, _mcastInterface, _mcastTtl);
+ }
+
+ public java.nio.channels.SelectableChannel fd()
+ {
+ assert(false); // Shouldn't be called, startConnect always completes immediately.
+ return null;
+ }
+
+ @Override
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ @Override
+ public String toString()
+ {
+ return Network.addrToString(_addr);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return _hashCode;
+ }
+
+ //
+ // Only for use by UdpEndpointI
+ //
+ UdpConnector(ProtocolInstance instance, java.net.InetSocketAddress addr, java.net.InetSocketAddress sourceAddr,
+ String mcastInterface, int mcastTtl, String connectionId)
+ {
+ _instance = instance;
+ _addr = addr;
+ _sourceAddr = sourceAddr;
+ _mcastInterface = mcastInterface;
+ _mcastTtl = mcastTtl;
+ _connectionId = connectionId;
+
+ _hashCode = 5381;
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _addr.getAddress().getHostAddress());
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _addr.getPort());
+ if(_sourceAddr != null)
+ {
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _sourceAddr.getAddress().getHostAddress());
+ }
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _mcastInterface);
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _mcastTtl);
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _connectionId);
+ }
+
+ @Override
+ public boolean equals(java.lang.Object obj)
+ {
+ if(!(obj instanceof UdpConnector))
+ {
+ return false;
+ }
+
+ if(this == obj)
+ {
+ return true;
+ }
+
+ UdpConnector p = (UdpConnector)obj;
+ if(!_connectionId.equals(p._connectionId))
+ {
+ return false;
+ }
+
+ if(_mcastTtl != p._mcastTtl)
+ {
+ return false;
+ }
+
+ if(_mcastInterface.compareTo(p._mcastInterface) != 0)
+ {
+ return false;
+ }
+
+ if(Network.compareAddress(_sourceAddr, p._sourceAddr) != 0)
+ {
+ return false;
+ }
+
+ return Network.compareAddress(_addr, p._addr) == 0;
+ }
+
+ private ProtocolInstance _instance;
+ private java.net.InetSocketAddress _addr;
+ private java.net.InetSocketAddress _sourceAddr;
+ private String _mcastInterface;
+ private int _mcastTtl;
+ private String _connectionId;
+ private int _hashCode;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/UdpEndpointFactory.java b/java-compat/src/Ice/src/main/java/IceInternal/UdpEndpointFactory.java
new file mode 100644
index 00000000000..6683b57dcb9
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/UdpEndpointFactory.java
@@ -0,0 +1,58 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class UdpEndpointFactory implements EndpointFactory
+{
+ UdpEndpointFactory(ProtocolInstance instance)
+ {
+ _instance = instance;
+ }
+
+ @Override
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public EndpointI create(java.util.ArrayList<String> args, boolean oaEndpoint)
+ {
+ IPEndpointI endpt = new UdpEndpointI(_instance);
+ endpt.initWithOptions(args, oaEndpoint);
+ return endpt;
+ }
+
+ @Override
+ public EndpointI read(Ice.InputStream s)
+ {
+ return new UdpEndpointI(_instance, s);
+ }
+
+ @Override
+ public void destroy()
+ {
+ _instance = null;
+ }
+
+ @Override
+ public EndpointFactory clone(ProtocolInstance instance, EndpointFactory delegate)
+ {
+ return new UdpEndpointFactory(instance);
+ }
+
+ private ProtocolInstance _instance;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/UdpEndpointI.java b/java-compat/src/Ice/src/main/java/IceInternal/UdpEndpointI.java
new file mode 100644
index 00000000000..8c1d0bc837d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/UdpEndpointI.java
@@ -0,0 +1,395 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class UdpEndpointI extends IPEndpointI
+{
+ public UdpEndpointI(ProtocolInstance instance, String ho, int po, java.net.InetSocketAddress sourceAddr,
+ String mcastInterface, int mttl, boolean conn, String conId, boolean co)
+ {
+ super(instance, ho, po, sourceAddr, conId);
+ _mcastInterface = mcastInterface;
+ _mcastTtl = mttl;
+ _connect = conn;
+ _compress = co;
+ }
+
+ public UdpEndpointI(ProtocolInstance instance)
+ {
+ super(instance);
+ _connect = false;
+ _compress = false;
+ }
+
+ public UdpEndpointI(ProtocolInstance instance, Ice.InputStream s)
+ {
+ super(instance, s);
+ if(s.getEncoding().equals(Ice.Util.Encoding_1_0))
+ {
+ s.readByte();
+ s.readByte();
+ s.readByte();
+ s.readByte();
+ }
+ // Not transmitted.
+ //_connect = s.readBool();
+ _connect = false;
+ _compress = s.readBool();
+ }
+
+ //
+ // Return the endpoint information.
+ //
+ @Override
+ public Ice.EndpointInfo getInfo()
+ {
+ Ice.UDPEndpointInfo info = new Ice.UDPEndpointInfo()
+ {
+ @Override
+ public short type()
+ {
+ return UdpEndpointI.this.type();
+ }
+
+ @Override
+ public boolean datagram()
+ {
+ return UdpEndpointI.this.datagram();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return UdpEndpointI.this.secure();
+ }
+ };
+ fillEndpointInfo(info);
+ return info;
+ }
+
+ //
+ // Return the timeout for the endpoint in milliseconds. 0 means
+ // non-blocking, -1 means no timeout.
+ //
+ @Override
+ public int timeout()
+ {
+ 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.
+ //
+ @Override
+ public EndpointI timeout(int timeout)
+ {
+ return this;
+ }
+
+ //
+ // Return true if the endpoints support bzip2 compress, or false
+ // otherwise.
+ //
+ @Override
+ public boolean compress()
+ {
+ return _compress;
+ }
+
+ //
+ // Return a new endpoint with a different compression value,
+ // provided that compression is supported by the
+ // endpoint. Otherwise the same endpoint is returned.
+ //
+ @Override
+ public EndpointI compress(boolean compress)
+ {
+ if(compress == _compress)
+ {
+ return this;
+ }
+ else
+ {
+ return new UdpEndpointI(_instance, _host, _port, _sourceAddr, _mcastInterface, _mcastTtl, _connect,
+ _connectionId, compress);
+ }
+ }
+
+ //
+ // Return true if the endpoint is datagram-based.
+ //
+ @Override
+ public boolean datagram()
+ {
+ return true;
+ }
+
+ //
+ // Return a server side transceiver for this endpoint, or null if a
+ // transceiver can only be created by an acceptor.
+ //
+ @Override
+ public Transceiver transceiver()
+ {
+ return new UdpTransceiver(this, _instance, _host, _port, _mcastInterface, _connect);
+ }
+
+ //
+ // Return an acceptor for this endpoint, or null if no acceptors
+ // is available.
+ //
+ @Override
+ public Acceptor acceptor(String adapterName)
+ {
+ return null;
+ }
+
+ public UdpEndpointI endpoint(UdpTransceiver transceiver)
+ {
+ return new UdpEndpointI(_instance, _host, transceiver.effectivePort(), _sourceAddr, _mcastInterface,_mcastTtl,
+ _connect, _connectionId, _compress);
+ }
+
+ //
+ // Convert the endpoint to its string form
+ //
+ @Override
+ public String options()
+ {
+ //
+ // 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.
+ //
+ String s = super.options();
+
+ if(_mcastInterface.length() != 0)
+ {
+ s += " --interface " + _mcastInterface;
+ }
+
+ if(_mcastTtl != -1)
+ {
+ s += " --ttl " + _mcastTtl;
+ }
+
+ if(_connect)
+ {
+ s += " -c";
+ }
+
+ if(_compress)
+ {
+ s += " -z";
+ }
+
+ return s;
+ }
+
+ @Override
+ public int compareTo(EndpointI obj) // From java.lang.Comparable
+ {
+ if(!(obj instanceof UdpEndpointI))
+ {
+ return type() < obj.type() ? -1 : 1;
+ }
+
+ UdpEndpointI p = (UdpEndpointI)obj;
+ if(this == p)
+ {
+ return 0;
+ }
+
+ if(!_connect && p._connect)
+ {
+ return -1;
+ }
+ else if(!p._connect && _connect)
+ {
+ return 1;
+ }
+
+ if(!_compress && p._compress)
+ {
+ return -1;
+ }
+ else if(!p._compress && _compress)
+ {
+ return 1;
+ }
+
+ if(_mcastTtl < p._mcastTtl)
+ {
+ return -1;
+ }
+ else if(p._mcastTtl < _mcastTtl)
+ {
+ return 1;
+ }
+
+ int rc = _mcastInterface.compareTo(p._mcastInterface);
+ if(rc != 0)
+ {
+ return rc;
+ }
+
+ return super.compareTo(obj);
+ }
+
+ //
+ // Marshal the endpoint
+ //
+ @Override
+ public void streamWriteImpl(Ice.OutputStream s)
+ {
+ super.streamWriteImpl(s);
+ if(s.getEncoding().equals(Ice.Util.Encoding_1_0))
+ {
+ Ice.Util.Protocol_1_0.__write(s);
+ Ice.Util.Encoding_1_0.__write(s);
+ }
+ // Not transmitted.
+ //s.writeBool(_connect);
+ s.writeBool(_compress);
+ }
+
+ @Override
+ public int hashInit(int h)
+ {
+ h = super.hashInit(h);
+ h = IceInternal.HashUtil.hashAdd(h, _mcastInterface);
+ h = IceInternal.HashUtil.hashAdd(h, _mcastTtl);
+ h = IceInternal.HashUtil.hashAdd(h, _connect);
+ h = IceInternal.HashUtil.hashAdd(h, _compress);
+ return h;
+ }
+
+ @Override
+ public void fillEndpointInfo(Ice.IPEndpointInfo info)
+ {
+ super.fillEndpointInfo(info);
+ if(info instanceof Ice.UDPEndpointInfo)
+ {
+ Ice.UDPEndpointInfo udpInfo = (Ice.UDPEndpointInfo)info;
+ udpInfo.mcastInterface = _mcastInterface;
+ udpInfo.mcastTtl = _mcastTtl;
+ }
+ }
+
+ @Override
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ if(super.checkOption(option, argument, endpoint))
+ {
+ return true;
+ }
+
+ if(option.equals("-c"))
+ {
+ if(argument != null)
+ {
+ throw new Ice.EndpointParseException("unexpected argument `" + argument +
+ "' provided for -c option in " + endpoint);
+ }
+
+ _connect = true;
+ }
+ else if(option.equals("-z"))
+ {
+ if(argument != null)
+ {
+ throw new Ice.EndpointParseException("unexpected argument `" + argument +
+ "' provided for -z option in " + endpoint);
+ }
+
+ _compress = true;
+ }
+ else if(option.equals("-v") || option.equals("-e"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for " + option + " option in endpoint " +
+ endpoint);
+ }
+
+ try
+ {
+ Ice.EncodingVersion v = Ice.Util.stringToEncodingVersion(argument);
+ if(v.major != 1 || v.minor != 0)
+ {
+ _instance.logger().warning("deprecated udp endpoint option: " + option);
+ }
+ }
+ catch(Ice.VersionParseException e)
+ {
+ throw new Ice.EndpointParseException("invalid version `" + argument + "' in endpoint " +
+ endpoint + ":\n" + e.str);
+ }
+ }
+ else if(option.equals("--ttl"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for --ttl option in endpoint " + endpoint);
+ }
+
+ try
+ {
+ _mcastTtl = Integer.parseInt(argument);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid TTL value `" + argument + "' in endpoint " + endpoint);
+ }
+
+ if(_mcastTtl < 0)
+ {
+ throw new Ice.EndpointParseException("TTL value `" + argument + "' out of range in endpoint " +
+ endpoint);
+ }
+ }
+ else if(option.equals("--interface"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for --interface option in endpoint " +
+ endpoint);
+ }
+ _mcastInterface = argument;
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected Connector createConnector(java.net.InetSocketAddress addr, NetworkProxy proxy)
+ {
+ return new UdpConnector(_instance, addr, _sourceAddr, _mcastInterface, _mcastTtl, _connectionId);
+ }
+
+ @Override
+ protected IPEndpointI createEndpoint(String host, int port, String connectionId)
+ {
+ return new UdpEndpointI(_instance, host, port, _sourceAddr, _mcastInterface,_mcastTtl, _connect,
+ connectionId, _compress);
+ }
+
+ private String _mcastInterface = "";
+ private int _mcastTtl = -1;
+ private boolean _connect;
+ private boolean _compress;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java b/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java
new file mode 100644
index 00000000000..1f4899f7bce
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java
@@ -0,0 +1,653 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class UdpTransceiver implements Transceiver
+{
+ @Override
+ public java.nio.channels.SelectableChannel fd()
+ {
+ assert(_fd != null);
+ return _fd;
+ }
+
+ @Override
+ public void setReadyCallback(ReadyCallback callback)
+ {
+ }
+
+ @Override
+ public int initialize(Buffer readBuffer, Buffer writeBuffer)
+ {
+ //
+ // Nothing to do.
+ //
+ return SocketOperation.None;
+ }
+
+ @Override
+ public int closing(boolean initiator, Ice.LocalException ex)
+ {
+ //
+ // Nothing to do.
+ //
+ return SocketOperation.None;
+ }
+
+ @Override
+ public void close()
+ {
+ assert(_fd != null);
+
+ try
+ {
+ _fd.close();
+ }
+ catch(java.io.IOException ex)
+ {
+ }
+ _fd = null;
+ }
+
+ @Override
+ public EndpointI bind()
+ {
+ if(_addr.getAddress().isMulticastAddress())
+ {
+ Network.setReuseAddress(_fd, true);
+ _mcastAddr = _addr;
+ if(System.getProperty("os.name").startsWith("Windows") ||
+ System.getProperty("java.vm.name").startsWith("OpenJDK"))
+ {
+ //
+ // Windows does not allow binding to the mcast address itself
+ // so we bind to INADDR_ANY (0.0.0.0) instead. As a result,
+ // bi-directional connection won't work because the source
+ // address won't be the multicast address and the client will
+ // therefore reject the datagram.
+ //
+ int protocol =
+ _mcastAddr.getAddress().getAddress().length == 4 ? Network.EnableIPv4 : Network.EnableIPv6;
+ _addr = Network.getAddressForServer("", _port, protocol, _instance.preferIPv6());
+ }
+ _addr = Network.doBind(_fd, _addr);
+ configureMulticast(_mcastAddr, _mcastInterface, -1);
+
+ if(_port == 0)
+ {
+ _mcastAddr = new java.net.InetSocketAddress(_mcastAddr.getAddress(), _addr.getPort());
+ }
+ }
+ else
+ {
+ if(!System.getProperty("os.name").startsWith("Windows"))
+ {
+ //
+ // Enable SO_REUSEADDR on Unix platforms to allow
+ // re-using the socket even if it's in the TIME_WAIT
+ // state. On Windows, this doesn't appear to be
+ // necessary and enabling SO_REUSEADDR would actually
+ // not be a good thing since it allows a second
+ // process to bind to an address even it's already
+ // bound by another process.
+ //
+ // TODO: using SO_EXCLUSIVEADDRUSE on Windows would
+ // probably be better but it's only supported by recent
+ // Windows versions (XP SP2, Windows Server 2003).
+ //
+ Network.setReuseAddress(_fd, true);
+ }
+ _addr = Network.doBind(_fd, _addr);
+ }
+
+ _bound = true;
+ _endpoint = _endpoint.endpoint(this);
+ return _endpoint;
+ }
+
+ @Override
+ public int write(Buffer buf)
+ {
+ if(!buf.b.hasRemaining())
+ {
+ return SocketOperation.None;
+ }
+
+ assert(buf.b.position() == 0);
+ assert(_fd != null && _state >= StateConnected);
+
+ // The caller is supposed to check the send size before by calling checkSendSize
+ assert(java.lang.Math.min(_maxPacketSize, _sndSize - _udpOverhead) >= buf.size());
+
+ int ret = 0;
+ while(true)
+ {
+ try
+ {
+ if(_state == StateConnected)
+ {
+ ret = _fd.write(buf.b);
+ }
+ else
+ {
+ if(_peerAddr == null)
+ {
+ throw new Ice.SocketException(); // No peer has sent a datagram yet.
+ }
+ ret = _fd.send(buf.b, _peerAddr);
+ }
+ break;
+ }
+ catch(java.nio.channels.AsynchronousCloseException ex)
+ {
+ throw new Ice.ConnectionLostException(ex);
+ }
+ catch(java.net.PortUnreachableException ex)
+ {
+ throw new Ice.ConnectionLostException(ex);
+ }
+ catch(java.io.InterruptedIOException ex)
+ {
+ continue;
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ if(ret == 0)
+ {
+ return SocketOperation.Write;
+ }
+
+ assert(ret == buf.b.limit());
+ buf.b.position(buf.b.limit());
+ return SocketOperation.None;
+ }
+
+ @Override
+ public int read(Buffer buf)
+ {
+ if(!buf.b.hasRemaining())
+ {
+ return SocketOperation.None;
+ }
+
+ assert(buf.b.position() == 0);
+
+ final int packetSize = java.lang.Math.min(_maxPacketSize, _rcvSize - _udpOverhead);
+ buf.resize(packetSize, true);
+ buf.b.position(0);
+
+ int ret = 0;
+ while(true)
+ {
+ try
+ {
+ java.net.SocketAddress peerAddr = _fd.receive(buf.b);
+ if(peerAddr == null || buf.b.position() == 0)
+ {
+ return SocketOperation.Read;
+ }
+
+ _peerAddr = (java.net.InetSocketAddress)peerAddr;
+ ret = buf.b.position();
+ break;
+ }
+ catch(java.nio.channels.AsynchronousCloseException ex)
+ {
+ throw new Ice.ConnectionLostException(ex);
+ }
+ catch(java.net.PortUnreachableException ex)
+ {
+ throw new Ice.ConnectionLostException(ex);
+ }
+ catch(java.io.InterruptedIOException ex)
+ {
+ continue;
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.ConnectionLostException(ex);
+ }
+ }
+
+ if(_state == StateNeedConnect)
+ {
+ //
+ // If we must connect, we connect to the first peer that sends us a packet.
+ //
+ Network.doConnect(_fd, _peerAddr, null);
+ _state = StateConnected;
+
+ if(_instance.traceLevel() >= 1)
+ {
+ String s = "connected " + _instance.protocol() + " socket\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
+ }
+ }
+
+ buf.resize(ret, true);
+ buf.b.position(ret);
+
+ return SocketOperation.None;
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public String toString()
+ {
+ if(_fd == null)
+ {
+ return "<closed>";
+ }
+
+ String s;
+ if(_incoming && !_bound)
+ {
+ s = "local address = " + Network.addrToString(_addr);
+ }
+ else if(_state == StateNotConnected)
+ {
+ java.net.DatagramSocket socket = _fd.socket();
+ s = "local address = " + Network.addrToString((java.net.InetSocketAddress)socket.getLocalSocketAddress());
+ if(_peerAddr != null)
+ {
+ s += "\nremote address = " + Network.addrToString(_peerAddr);
+ }
+ }
+ else
+ {
+ s = Network.fdToString(_fd);
+ }
+
+ if(_mcastAddr != null)
+ {
+ s += "\nmulticast address = " + Network.addrToString(_mcastAddr);
+ }
+ return s;
+ }
+
+ @Override
+ public String toDetailedString()
+ {
+ StringBuilder s = new StringBuilder(toString());
+ java.util.List<String> intfs =
+ Network.getHostsForEndpointExpand(_addr.getAddress().getHostAddress(), _instance.protocolSupport(), true);
+ if(!intfs.isEmpty())
+ {
+ s.append("\nlocal interfaces = ");
+ s.append(IceUtilInternal.StringUtil.joinString(intfs, ", "));
+ }
+ return s.toString();
+ }
+
+ @Override
+ public Ice.ConnectionInfo getInfo()
+ {
+ Ice.UDPConnectionInfo info = new Ice.UDPConnectionInfo();
+ if(_fd != null)
+ {
+ java.net.DatagramSocket socket = _fd.socket();
+ info.localAddress = socket.getLocalAddress().getHostAddress();
+ info.localPort = socket.getLocalPort();
+ if(_state == StateNotConnected)
+ {
+ if(_peerAddr != null)
+ {
+ info.remoteAddress = _peerAddr.getAddress().getHostAddress();
+ info.remotePort = _peerAddr.getPort();
+ }
+ }
+ else
+ {
+ if(socket.getInetAddress() != null)
+ {
+ info.remoteAddress = socket.getInetAddress().getHostAddress();
+ info.remotePort = socket.getPort();
+ }
+ }
+ if(!socket.isClosed())
+ {
+ info.rcvSize = Network.getRecvBufferSize(_fd);
+ info.sndSize = Network.getSendBufferSize(_fd);
+ }
+ }
+ if(_mcastAddr != null)
+ {
+ info.mcastAddress = _mcastAddr.getAddress().getHostAddress();
+ info.mcastPort = _mcastAddr.getPort();
+ }
+ return info;
+ }
+
+ @Override
+ public void checkSendSize(Buffer buf)
+ {
+ //
+ // The maximum packetSize is either the maximum allowable UDP packet size, or
+ // the UDP send buffer size (which ever is smaller).
+ //
+ final int packetSize = java.lang.Math.min(_maxPacketSize, _sndSize - _udpOverhead);
+ if(packetSize < buf.size())
+ {
+ throw new Ice.DatagramLimitException();
+ }
+ }
+
+ @Override
+ public void setBufferSize(int rcvSize, int sndSize)
+ {
+ setBufSize(rcvSize, sndSize);
+ }
+
+ public final int effectivePort()
+ {
+ return _addr.getPort();
+ }
+
+ //
+ // Only for use by UdpEndpoint
+ //
+ UdpTransceiver(ProtocolInstance instance, java.net.InetSocketAddress addr, java.net.InetSocketAddress sourceAddr,
+ String mcastInterface, int mcastTtl)
+ {
+ _instance = instance;
+ _state = StateNeedConnect;
+ _addr = addr;
+
+ try
+ {
+ _fd = Network.createUdpSocket(_addr);
+ setBufSize(-1, -1);
+ Network.setBlock(_fd, false);
+ //
+ // NOTE: setting the multicast interface before performing the
+ // connect is important for some OS such as OS X.
+ //
+ if(_addr.getAddress().isMulticastAddress())
+ {
+ configureMulticast(null, mcastInterface, mcastTtl);
+ }
+ Network.doConnect(_fd, _addr, sourceAddr);
+ _state = StateConnected; // We're connected now
+ }
+ catch(Ice.LocalException ex)
+ {
+ _fd = null;
+ throw ex;
+ }
+ }
+
+ //
+ // Only for use by UdpEndpoint
+ //
+ UdpTransceiver(UdpEndpointI endpoint, ProtocolInstance instance, String host, int port, String mcastInterface,
+ boolean connect)
+ {
+ _endpoint = endpoint;
+ _instance = instance;
+ _state = connect ? StateNeedConnect : StateNotConnected;
+ _mcastInterface = mcastInterface;
+ _incoming = true;
+ _port = port;
+
+ try
+ {
+ _addr = Network.getAddressForServer(host, port, instance.protocolSupport(), instance.preferIPv6());
+ _fd = Network.createUdpSocket(_addr);
+ setBufSize(-1, -1);
+ Network.setBlock(_fd, false);
+ }
+ catch(Ice.LocalException ex)
+ {
+ _fd = null;
+ throw ex;
+ }
+ }
+
+ private synchronized void setBufSize(int rcvSize, int sndSize)
+ {
+ assert(_fd != null);
+
+ for(int i = 0; i < 2; ++i)
+ {
+ boolean isSnd;
+ String direction;
+ String prop;
+ int dfltSize;
+ int sizeRequested;
+ if(i == 0)
+ {
+ isSnd = false;
+ direction = "receive";
+ prop = "Ice.UDP.RcvSize";
+ dfltSize = Network.getRecvBufferSize(_fd);
+ sizeRequested = rcvSize;
+ _rcvSize = dfltSize;
+ }
+ else
+ {
+ isSnd = true;
+ direction = "send";
+ prop = "Ice.UDP.SndSize";
+ dfltSize = Network.getSendBufferSize(_fd);
+ sizeRequested = sndSize;
+ _sndSize = dfltSize;
+ }
+
+ //
+ // Get property for buffer size if size not passed in.
+ //
+ if(sizeRequested == -1)
+ {
+ sizeRequested = _instance.properties().getPropertyAsIntWithDefault(prop, dfltSize);
+ }
+ //
+ // Check for sanity.
+ //
+ if(sizeRequested < (_udpOverhead + IceInternal.Protocol.headerSize))
+ {
+ _instance.logger().warning("Invalid " + prop + " value of " + sizeRequested + " adjusted to " +
+ dfltSize);
+ sizeRequested = dfltSize;
+ }
+
+ if(sizeRequested != dfltSize)
+ {
+ //
+ // Try to set the buffer size. The kernel will silently adjust
+ // the size to an acceptable value. Then read the size back to
+ // get the size that was actually set.
+ //
+ int sizeSet;
+ if(i == 0)
+ {
+ Network.setRecvBufferSize(_fd, sizeRequested);
+ _rcvSize = Network.getRecvBufferSize(_fd);
+ sizeSet = _rcvSize;
+ }
+ else
+ {
+ Network.setSendBufferSize(_fd, sizeRequested);
+ _sndSize = Network.getSendBufferSize(_fd);
+ sizeSet = _sndSize;
+ }
+
+ //
+ // Warn if the size that was set is less than the requested size
+ // and we have not already warned
+ //
+ if(sizeSet < sizeRequested)
+ {
+ BufSizeWarnInfo winfo = _instance.getBufSizeWarn(Ice.UDPEndpointType.value);
+ if((isSnd && (!winfo.sndWarn || winfo.sndSize != sizeRequested)) ||
+ (!isSnd && (!winfo.rcvWarn || winfo.rcvSize != sizeRequested)))
+ {
+ _instance.logger().warning("UDP " + direction + " buffer size: requested size of "
+ + sizeRequested + " adjusted to " + sizeSet);
+
+ if(isSnd)
+ {
+ _instance.setSndBufSizeWarn(Ice.UDPEndpointType.value, sizeRequested);
+ }
+ else
+ {
+ _instance.setRcvBufSizeWarn(Ice.UDPEndpointType.value, sizeRequested);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void configureMulticast(java.net.InetSocketAddress group, String interfaceAddr, int ttl)
+ {
+ try
+ {
+ java.net.NetworkInterface intf = null;
+
+ if(interfaceAddr.length() != 0)
+ {
+ intf = java.net.NetworkInterface.getByName(interfaceAddr);
+ if(intf == null)
+ {
+ try
+ {
+ intf = java.net.NetworkInterface.getByInetAddress(
+ java.net.InetAddress.getByName(interfaceAddr));
+ }
+ catch(Exception ex)
+ {
+ }
+ }
+ }
+
+ if(group != null)
+ {
+ //
+ // Join multicast group.
+ //
+ if(intf != null)
+ {
+ _fd.join(group.getAddress(), intf);
+ }
+ else
+ {
+ boolean join = false;
+ //
+ // If the user doesn't specify an interface, we join to the multicast group with every
+ // interface that supports multicast and has a configured address with the same protocol
+ // as the group address protocol.
+ //
+ int protocol = group.getAddress().getAddress().length == 4 ? Network.EnableIPv4 :
+ Network.EnableIPv6;
+
+ java.util.List<java.net.NetworkInterface> interfaces =
+ java.util.Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
+ for(java.net.NetworkInterface iface : interfaces)
+ {
+ boolean hasProtocolAddress = false;
+ java.util.List<java.net.InetAddress> addresses =
+ java.util.Collections.list(iface.getInetAddresses());
+ for(java.net.InetAddress address : addresses)
+ {
+ if(address.getAddress().length == 4 && protocol == Network.EnableIPv4 ||
+ address.getAddress().length != 4 && protocol == Network.EnableIPv6)
+ {
+ hasProtocolAddress = true;
+ break;
+ }
+ }
+
+ if(hasProtocolAddress)
+ {
+ _fd.join(group.getAddress(), iface);
+ join = true;
+ }
+ }
+
+ if(!join)
+ {
+ throw new Ice.SocketException(new IllegalArgumentException(
+ "There are no interfaces that are configured for the group protocol.\n" +
+ "Cannot join the multicast group."));
+ }
+ }
+ }
+ else if(intf != null)
+ {
+ //
+ // Otherwise, set the multicast interface if specified.
+ //
+ _fd.setOption(java.net.StandardSocketOptions.IP_MULTICAST_IF, intf);
+ }
+
+ if(ttl != -1)
+ {
+ _fd.setOption(java.net.StandardSocketOptions.IP_MULTICAST_TTL, ttl);
+ }
+ }
+ catch(Exception ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+ }
+
+ @Override
+ protected synchronized void finalize()
+ throws Throwable
+ {
+ try
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_fd == null);
+ }
+ catch(java.lang.Exception ex)
+ {
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+
+ private UdpEndpointI _endpoint = null;
+ private ProtocolInstance _instance;
+
+ private int _state;
+ private int _rcvSize;
+ private int _sndSize;
+ private java.nio.channels.DatagramChannel _fd;
+ private java.net.InetSocketAddress _addr;
+ private java.net.InetSocketAddress _mcastAddr = null;
+ private String _mcastInterface;
+ private java.net.InetSocketAddress _peerAddr = null;
+
+ private boolean _incoming = false;
+ private int _port = 0;
+ private boolean _bound = false;
+
+ //
+ // The maximum IP datagram size is 65535. Subtract 20 bytes for the IP header and 8 bytes for the UDP header
+ // to get the maximum payload.
+ //
+ private final static int _udpOverhead = 20 + 8;
+ private final static int _maxPacketSize = 65535 - _udpOverhead;
+
+ private static final int StateNeedConnect = 0;
+ private static final int StateConnected = 1;
+ private static final int StateNotConnected = 2;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Util.java b/java-compat/src/Ice/src/main/java/IceInternal/Util.java
new file mode 100644
index 00000000000..46920d5d04d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Util.java
@@ -0,0 +1,301 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.util.concurrent.ThreadFactory;
+
+public final class Util
+{
+ static String
+ createThreadName(final Ice.Properties properties, final String name)
+ {
+ String threadName = properties.getProperty("Ice.ProgramName");
+ if(threadName.length() > 0)
+ {
+ threadName += "-";
+ }
+
+ threadName = threadName + name;
+ return threadName;
+ }
+
+ static ThreadFactory
+ createThreadFactory(final Ice.Properties properties, final String name)
+ {
+ return new java.util.concurrent.ThreadFactory()
+ {
+ @Override
+ public Thread newThread(Runnable r)
+ {
+ Thread t = new Thread(r);
+ t.setName(name);
+
+ if(properties.getProperty("Ice.ThreadPriority").length() > 0)
+ {
+ t.setPriority(Util.getThreadPriorityProperty(properties, "Ice"));
+ }
+ return t;
+ }
+ };
+ }
+
+ public static Instance
+ getInstance(Ice.Communicator communicator)
+ {
+ Ice.CommunicatorI p = (Ice.CommunicatorI)communicator;
+ return p.getInstance();
+ }
+
+ public static ProtocolPluginFacade
+ getProtocolPluginFacade(Ice.Communicator communicator)
+ {
+ return new ProtocolPluginFacadeI(communicator);
+ }
+
+ //
+ // Given a path name, first try to open it as a class path resource (the path is
+ // treated as absolute). If that fails, fall back to the file system. Returns null
+ // if the file does not exist and raises IOException if an error occurs.
+ //
+ public static java.io.InputStream
+ openResource(ClassLoader cl, String path)
+ throws java.io.IOException
+ {
+ //
+ // Calling getResourceAsStream on the class loader means all paths are absolute,
+ // whereas calling it on the class means all paths are relative to the class
+ // unless the path has a leading forward slash. We call it on the class loader.
+ //
+ // getResourceAsStream returns null if the resource can't be found.
+ //
+ java.io.InputStream stream = null;
+ try
+ {
+ stream = cl.getResourceAsStream(path);
+ }
+ catch(IllegalArgumentException ex)
+ {
+ //
+ // With JDK-7 this can happen if the result url (base url + path) produces a
+ // malformed url for an URLClassLoader. For example the code in following
+ // comment will produce this exception under Windows.
+ //
+ // URLClassLoader cl = new URLClassLoader(new URL[] {new URL("http://localhost:8080/")});
+ // java.io.InputStream in = IceInternal.Util.openResource(cl, "c:\\foo.txt");
+ //
+ }
+ if(stream == null)
+ {
+ try
+ {
+ java.io.File f = new java.io.File(path);
+ if(f.exists())
+ {
+ stream = new java.io.FileInputStream(f);
+ }
+ }
+ catch(java.lang.SecurityException ex)
+ {
+ // Ignore - a security manager may forbid access to the local file system.
+ }
+ }
+
+ return stream;
+ }
+
+ public static Class<?>
+ findClass(String className, ClassLoader cl)
+ throws LinkageError
+ {
+ //
+ // Try to load the class using the given class loader (if any). If that fails (or
+ // none is provided), we try to load the class a few more ways before giving up.
+ //
+ // Calling Class.forName() doesn't always work. For example, if Ice.jar is installed
+ // as an extension (in $JAVA_HOME/jre/lib/ext), calling Class.forName(name) uses the
+ // extension class loader, which will not look in CLASSPATH for the target class.
+ //
+
+ Class<?> c = null;
+
+ if(cl != null)
+ {
+ c = loadClass(className, cl);
+ }
+
+ //
+ // Try using the current thread's class loader.
+ //
+ if(c == null)
+ {
+ try
+ {
+ cl = Thread.currentThread().getContextClassLoader();
+ if(cl != null)
+ {
+ c = loadClass(className, cl);
+ }
+ }
+ catch(SecurityException ex)
+ {
+ }
+ }
+
+ //
+ // Try using Class.forName().
+ //
+ try
+ {
+ if(c == null)
+ {
+ c = Class.forName(className);
+ }
+ }
+ catch(ClassNotFoundException ex)
+ {
+ // Ignore
+ }
+
+ //
+ // Fall back to the system class loader (which knows about CLASSPATH).
+ //
+ if(c == null)
+ {
+ try
+ {
+ cl = ClassLoader.getSystemClassLoader();
+ if(cl != null)
+ {
+ c = loadClass(className, cl);
+ }
+ }
+ catch(SecurityException ex)
+ {
+ }
+ }
+
+ return c;
+ }
+
+ private static Class<?>
+ loadClass(String className, ClassLoader cl)
+ {
+ if(cl != null)
+ {
+ try
+ {
+ return cl.loadClass(className);
+ }
+ catch(ClassNotFoundException ex)
+ {
+ // Ignore
+ }
+ }
+
+ return null;
+ }
+
+ public static int
+ getThreadPriorityProperty(Ice.Properties properties, String prefix)
+ {
+ String pri = properties.getProperty(prefix + ".ThreadPriority");
+ if(pri.equals("MIN_PRIORITY") || pri.equals("java.lang.Thread.MIN_PRIORITY"))
+ {
+ return java.lang.Thread.MIN_PRIORITY;
+ }
+ else if(pri.equals("NORM_PRIORITY") || pri.equals("java.lang.Thread.NORM_PRIORITY"))
+ {
+ return java.lang.Thread.NORM_PRIORITY;
+ }
+ else if(pri.equals("MAX_PRIORITY") || pri.equals("java.lang.Thread.MAX_PRIORITY"))
+ {
+ return java.lang.Thread.MAX_PRIORITY;
+ }
+
+ try
+ {
+ return Integer.parseInt(pri);
+ }
+ catch(NumberFormatException ex)
+ {
+ }
+ return java.lang.Thread.NORM_PRIORITY;
+ }
+
+ //
+ // Translate a Slice type id (such as "::Module::Type") into its equivalent
+ // Java class name (such as "Module.Type").
+ //
+ public static String typeIdToClassName(String typeId)
+ {
+ if(!typeId.startsWith("::"))
+ {
+ return null;
+ }
+
+ StringBuilder buf = new StringBuilder(typeId.length());
+
+ int start = 2;
+ boolean done = false;
+ while(!done)
+ {
+ int end = typeId.indexOf(':', start);
+ String s;
+ if(end != -1)
+ {
+ s = typeId.substring(start, end);
+ start = end + 2;
+ }
+ else
+ {
+ s = typeId.substring(start);
+ done = true;
+ }
+ if(buf.length() > 0)
+ {
+ buf.append('.');
+ }
+ buf.append(fixKwd(s));
+ }
+
+ return buf.toString();
+ }
+
+ private static String fixKwd(String name)
+ {
+ //
+ // Keyword list. *Must* be kept in alphabetical order. Note that checkedCast and uncheckedCast
+ // are not Java keywords, but are in this list to prevent illegal code being generated if
+ // someone defines Slice operations with that name.
+ //
+ final String[] keywordList =
+ {
+ "abstract", "assert", "boolean", "break", "byte", "case", "catch",
+ "char", "checkedCast", "class", "clone", "const", "continue", "default", "do",
+ "double", "else", "enum", "equals", "extends", "false", "final", "finalize",
+ "finally", "float", "for", "getClass", "goto", "hashCode", "if",
+ "implements", "import", "instanceof", "int", "interface", "long",
+ "native", "new", "notify", "notifyAll", "null", "package", "private",
+ "protected", "public", "return", "short", "static", "strictfp", "super", "switch",
+ "synchronized", "this", "throw", "throws", "toString", "transient",
+ "true", "try", "uncheckedCast", "void", "volatile", "wait", "while"
+ };
+ boolean found = java.util.Arrays.binarySearch(keywordList, name) >= 0;
+ return found ? "_" + name : name;
+ }
+
+ //
+ // Return true if we're running on Android.
+ //
+ public static boolean isAndroid()
+ {
+ return System.getProperty("java.vm.name").startsWith("Dalvik");
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ValueFactoryManagerI.java b/java-compat/src/Ice/src/main/java/IceInternal/ValueFactoryManagerI.java
new file mode 100644
index 00000000000..dfd51f0cbd5
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ValueFactoryManagerI.java
@@ -0,0 +1,33 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class ValueFactoryManagerI implements Ice.ValueFactoryManager
+{
+ public synchronized void add(Ice.ValueFactory factory, String id)
+ {
+ Object o = _factoryMap.get(id);
+ if(o != null)
+ {
+ Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException();
+ ex.id = id;
+ ex.kindOfObject = "value factory";
+ throw ex;
+ }
+ _factoryMap.put(id, factory);
+ }
+
+ public synchronized Ice.ValueFactory find(String id)
+ {
+ return _factoryMap.get(id);
+ }
+
+ private java.util.Map<String, Ice.ValueFactory> _factoryMap = new java.util.HashMap<String, Ice.ValueFactory>();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ValueWriter.java b/java-compat/src/Ice/src/main/java/IceInternal/ValueWriter.java
new file mode 100644
index 00000000000..3184c250734
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ValueWriter.java
@@ -0,0 +1,191 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public final class ValueWriter
+{
+ public static void
+ write(java.lang.Object obj, IceUtilInternal.OutputBase out)
+ {
+ writeValue(null, obj, null, out);
+ }
+
+ private static void
+ writeValue(String name, java.lang.Object value, java.util.Map<java.lang.Object, java.lang.Object> objectTable,
+ IceUtilInternal.OutputBase out)
+ {
+ if(value == null)
+ {
+ writeName(name, out);
+ out.print("(null)");
+ }
+ else
+ {
+ Class<?> c = value.getClass();
+ if(c.equals(Byte.class) || c.equals(Short.class) || c.equals(Integer.class) || c.equals(Long.class) ||
+ c.equals(Double.class) || c.equals(Float.class) || c.equals(Boolean.class))
+ {
+ writeName(name, out);
+ out.print(value.toString());
+ }
+ else if(c.equals(String.class))
+ {
+ //
+ // Indent the lines of a string value.
+ //
+ writeName(name, out);
+ out.print("\"");
+ out.useCurrentPosAsIndent();
+ String str = value.toString();
+ int start = 0, pos;
+ while(start < str.length() && (pos = str.indexOf('\n', start)) != -1)
+ {
+ out.print(str.substring(start, pos));
+ out.nl();
+ start = pos + 1;
+ }
+ if(start < str.length())
+ {
+ out.print(str.substring(start));
+ }
+ out.print("\"");
+ out.restoreIndent();
+ }
+ else if(c.isArray())
+ {
+ int n = java.lang.reflect.Array.getLength(value);
+ for(int i = 0; i < n; i++)
+ {
+ String elem = (name != null ? name : "");
+ elem += "[" + i + "]";
+ writeValue(elem, java.lang.reflect.Array.get(value, i), objectTable, out);
+ }
+ }
+ else if(value instanceof java.util.Map)
+ {
+ java.util.Map<?,?> map = (java.util.Map<?,?>)value;
+ java.util.Iterator<?> i = map.entrySet().iterator();
+ while(i.hasNext())
+ {
+ java.util.Map.Entry<?,?> entry = (java.util.Map.Entry<?,?>)i.next();
+ String elem = (name != null ? name + "." : "");
+ writeValue(elem + "key", entry.getKey(), objectTable, out);
+ writeValue(elem + "value", entry.getValue(), objectTable, out);
+ }
+ }
+ else if(value instanceof Ice.ObjectPrxHelperBase)
+ {
+ writeName(name, out);
+ Ice.ObjectPrxHelperBase proxy = (Ice.ObjectPrxHelperBase)value;
+ out.print(proxy.__reference().toString());
+ }
+ else if(value instanceof Ice.Object)
+ {
+ //
+ // Check for recursion.
+ //
+ if(objectTable != null && objectTable.containsKey(value))
+ {
+ writeName(name, out);
+ out.print("(recursive)");
+ }
+ else
+ {
+ if(objectTable == null)
+ {
+ objectTable = new java.util.IdentityHashMap<java.lang.Object, java.lang.Object>();
+ }
+ objectTable.put(value, null);
+ writeFields(name, value, c, objectTable, out);
+ }
+ }
+ else if(value instanceof java.lang.Enum)
+ {
+ writeName(name, out);
+ out.print(((java.lang.Enum<?>)value).name());
+ }
+ else
+ {
+ //
+ // Must be struct.
+ //
+ writeFields(name, value, c, objectTable, out);
+ }
+ }
+ }
+
+ private static void
+ writeFields(String name, java.lang.Object obj, Class<?> c,
+ java.util.Map<java.lang.Object, java.lang.Object> objectTable, IceUtilInternal.OutputBase out)
+ {
+ if(!c.equals(java.lang.Object.class))
+ {
+ //
+ // Write the superclass first.
+ //
+ writeFields(name, obj, c.getSuperclass(), objectTable, out);
+
+ //
+ // Write the declared fields of the given class. We prefer to use the declared
+ // fields because it includes protected fields that may have been defined using
+ // the Slice "protected" metadata. However, if a security manager prevents us
+ // from obtaining the declared fields, we will fall back to using the public ones.
+ //
+ java.lang.reflect.Field[] fields = null;
+ try
+ {
+ fields = c.getDeclaredFields();
+ }
+ catch(java.lang.SecurityException ex)
+ {
+ try
+ {
+ fields = c.getFields();
+ }
+ catch(java.lang.SecurityException e)
+ {
+ return; // Nothing else we can do.
+ }
+ }
+ assert(fields != null);
+ for(java.lang.reflect.Field field : fields)
+ {
+ //
+ // Only write public, non-static fields.
+ //
+ int mods = field.getModifiers();
+ if(java.lang.reflect.Modifier.isPublic(mods) && !java.lang.reflect.Modifier.isStatic(mods))
+ {
+ String fieldName = (name != null ? name + '.' + field.getName() : field.getName());
+
+ try
+ {
+ java.lang.Object value = field.get(obj);
+ writeValue(fieldName, value, objectTable, out);
+ }
+ catch(IllegalAccessException ex)
+ {
+ assert(false);
+ }
+ }
+ }
+ }
+ }
+
+ private static void
+ writeName(String name, IceUtilInternal.OutputBase out)
+ {
+ if(name != null)
+ {
+ out.nl();
+ out.print(name + " = ");
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/WSAcceptor.java b/java-compat/src/Ice/src/main/java/IceInternal/WSAcceptor.java
new file mode 100644
index 00000000000..4b87907a671
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/WSAcceptor.java
@@ -0,0 +1,82 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class WSAcceptor implements IceInternal.Acceptor
+{
+ @Override
+ public java.nio.channels.ServerSocketChannel fd()
+ {
+ return _delegate.fd();
+ }
+
+ @Override
+ public void setReadyCallback(ReadyCallback callback)
+ {
+ _delegate.setReadyCallback(callback);
+ }
+
+ @Override
+ public void close()
+ {
+ _delegate.close();
+ }
+
+ @Override
+ public EndpointI listen()
+ {
+ _endpoint = _endpoint.endpoint(_delegate.listen());
+ return _endpoint;
+ }
+
+ @Override
+ public IceInternal.Transceiver accept()
+ {
+ //
+ // WebSocket handshaking is performed in TransceiverI::initialize, since
+ // accept must not block.
+ //
+ return new WSTransceiver(_instance, _delegate.accept());
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _delegate.protocol();
+ }
+
+ @Override
+ public String toString()
+ {
+ return _delegate.toString();
+ }
+
+ @Override
+ public String toDetailedString()
+ {
+ return _delegate.toDetailedString();
+ }
+
+ public Acceptor delegate()
+ {
+ return _delegate;
+ }
+
+ WSAcceptor(WSEndpoint endpoint, ProtocolInstance instance, IceInternal.Acceptor del)
+ {
+ _endpoint = endpoint;
+ _instance = instance;
+ _delegate = del;
+ }
+
+ private WSEndpoint _endpoint;
+ private ProtocolInstance _instance;
+ private IceInternal.Acceptor _delegate;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/WSConnector.java b/java-compat/src/Ice/src/main/java/IceInternal/WSConnector.java
new file mode 100644
index 00000000000..3c9ecc7e06b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/WSConnector.java
@@ -0,0 +1,77 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class WSConnector implements Connector
+{
+ @Override
+ public Transceiver connect()
+ {
+ return new WSTransceiver(_instance, _delegate.connect(), _host, _resource);
+ }
+
+ @Override
+ public short type()
+ {
+ return _delegate.type();
+ }
+
+ @Override
+ public String toString()
+ {
+ return _delegate.toString();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return _delegate.hashCode();
+ }
+
+ WSConnector(ProtocolInstance instance, Connector del, String host, String resource)
+ {
+ _instance = instance;
+ _delegate = del;
+ _host = host;
+ _resource = resource;
+ }
+
+ @Override
+ public boolean equals(java.lang.Object obj)
+ {
+ if(!(obj instanceof WSConnector))
+ {
+ return false;
+ }
+
+ if(this == obj)
+ {
+ return true;
+ }
+
+ WSConnector p = (WSConnector)obj;
+ if(!_delegate.equals(p._delegate))
+ {
+ return false;
+ }
+
+ if(!_resource.equals(p._resource))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private ProtocolInstance _instance;
+ private Connector _delegate;
+ private String _host;
+ private String _resource;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/WSEndpoint.java b/java-compat/src/Ice/src/main/java/IceInternal/WSEndpoint.java
new file mode 100644
index 00000000000..91ea36d1a62
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/WSEndpoint.java
@@ -0,0 +1,324 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class WSEndpoint extends IceInternal.EndpointI
+{
+ public WSEndpoint(ProtocolInstance instance, EndpointI del, String res)
+ {
+ _instance = instance;
+ _delegate = del;
+ _resource = res;
+ }
+
+ public WSEndpoint(ProtocolInstance instance, EndpointI del, java.util.ArrayList<String> args)
+ {
+ _instance = instance;
+ _delegate = del;
+
+ initWithOptions(args);
+
+ if(_resource == null)
+ {
+ _resource = "/";
+ }
+ }
+
+ public WSEndpoint(ProtocolInstance instance, EndpointI del, Ice.InputStream s)
+ {
+ _instance = instance;
+ _delegate = del;
+ _resource = s.readString();
+ }
+
+ @Override
+ public Ice.EndpointInfo getInfo()
+ {
+ Ice.WSEndpointInfo info = new Ice.WSEndpointInfo(_delegate.getInfo(), timeout(), compress(), _resource)
+ {
+ @Override
+ public short type()
+ {
+ return WSEndpoint.this.type();
+ }
+
+ @Override
+ public boolean datagram()
+ {
+ return WSEndpoint.this.datagram();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return WSEndpoint.this.secure();
+ }
+ };
+ info.compress = info.underlying.compress;
+ info.timeout = info.underlying.timeout;
+ return info;
+ }
+
+ @Override
+ public short type()
+ {
+ return _delegate.type();
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _delegate.protocol();
+ }
+
+ @Override
+ public void streamWriteImpl(Ice.OutputStream s)
+ {
+ _delegate.streamWriteImpl(s);
+ s.writeString(_resource);
+ }
+
+ @Override
+ public int timeout()
+ {
+ return _delegate.timeout();
+ }
+
+ @Override
+ public EndpointI timeout(int timeout)
+ {
+ if(timeout == _delegate.timeout())
+ {
+ return this;
+ }
+ else
+ {
+ return new WSEndpoint(_instance, _delegate.timeout(timeout), _resource);
+ }
+ }
+
+ @Override
+ public String connectionId()
+ {
+ return _delegate.connectionId();
+ }
+
+ @Override
+ public EndpointI connectionId(String connectionId)
+ {
+ if(connectionId.equals(_delegate.connectionId()))
+ {
+ return this;
+ }
+ else
+ {
+ return new WSEndpoint(_instance, _delegate.connectionId(connectionId), _resource);
+ }
+ }
+
+ @Override
+ public boolean compress()
+ {
+ return _delegate.compress();
+ }
+
+ @Override
+ public EndpointI compress(boolean compress)
+ {
+ if(compress == _delegate.compress())
+ {
+ return this;
+ }
+ else
+ {
+ return new WSEndpoint(_instance, _delegate.compress(compress), _resource);
+ }
+ }
+
+ @Override
+ public boolean datagram()
+ {
+ return _delegate.datagram();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return _delegate.secure();
+ }
+
+ @Override
+ public Transceiver transceiver()
+ {
+ return null;
+ }
+
+ @Override
+ public void connectors_async(Ice.EndpointSelectionType selType, final EndpointI_connectors callback)
+ {
+ Ice.IPEndpointInfo ipInfo = null;
+ for(Ice.EndpointInfo p = _delegate.getInfo(); p != null; p = p.underlying)
+ {
+ if(p instanceof Ice.IPEndpointInfo)
+ {
+ ipInfo = (Ice.IPEndpointInfo)p;
+ }
+ }
+ final String host = ipInfo != null ? (ipInfo.host + ":" + ipInfo.port) : "";
+ EndpointI_connectors cb = new EndpointI_connectors()
+ {
+ @Override
+ public void connectors(java.util.List<Connector> connectors)
+ {
+ java.util.List<Connector> l = new java.util.ArrayList<Connector>();
+ for(Connector c : connectors)
+ {
+ l.add(new WSConnector(_instance, c, host, _resource));
+ }
+ callback.connectors(l);
+ }
+
+ @Override
+ public void exception(Ice.LocalException ex)
+ {
+ callback.exception(ex);
+ }
+ };
+ _delegate.connectors_async(selType, cb);
+ }
+
+ @Override
+ public Acceptor acceptor(String adapterName)
+ {
+ Acceptor delAcc = _delegate.acceptor(adapterName);
+ return new WSAcceptor(this, _instance, delAcc);
+ }
+
+ public WSEndpoint endpoint(EndpointI delEndp)
+ {
+ return new WSEndpoint(_instance, delEndp, _resource);
+ }
+
+ @Override
+ public java.util.List<EndpointI> expand()
+ {
+ java.util.List<EndpointI> endps = _delegate.expand();
+ java.util.List<EndpointI> l = new java.util.ArrayList<EndpointI>();
+ for(EndpointI e : endps)
+ {
+ l.add(e == _delegate ? this : new WSEndpoint(_instance, e, _resource));
+ }
+ return l;
+ }
+
+ @Override
+ public boolean equivalent(EndpointI endpoint)
+ {
+ if(!(endpoint instanceof WSEndpoint))
+ {
+ return false;
+ }
+ WSEndpoint wsEndpointI = (WSEndpoint)endpoint;
+ return _delegate.equivalent(wsEndpointI._delegate);
+ }
+
+ @Override
+ synchronized public int hashCode()
+ {
+ int h = _delegate.hashCode();
+ h = IceInternal.HashUtil.hashAdd(h, _resource);
+ return h;
+ }
+
+ @Override
+ public String options()
+ {
+ //
+ // 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.
+ //
+ String s = _delegate.options();
+
+ if(_resource != null && _resource.length() > 0)
+ {
+ s += " -r ";
+ boolean addQuote = _resource.indexOf(':') != -1;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ s += _resource;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ }
+
+ return s;
+ }
+
+ @Override
+ public int compareTo(EndpointI obj) // From java.lang.Comparable
+ {
+ if(!(obj instanceof WSEndpoint))
+ {
+ return type() < obj.type() ? -1 : 1;
+ }
+
+ WSEndpoint p = (WSEndpoint)obj;
+ if(this == p)
+ {
+ return 0;
+ }
+
+ int v = _resource.compareTo(p._resource);
+ if(v != 0)
+ {
+ return v;
+ }
+
+ return _delegate.compareTo(p._delegate);
+ }
+
+ public EndpointI delegate()
+ {
+ return _delegate;
+ }
+
+ @Override
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ switch(option.charAt(1))
+ {
+ case 'r':
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -r option in endpoint " + endpoint +
+ _delegate.options());
+ }
+ _resource = argument;
+ return true;
+ }
+
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+ private ProtocolInstance _instance;
+ private EndpointI _delegate;
+ private String _resource;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/WSEndpointFactory.java b/java-compat/src/Ice/src/main/java/IceInternal/WSEndpointFactory.java
new file mode 100644
index 00000000000..493cddfd5eb
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/WSEndpointFactory.java
@@ -0,0 +1,59 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final public class WSEndpointFactory implements EndpointFactory
+{
+ public WSEndpointFactory(ProtocolInstance instance, EndpointFactory delegate)
+ {
+ _instance = instance;
+ _delegate = delegate;
+ }
+
+ @Override
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public EndpointI create(java.util.ArrayList<String> args, boolean oaEndpoint)
+ {
+ return new WSEndpoint(_instance, _delegate.create(args, oaEndpoint), args);
+ }
+
+ @Override
+ public EndpointI read(Ice.InputStream s)
+ {
+ return new WSEndpoint(_instance, _delegate.read(s), s);
+ }
+
+ @Override
+ public void destroy()
+ {
+ _delegate.destroy();
+ _instance = null;
+ }
+
+ @Override
+ public EndpointFactory clone(ProtocolInstance instance, EndpointFactory delegate)
+ {
+ return new WSEndpointFactory(instance, delegate);
+ }
+
+ private ProtocolInstance _instance;
+ private EndpointFactory _delegate;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/WSTransceiver.java b/java-compat/src/Ice/src/main/java/IceInternal/WSTransceiver.java
new file mode 100644
index 00000000000..8188ab322c8
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/WSTransceiver.java
@@ -0,0 +1,1616 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.security.*;
+
+final class WSTransceiver implements Transceiver
+{
+ @Override
+ public java.nio.channels.SelectableChannel fd()
+ {
+ return _delegate.fd();
+ }
+
+ @Override
+ public void setReadyCallback(ReadyCallback callback)
+ {
+ _readyCallback = callback;
+ _delegate.setReadyCallback(callback);
+ }
+
+ @Override
+ public int initialize(Buffer readBuffer, Buffer writeBuffer)
+ {
+ //
+ // Delegate logs exceptions that occur during initialize(), so there's no need to trap them here.
+ //
+ if(_state == StateInitializeDelegate)
+ {
+ int op = _delegate.initialize(readBuffer, writeBuffer);
+ if(op != 0)
+ {
+ return op;
+ }
+ _state = StateConnected;
+ }
+
+ try
+ {
+ if(_state == StateConnected)
+ {
+ //
+ // We don't know how much we'll need to read.
+ //
+ _readBuffer.resize(1024, true);
+ _readBuffer.b.position(0);
+ _readBufferPos = 0;
+
+ //
+ // The server waits for the client's upgrade request, the
+ // client sends the upgrade request.
+ //
+ _state = StateUpgradeRequestPending;
+ if(!_incoming)
+ {
+ //
+ // Compose the upgrade request.
+ //
+ StringBuffer out = new StringBuffer();
+ out.append("GET " + _resource + " HTTP/1.1\r\n");
+ out.append("Host: " + _host);
+ out.append("\r\n");
+ out.append("Upgrade: websocket\r\n");
+ out.append("Connection: Upgrade\r\n");
+ out.append("Sec-WebSocket-Protocol: " + _iceProtocol + "\r\n");
+ out.append("Sec-WebSocket-Version: 13\r\n");
+ out.append("Sec-WebSocket-Key: ");
+
+ //
+ // The value for Sec-WebSocket-Key is a 16-byte random number,
+ // encoded with Base64.
+ //
+ byte[] key = new byte[16];
+ _rand.nextBytes(key);
+ _key = IceUtilInternal.Base64.encode(key);
+ out.append(_key + "\r\n\r\n"); // EOM
+
+ _writeBuffer.resize(out.length(), false);
+ _writeBuffer.b.position(0);
+ _writeBuffer.b.put(out.toString().getBytes(_ascii));
+ _writeBuffer.b.flip();
+ }
+ }
+
+ //
+ // Try to write the client's upgrade request.
+ //
+ if(_state == StateUpgradeRequestPending && !_incoming)
+ {
+ if(_writeBuffer.b.hasRemaining())
+ {
+ int s = _delegate.write(_writeBuffer);
+ if(s != 0)
+ {
+ return s;
+ }
+ }
+ assert(!_writeBuffer.b.hasRemaining());
+ _state = StateUpgradeResponsePending;
+ }
+
+ while(true)
+ {
+ if(_readBuffer.b.hasRemaining())
+ {
+ int s = _delegate.read(_readBuffer);
+ if(s == SocketOperation.Write || _readBuffer.b.position() == 0)
+ {
+ return s;
+ }
+ }
+
+ //
+ // Try to read the client's upgrade request or the server's response.
+ //
+ if((_state == StateUpgradeRequestPending && _incoming) ||
+ (_state == StateUpgradeResponsePending && !_incoming))
+ {
+ //
+ // Check if we have enough data for a complete message.
+ //
+ int p = _parser.isCompleteMessage(_readBuffer.b, 0, _readBuffer.b.position());
+ if(p == -1)
+ {
+ if(_readBuffer.b.hasRemaining())
+ {
+ return SocketOperation.Read;
+ }
+
+ //
+ // Enlarge the buffer and try to read more.
+ //
+ final int oldSize = _readBuffer.b.position();
+ if(oldSize + 1024 > _instance.messageSizeMax())
+ {
+ throw new Ice.MemoryLimitException();
+ }
+ _readBuffer.resize(oldSize + 1024, true);
+ _readBuffer.b.position(oldSize);
+ continue; // Try again to read the response/request
+ }
+
+ //
+ // Set _readBufferPos at the end of the response/request message.
+ //
+ _readBufferPos = p;
+ }
+
+ //
+ // We're done, the client's upgrade request or server's response is read.
+ //
+ break;
+ }
+
+ try
+ {
+ //
+ // Parse the client's upgrade request.
+ //
+ if(_state == StateUpgradeRequestPending && _incoming)
+ {
+ if(_parser.parse(_readBuffer.b, 0, _readBufferPos))
+ {
+ handleRequest(_writeBuffer);
+ _state = StateUpgradeResponsePending;
+ }
+ else
+ {
+ throw new Ice.ProtocolException("incomplete request message");
+ }
+ }
+
+ if(_state == StateUpgradeResponsePending)
+ {
+ if(_incoming)
+ {
+ if(_writeBuffer.b.hasRemaining())
+ {
+ int s = _delegate.write(_writeBuffer);
+ if(s != 0)
+ {
+ return s;
+ }
+ }
+ }
+ else
+ {
+ //
+ // Parse the server's response
+ //
+ if(_parser.parse(_readBuffer.b, 0, _readBufferPos))
+ {
+ handleResponse();
+ }
+ else
+ {
+ throw new Ice.ProtocolException("incomplete response message");
+ }
+ }
+ }
+ }
+ catch(WebSocketException ex)
+ {
+ throw new Ice.ProtocolException(ex.getMessage());
+ }
+
+ _state = StateOpened;
+ _nextState = StateOpened;
+
+ if(_readBufferPos < _readBuffer.b.position())
+ {
+ _readyCallback.ready(SocketOperation.Read, true);
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ if(_instance.traceLevel() >= 2)
+ {
+ _instance.logger().trace(_instance.traceCategory(),
+ protocol() + " connection HTTP upgrade request failed\n" + toString() + "\n" + ex);
+ }
+ throw ex;
+ }
+
+ if(_instance.traceLevel() >= 1)
+ {
+ if(_incoming)
+ {
+ _instance.logger().trace(_instance.traceCategory(),
+ "accepted " + protocol() + " connection HTTP upgrade request\n" + toString());
+ }
+ else
+ {
+ _instance.logger().trace(_instance.traceCategory(),
+ protocol() + " connection HTTP upgrade request accepted\n" + toString());
+ }
+ }
+
+ return SocketOperation.None;
+ }
+
+ @Override
+ public int closing(boolean initiator, Ice.LocalException reason)
+ {
+ if(_instance.traceLevel() >= 1)
+ {
+ _instance.logger().trace(_instance.traceCategory(),
+ "gracefully closing " + protocol() + " connection\n" + toString());
+ }
+
+ int s = _nextState == StateOpened ? _state : _nextState;
+
+ if(s == StateClosingRequestPending && _closingInitiator)
+ {
+ //
+ // If we initiated a close connection but also received a
+ // close connection, we assume we didn't initiated the
+ // connection and we send the close frame now. This is to
+ // ensure that if both peers close the connection at the same
+ // time we don't hang having both peer waiting for the close
+ // frame of the other.
+ //
+ assert(!initiator);
+ _closingInitiator = false;
+ return SocketOperation.Write;
+ }
+ else if(s >= StateClosingRequestPending)
+ {
+ return SocketOperation.None;
+ }
+
+ _closingInitiator = initiator;
+ if(reason instanceof Ice.CloseConnectionException)
+ {
+ _closingReason = CLOSURE_NORMAL;
+ }
+ else if(reason instanceof Ice.ObjectAdapterDeactivatedException ||
+ reason instanceof Ice.CommunicatorDestroyedException)
+ {
+ _closingReason = CLOSURE_SHUTDOWN;
+ }
+ else if(reason instanceof Ice.ProtocolException)
+ {
+ _closingReason = CLOSURE_PROTOCOL_ERROR;
+ }
+ else if(reason instanceof Ice.MemoryLimitException)
+ {
+ _closingReason = CLOSURE_TOO_BIG;
+ }
+
+ if(_state == StateOpened)
+ {
+ _state = StateClosingRequestPending;
+ return initiator ? SocketOperation.Read : SocketOperation.Write;
+ }
+ else
+ {
+ _nextState = StateClosingRequestPending;
+ return SocketOperation.None;
+ }
+ }
+
+ @Override
+ public void close()
+ {
+ _delegate.close();
+ _state = StateClosed;
+
+ //
+ // Clear the buffers now instead of waiting for destruction.
+ //
+ _writeBuffer.clear();
+ _readBuffer.clear();
+ }
+
+ @Override
+ public EndpointI bind()
+ {
+ assert(false);
+ return null;
+ }
+
+ @Override
+ public int write(Buffer buf)
+ {
+ if(_state < StateOpened)
+ {
+ if(_state < StateConnected)
+ {
+ return _delegate.write(buf);
+ }
+ else
+ {
+ return _delegate.write(_writeBuffer);
+ }
+ }
+
+ int s = SocketOperation.None;
+ do
+ {
+ if(preWrite(buf))
+ {
+ if(_writeState == WriteStateFlush)
+ {
+ //
+ // Invoke write() even though there's nothing to write.
+ //
+ assert(!buf.b.hasRemaining());
+ s = _delegate.write(buf);
+ }
+
+ if(s == SocketOperation.None && _writeBuffer.b.hasRemaining())
+ {
+ s = _delegate.write(_writeBuffer);
+ }
+ else if(s == SocketOperation.None && _incoming && !buf.empty() && _writeState == WriteStatePayload)
+ {
+ s = _delegate.write(buf);
+ }
+ }
+ }
+ while(postWrite(buf, s));
+
+ if(s != SocketOperation.None)
+ {
+ return s;
+ }
+ if(_state == StateClosingResponsePending && !_closingInitiator)
+ {
+ return SocketOperation.Read;
+ }
+ return SocketOperation.None;
+ }
+
+ @Override
+ public int read(Buffer buf)
+ {
+ if(_state < StateOpened)
+ {
+ if(_state < StateConnected)
+ {
+ return _delegate.read(buf);
+ }
+ else
+ {
+ if(_delegate.read(_readBuffer) == SocketOperation.Write)
+ {
+ return SocketOperation.Write;
+ }
+ else
+ {
+ return SocketOperation.None;
+ }
+ }
+ }
+
+ if(!buf.b.hasRemaining())
+ {
+ if(_readBufferPos < _readBuffer.b.position())
+ {
+ _readyCallback.ready(SocketOperation.Read, true);
+ }
+ return SocketOperation.None;
+ }
+
+ int s = SocketOperation.None;
+ do
+ {
+ if(preRead(buf))
+ {
+ if(_readState == ReadStatePayload)
+ {
+ //
+ // If the payload length is smaller than what remains to be read, we read
+ // no more than the payload length. The remaining of the buffer will be
+ // sent over in another frame.
+ //
+ int readSz = _readPayloadLength - (buf.b.position() - _readStart);
+ if(buf.b.remaining() > readSz)
+ {
+ int size = buf.size();
+ buf.resize(buf.b.position() + readSz, true);
+ s = _delegate.read(buf);
+ buf.resize(size, true);
+ }
+ else
+ {
+ s = _delegate.read(buf);
+ }
+ }
+ else
+ {
+ s = _delegate.read(_readBuffer);
+ }
+
+ if(s == SocketOperation.Write)
+ {
+ postRead(buf);
+ return s;
+ }
+ }
+ }
+ while(postRead(buf));
+
+ if(!buf.b.hasRemaining())
+ {
+ if(_readBufferPos < _readBuffer.b.position())
+ {
+ _readyCallback.ready(SocketOperation.Read, true);
+ }
+ s = SocketOperation.None;
+ }
+ else
+ {
+ _readyCallback.ready(SocketOperation.Read, false);
+ s = SocketOperation.Read;
+ }
+
+ if(((_state == StateClosingRequestPending && !_closingInitiator) ||
+ (_state == StateClosingResponsePending && _closingInitiator) ||
+ _state == StatePingPending ||
+ _state == StatePongPending) &&
+ _writeState == WriteStateHeader)
+ {
+ // We have things to write, ask to be notified when writes are ready.
+ s |= SocketOperation.Write;
+ }
+
+ return s;
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public String toString()
+ {
+ return _delegate.toString();
+ }
+
+ @Override
+ public String toDetailedString()
+ {
+ return _delegate.toDetailedString();
+ }
+
+ @Override
+ public Ice.ConnectionInfo getInfo()
+ {
+ Ice.WSConnectionInfo info = new Ice.WSConnectionInfo();
+ info.underlying = _delegate.getInfo();
+ info.headers = _parser.getHeaders();
+ return info;
+ }
+
+ @Override
+ public void checkSendSize(Buffer buf)
+ {
+ _delegate.checkSendSize(buf);
+ }
+
+ @Override
+ public void setBufferSize(int rcvSize, int sndSize)
+ {
+ _delegate.setBufferSize(rcvSize, sndSize);
+ }
+
+ WSTransceiver(ProtocolInstance instance, Transceiver del, String host, String resource)
+ {
+ init(instance, del);
+ _host = host;
+ _resource = resource;
+ _incoming = false;
+
+ //
+ // Use a 16KB write buffer size. We use 16KB for the write
+ // buffer size because all the data needs to be copied to the
+ // write buffer for the purpose of masking. A 16KB buffer
+ // appears to be a good compromise to reduce the number of
+ // socket write calls and not consume too much memory.
+ //
+ _writeBufferSize = 16 * 1024;
+
+ //
+ // Write and read buffer size must be large enough to hold the frame header!
+ //
+ assert(_writeBufferSize > 256);
+ assert(_readBufferSize > 256);
+ }
+
+ WSTransceiver(ProtocolInstance instance, Transceiver del)
+ {
+ init(instance, del);
+ _host = "";
+ _resource = "";
+ _incoming = true;
+
+ //
+ // Write and read buffer size must be large enough to hold the frame header!
+ //
+ assert(_writeBufferSize > 256);
+ assert(_readBufferSize > 256);
+ }
+
+ private void init(ProtocolInstance instance, Transceiver del)
+ {
+ _instance = instance;
+ _delegate = del;
+ _state = StateInitializeDelegate;
+ _parser = new HttpParser();
+ _readState = ReadStateOpcode;
+ _readBuffer = new Buffer(false, java.nio.ByteOrder.BIG_ENDIAN); // Use network byte order.
+ _readBufferSize = 1024;
+ _readLastFrame = true;
+ _readOpCode = 0;
+ _readHeaderLength = 0;
+ _readPayloadLength = 0;
+ _readMask = new byte[4];
+ _writeState = WriteStateHeader;
+ _writeBuffer = new Buffer(false, java.nio.ByteOrder.BIG_ENDIAN); // Use network byte order.
+ _writeBufferSize = 1024;
+ _readMask = new byte[4];
+ _writeMask = new byte[4];
+ _key = "";
+ _pingPayload = new byte[0];
+ _rand = new java.util.Random();
+ }
+
+ private void handleRequest(Buffer responseBuffer)
+ {
+ //
+ // HTTP/1.1
+ //
+ if(_parser.versionMajor() != 1 || _parser.versionMinor() != 1)
+ {
+ throw new WebSocketException("unsupported HTTP version");
+ }
+
+ //
+ // "An |Upgrade| header field containing the value 'websocket',
+ // treated as an ASCII case-insensitive value."
+ //
+ String val = _parser.getHeader("Upgrade", true);
+ if(val == null)
+ {
+ throw new WebSocketException("missing value for Upgrade field");
+ }
+ else if(!val.equals("websocket"))
+ {
+ throw new WebSocketException("invalid value `" + val + "' for Upgrade field");
+ }
+
+ //
+ // "A |Connection| header field that includes the token 'Upgrade',
+ // treated as an ASCII case-insensitive value.
+ //
+ val = _parser.getHeader("Connection", true);
+ if(val == null)
+ {
+ throw new WebSocketException("missing value for Connection field");
+ }
+ else if(val.indexOf("upgrade") == -1)
+ {
+ throw new WebSocketException("invalid value `" + val + "' for Connection field");
+ }
+
+ //
+ // "A |Sec-WebSocket-Version| header field, with a value of 13."
+ //
+ val = _parser.getHeader("Sec-WebSocket-Version", false);
+ if(val == null)
+ {
+ throw new WebSocketException("missing value for WebSocket version");
+ }
+ else if(!val.equals("13"))
+ {
+ throw new WebSocketException("unsupported WebSocket version `" + val + "'");
+ }
+
+ //
+ // "Optionally, a |Sec-WebSocket-Protocol| header field, with a list
+ // of values indicating which protocols the client would like to
+ // speak, ordered by preference."
+ //
+ boolean addProtocol = false;
+ val = _parser.getHeader("Sec-WebSocket-Protocol", true);
+ if(val != null)
+ {
+ String[] protocols = IceUtilInternal.StringUtil.splitString(val, ",");
+ if(protocols == null)
+ {
+ throw new WebSocketException("invalid value `" + val + "' for WebSocket protocol");
+ }
+ for(String p : protocols)
+ {
+ if(!p.trim().equals(_iceProtocol))
+ {
+ throw new WebSocketException("unknown value `" + p + "' for WebSocket protocol");
+ }
+ addProtocol = true;
+ }
+ }
+
+ //
+ // "A |Sec-WebSocket-Key| header field with a base64-encoded
+ // value that, when decoded, is 16 bytes in length."
+ //
+ String key = _parser.getHeader("Sec-WebSocket-Key", false);
+ if(key == null)
+ {
+ throw new WebSocketException("missing value for WebSocket key");
+ }
+
+ byte[] decodedKey = IceUtilInternal.Base64.decode(key);
+ if(decodedKey.length != 16)
+ {
+ throw new WebSocketException("invalid value `" + key + "' for WebSocket key");
+ }
+
+ //
+ // Retain the target resource.
+ //
+ _resource = _parser.uri();
+
+ //
+ // Compose the response.
+ //
+ StringBuffer out = new StringBuffer();
+ out.append("HTTP/1.1 101 Switching Protocols\r\n");
+ out.append("Upgrade: websocket\r\n");
+ out.append("Connection: Upgrade\r\n");
+ if(addProtocol)
+ {
+ out.append("Sec-WebSocket-Protocol: " + _iceProtocol + "\r\n");
+ }
+
+ //
+ // The response includes:
+ //
+ // "A |Sec-WebSocket-Accept| header field. The value of this
+ // header field is constructed by concatenating /key/, defined
+ // above in step 4 in Section 4.2.2, with the string "258EAFA5-
+ // E914-47DA-95CA-C5AB0DC85B11", taking the SHA-1 hash of this
+ // concatenated value to obtain a 20-byte value and base64-
+ // encoding (see Section 4 of [RFC4648]) this 20-byte hash.
+ //
+ out.append("Sec-WebSocket-Accept: ");
+ final String input = key + _wsUUID;
+ try
+ {
+ final MessageDigest sha1 = MessageDigest.getInstance("SHA1");
+ sha1.update(input.getBytes(_ascii));
+ final byte[] hash = sha1.digest();
+ out.append(IceUtilInternal.Base64.encode(hash) + "\r\n" + "\r\n"); // EOM
+ }
+ catch(NoSuchAlgorithmException ex)
+ {
+ throw new WebSocketException(ex);
+ }
+
+ final byte[] bytes = out.toString().getBytes(_ascii);
+ assert(bytes.length == out.length());
+ responseBuffer.resize(bytes.length, false);
+ responseBuffer.b.position(0);
+ responseBuffer.b.put(bytes);
+ responseBuffer.b.flip();
+ }
+
+ private void handleResponse()
+ {
+ String val;
+
+ //
+ // HTTP/1.1
+ //
+ if(_parser.versionMajor() != 1 || _parser.versionMinor() != 1)
+ {
+ throw new WebSocketException("unsupported HTTP version");
+ }
+
+ //
+ // "If the status code received from the server is not 101, the
+ // client handles the response per HTTP [RFC2616] procedures. In
+ // particular, the client might perform authentication if it
+ // receives a 401 status code; the server might redirect the client
+ // using a 3xx status code (but clients are not required to follow
+ // them), etc."
+ //
+ if(_parser.status() != 101)
+ {
+ StringBuffer out = new StringBuffer("unexpected status value " + _parser.status());
+ if(_parser.reason().length() > 0)
+ {
+ out.append(":\n" + _parser.reason());
+ }
+ throw new WebSocketException(out.toString());
+ }
+
+ //
+ // "If the response lacks an |Upgrade| header field or the |Upgrade|
+ // header field contains a value that is not an ASCII case-
+ // insensitive match for the value "websocket", the client MUST
+ // _Fail the WebSocket Connection_."
+ //
+ val = _parser.getHeader("Upgrade", true);
+ if(val == null)
+ {
+ throw new WebSocketException("missing value for Upgrade field");
+ }
+ else if(!val.equals("websocket"))
+ {
+ throw new WebSocketException("invalid value `" + val + "' for Upgrade field");
+ }
+
+ //
+ // "If the response lacks a |Connection| header field or the
+ // |Connection| header field doesn't contain a token that is an
+ // ASCII case-insensitive match for the value "Upgrade", the client
+ // MUST _Fail the WebSocket Connection_."
+ //
+ val = _parser.getHeader("Connection", true);
+ if(val == null)
+ {
+ throw new WebSocketException("missing value for Connection field");
+ }
+ else if(val.indexOf("upgrade") == -1)
+ {
+ throw new WebSocketException("invalid value `" + val + "' for Connection field");
+ }
+
+ //
+ // "If the response includes a |Sec-WebSocket-Protocol| header field
+ // and this header field indicates the use of a subprotocol that was
+ // not present in the client's handshake (the server has indicated a
+ // subprotocol not requested by the client), the client MUST _Fail
+ // the WebSocket Connection_."
+ //
+ val = _parser.getHeader("Sec-WebSocket-Protocol", true);
+ if(val != null && !val.equals(_iceProtocol))
+ {
+ throw new WebSocketException("invalid value `" + val + "' for WebSocket protocol");
+ }
+
+ //
+ // "If the response lacks a |Sec-WebSocket-Accept| header field or
+ // the |Sec-WebSocket-Accept| contains a value other than the
+ // base64-encoded SHA-1 of the concatenation of the |Sec-WebSocket-
+ // Key| (as a string, not base64-decoded) with the string "258EAFA5-
+ // E914-47DA-95CA-C5AB0DC85B11" but ignoring any leading and
+ // trailing whitespace, the client MUST _Fail the WebSocket
+ // Connection_."
+ //
+ val = _parser.getHeader("Sec-WebSocket-Accept", false);
+ if(val == null)
+ {
+ throw new WebSocketException("missing value for Sec-WebSocket-Accept");
+ }
+
+ try
+ {
+ final String input = _key + _wsUUID;
+ final MessageDigest sha1 = MessageDigest.getInstance("SHA1");
+ sha1.update(input.getBytes(_ascii));
+ if(!val.equals(IceUtilInternal.Base64.encode(sha1.digest())))
+ {
+ throw new WebSocketException("invalid value `" + val + "' for Sec-WebSocket-Accept");
+ }
+ }
+ catch(NoSuchAlgorithmException ex)
+ {
+ throw new WebSocketException(ex);
+ }
+ }
+
+ private boolean preRead(Buffer buf)
+ {
+ while(true)
+ {
+ if(_readState == ReadStateOpcode)
+ {
+ //
+ // Is there enough data available to read the opcode?
+ //
+ if(!readBuffered(2))
+ {
+ return true;
+ }
+
+ //
+ // Most-significant bit indicates whether this is the
+ // last frame. Least-significant four bits hold the
+ // opcode.
+ //
+ int ch = _readBuffer.b.get(_readBufferPos++);
+ if(ch < 0)
+ {
+ ch += 256;
+ }
+ _readOpCode = ch & 0xf;
+
+ //
+ // Remember if last frame if we're going to read a data or
+ // continuation frame, this is only for protocol
+ // correctness checking purpose.
+ //
+ if(_readOpCode == OP_DATA)
+ {
+ if(!_readLastFrame)
+ {
+ throw new Ice.ProtocolException("invalid data frame, no FIN on previous frame");
+ }
+ _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
+ }
+ else if(_readOpCode == OP_CONT)
+ {
+ if(_readLastFrame)
+ {
+ throw new Ice.ProtocolException("invalid continuation frame, previous frame FIN set");
+ }
+ _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
+ }
+
+ ch = _readBuffer.b.get(_readBufferPos++);
+ if(ch < 0)
+ {
+ ch += 256;
+ }
+
+ //
+ // Check the MASK bit. Messages sent by a client must be masked;
+ // messages sent by a server must not be masked.
+ //
+ final boolean masked = (ch & FLAG_MASKED) == FLAG_MASKED;
+ if(masked != _incoming)
+ {
+ throw new Ice.ProtocolException("invalid masking");
+ }
+
+ //
+ // Extract the payload length, which can have the following values:
+ //
+ // 0-125: The payload length
+ // 126: The subsequent two bytes contain the payload length
+ // 127: The subsequent eight bytes contain the payload length
+ //
+ _readPayloadLength = (ch & 0x7f);
+ if(_readPayloadLength < 126)
+ {
+ _readHeaderLength = 0;
+ }
+ else if(_readPayloadLength == 126)
+ {
+ _readHeaderLength = 2; // Need to read a 16-bit payload length.
+ }
+ else
+ {
+ _readHeaderLength = 8; // Need to read a 64-bit payload length.
+ }
+ if(masked)
+ {
+ _readHeaderLength += 4; // Need to read a 32-bit mask.
+ }
+
+ _readState = ReadStateHeader;
+ }
+
+ if(_readState == ReadStateHeader)
+ {
+ //
+ // Is there enough data available to read the header?
+ //
+ if(_readHeaderLength > 0 && !readBuffered(_readHeaderLength))
+ {
+ return true;
+ }
+
+ if(_readPayloadLength == 126)
+ {
+ _readPayloadLength = _readBuffer.b.getShort(_readBufferPos); // Uses network byte order.
+ if(_readPayloadLength < 0)
+ {
+ _readPayloadLength += 65536;
+ }
+ _readBufferPos += 2;
+ }
+ else if(_readPayloadLength == 127)
+ {
+ long l = _readBuffer.b.getLong(_readBufferPos); // Uses network byte order.
+ _readBufferPos += 8;
+ if(l < 0 || l > Integer.MAX_VALUE)
+ {
+ throw new Ice.ProtocolException("invalid WebSocket payload length: " + l);
+ }
+ _readPayloadLength = (int)l;
+ }
+
+ //
+ // Read the mask if this is an incoming connection.
+ //
+ if(_incoming)
+ {
+ assert(_readBuffer.b.position() - _readBufferPos >= 4); // We must have needed to read the mask.
+ for(int i = 0; i < 4; ++i)
+ {
+ _readMask[i] = _readBuffer.b.get(_readBufferPos++); // Copy the mask.
+ }
+ }
+
+ switch(_readOpCode)
+ {
+ case OP_TEXT: // Text frame
+ {
+ throw new Ice.ProtocolException("text frames not supported");
+ }
+ case OP_CONT: // Continuation frame
+ case OP_DATA: // Data frame
+ {
+ if(_instance.traceLevel() >= 2)
+ {
+ _instance.logger().trace(_instance.traceCategory(), "received " + protocol() +
+ (_readOpCode == OP_DATA ? " data" : " continuation") +
+ " frame with payload length of " + _readPayloadLength + " bytes\n" +
+ toString());
+ }
+
+ if(_readPayloadLength <= 0)
+ {
+ throw new Ice.ProtocolException("payload length is 0");
+ }
+ _readState = ReadStatePayload;
+ assert(buf.b.hasRemaining());
+ _readFrameStart = buf.b.position();
+ break;
+ }
+ case OP_CLOSE: // Connection close
+ {
+ if(_instance.traceLevel() >= 2)
+ {
+ _instance.logger().trace(_instance.traceCategory(), "received " + protocol() +
+ " connection close frame\n" + toString());
+ }
+
+ int s = _nextState == StateOpened ? _state : _nextState;
+ if(s == StateClosingRequestPending)
+ {
+ //
+ // If we receive a close frame while we were actually
+ // waiting to send one, change the role and send a
+ // close frame response.
+ //
+ if(!_closingInitiator)
+ {
+ _closingInitiator = true;
+ }
+ if(_state == StateClosingRequestPending)
+ {
+ _state = StateClosingResponsePending;
+ }
+ else
+ {
+ _nextState = StateClosingResponsePending;
+ }
+ return false; // No longer interested in reading
+ }
+ else
+ {
+ throw new Ice.ConnectionLostException();
+ }
+ }
+ case OP_PING:
+ {
+ if(_instance.traceLevel() >= 2)
+ {
+ _instance.logger().trace(_instance.traceCategory(),
+ "received " + protocol() + " connection ping frame\n" + toString());
+ }
+ _readState = ReadStateControlFrame;
+ break;
+ }
+ case OP_PONG: // Pong
+ {
+ if(_instance.traceLevel() >= 2)
+ {
+ _instance.logger().trace(_instance.traceCategory(),
+ "received " + protocol() + " connection pong frame\n" + toString());
+ }
+ _readState = ReadStateControlFrame;
+ break;
+ }
+ default:
+ {
+ throw new Ice.ProtocolException("unsupported opcode: " + _readOpCode);
+ }
+ }
+ }
+
+ if(_readState == ReadStateControlFrame)
+ {
+ if(_readPayloadLength > 0 && !readBuffered(_readPayloadLength))
+ {
+ return true;
+ }
+
+ if(_readPayloadLength > 0 && _readOpCode == OP_PING)
+ {
+ _pingPayload = new byte[_readPayloadLength];
+ if(_readBuffer.b.hasArray())
+ {
+ System.arraycopy(_readBuffer.b.array(), _readBuffer.b.arrayOffset() + _readBufferPos,
+ _pingPayload, 0, _readPayloadLength);
+ }
+ else
+ {
+ for(int i = 0; i < _readPayloadLength; ++i)
+ {
+ _pingPayload[i] = _readBuffer.b.get(_readBufferPos + i);
+ }
+ }
+ }
+
+ _readBufferPos += _readPayloadLength;
+ _readPayloadLength = 0;
+
+ if(_readOpCode == OP_PING)
+ {
+ if(_state == StateOpened)
+ {
+ _state = StatePongPending; // Send pong frame now
+ }
+ else if(_nextState < StatePongPending)
+ {
+ _nextState = StatePongPending; // Send pong frame next
+ }
+ }
+
+ //
+ // We've read the payload of the PING/PONG frame, we're ready
+ // to read a new frame.
+ //
+ _readState = ReadStateOpcode;
+ }
+
+ if(_readState == ReadStatePayload)
+ {
+ //
+ // This must be assigned before the check for the buffer. If the buffer is empty
+ // or already read, postRead will return false.
+ //
+ _readStart = buf.b.position();
+
+ if(buf.empty() || !buf.b.hasRemaining())
+ {
+ return false;
+ }
+
+ int n = Math.min(_readBuffer.b.position() - _readBufferPos, buf.b.remaining());
+ if(n > _readPayloadLength)
+ {
+ n = _readPayloadLength;
+ }
+ if(n > 0)
+ {
+ if(buf.b.hasArray() && _readBuffer.b.hasArray())
+ {
+ System.arraycopy(_readBuffer.b.array(), _readBuffer.b.arrayOffset() + _readBufferPos,
+ buf.b.array(), buf.b.arrayOffset() + buf.b.position(), n);
+ buf.b.position(buf.b.position() + n);
+ }
+ else
+ {
+ for(int i = 0; i < n; ++i)
+ {
+ buf.b.put(_readBuffer.b.get(_readBufferPos + i));
+ }
+ }
+ _readBufferPos += n;
+ }
+
+ //
+ // Continue reading if we didn't read the full message or there's more payload data to read.
+ //
+ return buf.b.hasRemaining() && n < _readPayloadLength;
+ }
+ }
+ }
+
+ private boolean postRead(Buffer buf)
+ {
+ if(_readState != ReadStatePayload)
+ {
+ return _readStart < _readBuffer.b.position(); // Returns true if data was read.
+ }
+
+ if(_readStart == buf.b.position())
+ {
+ return false; // Nothing was read or nothing to read.
+ }
+ assert(_readStart < buf.b.position());
+
+ if(_incoming)
+ {
+ //
+ // Unmask the data we just read.
+ //
+ final int pos = buf.b.position();
+ if(buf.b.hasArray())
+ {
+ byte[] arr = buf.b.array();
+ int offset = buf.b.arrayOffset();
+ for(int n = _readStart; n < pos; ++n)
+ {
+ arr[n + offset] = (byte)(arr[n + offset] ^ _readMask[(n - _readFrameStart) % 4]);
+ }
+ }
+ else
+ {
+ for(int n = _readStart; n < pos; ++n)
+ {
+ final byte b = (byte)(buf.b.get(n) ^ _readMask[(n - _readFrameStart) % 4]);
+ buf.b.put(n, b);
+ }
+ }
+ }
+
+ _readPayloadLength -= buf.b.position() - _readStart;
+ _readStart = buf.b.position();
+ if(_readPayloadLength == 0)
+ {
+ //
+ // We've read the complete payload, we're ready to read a new frame.
+ //
+ _readState = ReadStateOpcode;
+ }
+ return buf.b.hasRemaining();
+ }
+
+ private boolean preWrite(Buffer buf)
+ {
+ if(_writeState == WriteStateHeader)
+ {
+ if(_state == StateOpened)
+ {
+ if(buf.empty() || !buf.b.hasRemaining())
+ {
+ return false;
+ }
+
+ assert(buf.b.position() == 0);
+ prepareWriteHeader((byte)OP_DATA, buf.size());
+
+ _writeState = WriteStatePayload;
+ }
+ else if(_state == StatePingPending)
+ {
+ prepareWriteHeader((byte)OP_PING, 0); // Don't send any payload
+
+ _writeState = WriteStateControlFrame;
+ _writeBuffer.b.flip();
+ }
+ else if(_state == StatePongPending)
+ {
+ prepareWriteHeader((byte)OP_PONG, _pingPayload.length);
+ if(_pingPayload.length > _writeBuffer.b.remaining())
+ {
+ final int pos = _writeBuffer.b.position();
+ _writeBuffer.resize(pos + _pingPayload.length, false);
+ _writeBuffer.b.position(pos);
+ }
+ _writeBuffer.b.put(_pingPayload);
+ _pingPayload = new byte[0];
+
+ _writeState = WriteStateControlFrame;
+ _writeBuffer.b.flip();
+ }
+ else if((_state == StateClosingRequestPending && !_closingInitiator) ||
+ (_state == StateClosingResponsePending && _closingInitiator))
+ {
+ prepareWriteHeader((byte)OP_CLOSE, 2);
+
+ // Write closing reason
+ _writeBuffer.b.putShort((short)_closingReason);
+
+ if(!_incoming)
+ {
+ byte b;
+ int pos = _writeBuffer.b.position() - 2;
+ b = (byte)(_writeBuffer.b.get(pos) ^ _writeMask[0]);
+ _writeBuffer.b.put(pos, b);
+ pos++;
+ b = (byte)(_writeBuffer.b.get(pos) ^ _writeMask[1]);
+ _writeBuffer.b.put(pos, b);
+ }
+
+ _writeState = WriteStateControlFrame;
+ _writeBuffer.b.flip();
+ }
+ else
+ {
+ assert(_state != StateClosed);
+ return false; // Nothing to write in this state
+ }
+
+ _writePayloadLength = 0;
+ }
+
+ if(_writeState == WriteStatePayload)
+ {
+ //
+ // For an outgoing connection, each message must be masked with a random
+ // 32-bit value, so we copy the entire message into the internal buffer
+ // for writing. For incoming connections, we just copy the start of the
+ // message in the internal buffer after the hedaer. If the message is
+ // larger, the reminder is sent directly from the message buffer to avoid
+ // copying.
+ //
+
+ if(!_incoming && (_writePayloadLength == 0 || !_writeBuffer.b.hasRemaining()))
+ {
+ if(!_writeBuffer.b.hasRemaining())
+ {
+ _writeBuffer.b.position(0);
+ }
+
+ int n = buf.b.position();
+ final int sz = buf.size();
+ if(buf.b.hasArray() && _writeBuffer.b.hasArray())
+ {
+ int pos = _writeBuffer.b.position();
+ final int count = Math.min(sz - n, _writeBuffer.b.remaining());
+ final byte[] src = buf.b.array();
+ final int srcOff = buf.b.arrayOffset();
+ final byte[] dest = _writeBuffer.b.array();
+ final int destOff = _writeBuffer.b.arrayOffset();
+ for(int i = 0; i < count; ++i, ++n, ++pos)
+ {
+ dest[destOff + pos] = (byte)(src[srcOff + n] ^ _writeMask[n % 4]);
+ }
+ _writeBuffer.b.position(pos);
+ }
+ else
+ {
+ for(; n < sz && _writeBuffer.b.hasRemaining(); ++n)
+ {
+ final byte b = (byte)(buf.b.get(n) ^ _writeMask[n % 4]);
+ _writeBuffer.b.put(b);
+ }
+ }
+ _writePayloadLength = n;
+ _writeBuffer.b.flip();
+ }
+ else if(_writePayloadLength == 0)
+ {
+ assert(_incoming);
+ if(_writeBuffer.b.hasRemaining())
+ {
+ assert(buf.b.position() == 0);
+ int n = _writeBuffer.b.remaining();
+ if(buf.b.remaining() > n)
+ {
+ int limit = buf.b.limit();
+ buf.b.limit(n);
+ _writeBuffer.b.put(buf.b);
+ buf.b.limit(limit);
+ _writePayloadLength = n;
+ }
+ else
+ {
+ _writePayloadLength = buf.b.remaining();
+ _writeBuffer.b.put(buf.b);
+ }
+ buf.b.position(0);
+ }
+ _writeBuffer.b.flip();
+ }
+ return true;
+ }
+ else if(_writeState == WriteStateControlFrame)
+ {
+ return _writeBuffer.b.hasRemaining();
+ }
+ else
+ {
+ assert(_writeState == WriteStateFlush);
+ return true;
+ }
+ }
+
+ private boolean postWrite(Buffer buf, int status)
+ {
+ if(_state > StateOpened && _writeState == WriteStateControlFrame)
+ {
+ if(!_writeBuffer.b.hasRemaining())
+ {
+ if(_state == StatePingPending)
+ {
+ if(_instance.traceLevel() >= 2)
+ {
+ _instance.logger().trace(_instance.traceCategory(),
+ "sent " + protocol() + " connection ping frame\n" + toString());
+ }
+ }
+ else if(_state == StatePongPending)
+ {
+ if(_instance.traceLevel() >= 2)
+ {
+ _instance.logger().trace(_instance.traceCategory(),
+ "sent " + protocol() + " connection pong frame\n" + toString());
+ }
+ }
+ else if((_state == StateClosingRequestPending && !_closingInitiator) ||
+ (_state == StateClosingResponsePending && _closingInitiator))
+ {
+ if(_instance.traceLevel() >= 2)
+ {
+ _instance.logger().trace(_instance.traceCategory(),
+ "sent " + protocol() + " connection close frame\n" + toString());
+ }
+
+ if(_state == StateClosingRequestPending && !_closingInitiator)
+ {
+ _writeState = WriteStateHeader;
+ _state = StateClosingResponsePending;
+ return false;
+ }
+ else
+ {
+ throw new Ice.ConnectionLostException();
+ }
+ }
+ else if(_state == StateClosed)
+ {
+ return false;
+ }
+
+ _state = _nextState;
+ _nextState = StateOpened;
+ _writeState = WriteStateHeader;
+ }
+ else
+ {
+ return status == SocketOperation.None;
+ }
+ }
+
+ if((!_incoming || buf.b.position() == 0) && _writePayloadLength > 0)
+ {
+ if(!_writeBuffer.b.hasRemaining())
+ {
+ buf.b.position(_writePayloadLength);
+ }
+ }
+
+ if(status == SocketOperation.Write && !buf.b.hasRemaining() && !_writeBuffer.b.hasRemaining())
+ {
+ //
+ // Our buffers are empty but the delegate needs another call to write().
+ //
+ _writeState = WriteStateFlush;
+ return false;
+ }
+ else if(!buf.b.hasRemaining())
+ {
+ _writeState = WriteStateHeader;
+ if(_state == StatePingPending ||
+ _state == StatePongPending ||
+ (_state == StateClosingRequestPending && !_closingInitiator) ||
+ (_state == StateClosingResponsePending && _closingInitiator))
+ {
+ return true;
+ }
+ }
+ else if(_state == StateOpened)
+ {
+ return status == SocketOperation.None;
+ }
+
+ return false;
+ }
+
+ private boolean readBuffered(int sz)
+ {
+ if(_readBufferPos == _readBuffer.b.position())
+ {
+ _readBuffer.resize(_readBufferSize, true);
+ _readBufferPos = 0;
+ _readBuffer.b.position(0);
+ }
+ else
+ {
+ final int available = _readBuffer.b.position() - _readBufferPos;
+ if(available < sz)
+ {
+ if(_readBufferPos > 0)
+ {
+ _readBuffer.b.limit(_readBuffer.b.position());
+ _readBuffer.b.position(_readBufferPos);
+ _readBuffer.b.compact();
+ assert(_readBuffer.b.position() == available);
+ }
+ _readBuffer.resize(Math.max(_readBufferSize, sz), true);
+ _readBufferPos = 0;
+ _readBuffer.b.position(available);
+ }
+ }
+
+ _readStart = _readBuffer.b.position();
+ if(_readBufferPos + sz > _readBuffer.b.position())
+ {
+ return false; // Not enough read.
+ }
+ assert(_readBuffer.b.position() > _readBufferPos);
+ return true;
+ }
+
+ private void prepareWriteHeader(byte opCode, int payloadLength)
+ {
+ //
+ // We need to prepare the frame header.
+ //
+ _writeBuffer.resize(_writeBufferSize, false);
+ _writeBuffer.b.limit(_writeBufferSize);
+ _writeBuffer.b.position(0);
+
+ //
+ // Set the opcode - this is the one and only data frame.
+ //
+ _writeBuffer.b.put((byte)(opCode | FLAG_FINAL));
+
+ //
+ // Set the payload length.
+ //
+ if(payloadLength <= 125)
+ {
+ _writeBuffer.b.put((byte)payloadLength);
+ }
+ else if(payloadLength > 125 && payloadLength <= 65535)
+ {
+ //
+ // Use an extra 16 bits to encode the payload length.
+ //
+ _writeBuffer.b.put((byte)126);
+ _writeBuffer.b.putShort((short)payloadLength);
+ }
+ else if(payloadLength > 65535)
+ {
+ //
+ // Use an extra 64 bits to encode the payload length.
+ //
+ _writeBuffer.b.put((byte)127);
+ _writeBuffer.b.putLong(payloadLength);
+ }
+
+ if(!_incoming)
+ {
+ //
+ // Add a random 32-bit mask to every outgoing frame, copy the payload data,
+ // and apply the mask.
+ //
+ _writeBuffer.b.put(1, (byte)(_writeBuffer.b.get(1) | FLAG_MASKED));
+ _rand.nextBytes(_writeMask);
+ _writeBuffer.b.put(_writeMask);
+ }
+ }
+
+ private ProtocolInstance _instance;
+ private Transceiver _delegate;
+ private String _host;
+ private String _resource;
+ private boolean _incoming;
+ private ReadyCallback _readyCallback;
+
+ private static final int StateInitializeDelegate = 0;
+ private static final int StateConnected = 1;
+ private static final int StateUpgradeRequestPending = 2;
+ private static final int StateUpgradeResponsePending = 3;
+ private static final int StateOpened = 4;
+ private static final int StatePingPending = 5;
+ private static final int StatePongPending = 6;
+ private static final int StateClosingRequestPending = 7;
+ private static final int StateClosingResponsePending = 8;
+ private static final int StateClosed = 9;
+
+ private int _state;
+ private int _nextState;
+
+ private HttpParser _parser;
+ private String _key;
+
+ private static final int ReadStateOpcode = 0;
+ private static final int ReadStateHeader = 1;
+ private static final int ReadStateControlFrame = 2;
+ private static final int ReadStatePayload = 3;
+
+ private int _readState;
+ private Buffer _readBuffer;
+ private int _readBufferPos;
+ private int _readBufferSize;
+
+ private boolean _readLastFrame;
+ private int _readOpCode;
+ private int _readHeaderLength;
+ private int _readPayloadLength;
+ private int _readStart;
+ private int _readFrameStart;
+ private byte[] _readMask;
+
+ private static final int WriteStateHeader = 0;
+ private static final int WriteStatePayload = 1;
+ private static final int WriteStateControlFrame = 2;
+ private static final int WriteStateFlush = 3;
+
+ private int _writeState;
+ private Buffer _writeBuffer;
+ private int _writeBufferSize;
+ private byte[] _writeMask;
+ private int _writePayloadLength;
+
+ private boolean _closingInitiator;
+ private int _closingReason;
+
+ private byte[] _pingPayload;
+
+ private java.util.Random _rand;
+
+ //
+ // WebSocket opcodes
+ //
+ final static private int OP_CONT = 0x0; // Continuation frame
+ final static private int OP_TEXT = 0x1; // Text frame
+ final static private int OP_DATA = 0x2; // Data frame
+ @SuppressWarnings("unused")
+ final static private int OP_RES_0x3 = 0x3; // Reserved
+ @SuppressWarnings("unused")
+ final static private int OP_RES_0x4 = 0x4; // Reserved
+ @SuppressWarnings("unused")
+ final static private int OP_RES_0x5 = 0x5; // Reserved
+ @SuppressWarnings("unused")
+ final static private int OP_RES_0x6 = 0x6; // Reserved
+ @SuppressWarnings("unused")
+ final static private int OP_RES_0x7 = 0x7; // Reserved
+ final static private int OP_CLOSE = 0x8; // Connection close
+ final static private int OP_PING = 0x9; // Ping
+ final static private int OP_PONG = 0xA; // Pong
+ @SuppressWarnings("unused")
+ final static private int OP_RES_0xB = 0xB; // Reserved
+ @SuppressWarnings("unused")
+ final static private int OP_RES_0xC = 0xC; // Reserved
+ @SuppressWarnings("unused")
+ final static private int OP_RES_0xD = 0xD; // Reserved
+ @SuppressWarnings("unused")
+ final static private int OP_RES_0xE = 0xE; // Reserved
+ @SuppressWarnings("unused")
+ final static private int OP_RES_0xF = 0xF; // Reserved
+ final static private int FLAG_FINAL = 0x80; // Last frame
+ final static private int FLAG_MASKED = 0x80; // Payload is masked
+
+ final static private int CLOSURE_NORMAL = 1000;
+ final static private int CLOSURE_SHUTDOWN = 1001;
+ final static private int CLOSURE_PROTOCOL_ERROR = 1002;
+ final static private int CLOSURE_TOO_BIG = 1009;
+
+ final static private String _iceProtocol = "ice.zeroc.com";
+ final static private String _wsUUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
+ final static java.nio.charset.Charset _ascii = java.nio.charset.Charset.forName("US-ASCII");
+}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/WebSocketException.java b/java-compat/src/Ice/src/main/java/IceInternal/WebSocketException.java
new file mode 100644
index 00000000000..cee046461cb
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceInternal/WebSocketException.java
@@ -0,0 +1,28 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+final class WebSocketException extends java.lang.RuntimeException
+{
+ public WebSocketException(String reason)
+ {
+ super(reason);
+ }
+
+ public WebSocketException(String reason, Throwable cause)
+ {
+ super(reason, cause);
+ }
+
+ public WebSocketException(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceMX/MetricsHelper.java b/java-compat/src/Ice/src/main/java/IceMX/MetricsHelper.java
new file mode 100644
index 00000000000..84dfc57d19f
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceMX/MetricsHelper.java
@@ -0,0 +1,188 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceMX;
+
+public class MetricsHelper<T>
+{
+ public static class AttributeResolver
+ {
+ private abstract class Resolver
+ {
+ abstract Object resolve(Object obj) throws Exception;
+
+ String resolveImpl(Object obj)
+ {
+ try
+ {
+ Object result = resolve(obj);
+ if(result != null)
+ {
+ return result.toString();
+ }
+ return "";
+ }
+ catch(IllegalArgumentException ex)
+ {
+ throw ex;
+ }
+ catch(Exception ex)
+ {
+ ex.printStackTrace();
+ assert(false);
+ return null;
+ }
+ }
+ }
+
+ protected
+ AttributeResolver()
+ {
+ }
+
+ public String
+ resolve(MetricsHelper<?> helper, String attribute)
+ {
+ Resolver resolver = _attributes.get(attribute);
+ if(resolver == null)
+ {
+ if(attribute.equals("none"))
+ {
+ return "";
+ }
+ String v = helper.defaultResolve(attribute);
+ if(v != null)
+ {
+ return v;
+ }
+ throw new IllegalArgumentException(attribute);
+ }
+ return resolver.resolveImpl(helper);
+ }
+
+ public void
+ add(final String name, final java.lang.reflect.Method method)
+ {
+ _attributes.put(name, new Resolver()
+ {
+ @Override
+ public Object
+ resolve(Object obj) throws Exception
+ {
+ return method.invoke(obj);
+ }
+ });
+ }
+
+ public void
+ add(final String name, final java.lang.reflect.Field field)
+ {
+ _attributes.put(name, new Resolver()
+ {
+ @Override
+ public Object
+ resolve(Object obj) throws Exception
+ {
+ return getField(name, field, obj);
+ }
+ });
+ }
+
+ public void
+ add(final String name, final java.lang.reflect.Method method, final java.lang.reflect.Field field)
+ {
+ _attributes.put(name, new Resolver()
+ {
+ @Override
+ public Object
+ resolve(Object obj) throws Exception
+ {
+ return getField(name, field, method.invoke(obj));
+ }
+ });
+ }
+
+ public void
+ add(final String name, final java.lang.reflect.Method method, final java.lang.reflect.Method subMethod)
+ {
+ _attributes.put(name, new Resolver()
+ {
+ @Override
+ public Object
+ resolve(Object obj) throws Exception
+ {
+ Object o = method.invoke(obj);
+ if(o != null)
+ {
+ return subMethod.invoke(o);
+ }
+ throw new IllegalArgumentException(name);
+ }
+ });
+ }
+
+ private Object getField(String name, java.lang.reflect.Field field, Object o)
+ throws IllegalArgumentException, IllegalAccessException
+ {
+ while(o != null)
+ {
+ try
+ {
+ return field.get(o);
+ }
+ catch(IllegalArgumentException ex)
+ {
+ // If we're dealing with an endpoint/connection information class,
+ // check if the field is from the underlying info objects.
+ if(o instanceof Ice.EndpointInfo)
+ {
+ o = ((Ice.EndpointInfo)o).underlying;
+ }
+ else if(o instanceof Ice.ConnectionInfo)
+ {
+ o = ((Ice.ConnectionInfo)o).underlying;
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ }
+ throw new IllegalArgumentException(name);
+ }
+
+ private java.util.Map<String, Resolver> _attributes = new java.util.HashMap<String, Resolver>();
+ }
+
+ protected
+ MetricsHelper(AttributeResolver attributes)
+ {
+ _attributes = attributes;
+ }
+
+ public String
+ resolve(String attribute)
+ {
+ return _attributes.resolve(this, attribute);
+ }
+
+ public void
+ initMetrics(T metrics)
+ {
+ // Override in specialized helpers.
+ }
+
+ protected String
+ defaultResolve(String attribute)
+ {
+ return null;
+ }
+
+ private AttributeResolver _attributes;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceMX/Observer.java b/java-compat/src/Ice/src/main/java/IceMX/Observer.java
new file mode 100644
index 00000000000..deec790deff
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceMX/Observer.java
@@ -0,0 +1,136 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceMX;
+
+import IceInternal.MetricsMap;
+
+public class Observer<T extends Metrics> extends IceUtilInternal.StopWatch implements Ice.Instrumentation.Observer
+{
+ public interface MetricsUpdate<T>
+ {
+ void update(T m);
+ }
+
+ @Override
+ public void
+ attach()
+ {
+ if(!isStarted())
+ {
+ start();
+ }
+ }
+
+ @Override
+ public void
+ detach()
+ {
+ long lifetime = _previousDelay + stop();
+ for(MetricsMap<T>.Entry e : _objects)
+ {
+ e.detach(lifetime);
+ }
+ }
+
+ @Override
+ public void
+ failed(String exceptionName)
+ {
+ for(MetricsMap<T>.Entry e : _objects)
+ {
+ e.failed(exceptionName);
+ }
+ }
+
+ public void
+ forEach(MetricsUpdate<T> u)
+ {
+ for(MetricsMap<T>.Entry e : _objects)
+ {
+ e.execute(u);
+ }
+ }
+
+ public void
+ init(MetricsHelper<T> helper, java.util.List<MetricsMap<T>.Entry> objects, Observer<T> previous)
+ {
+ _objects = objects;
+
+ if(previous == null)
+ {
+ return;
+ }
+
+ _previousDelay = previous._previousDelay + previous.delay();
+
+ //
+ // Detach entries from previous observer which are no longer
+ // attached to this new observer.
+ //
+ for(MetricsMap<T>.Entry p : previous._objects)
+ {
+ if(!_objects.contains(p))
+ {
+ p.detach(_previousDelay);
+ }
+ }
+ }
+
+ public <S extends Metrics, ObserverImpl extends Observer<S>> ObserverImpl
+ getObserver(String mapName, MetricsHelper<S> helper, Class<S> mcl, Class<ObserverImpl> ocl)
+ {
+ java.util.List<MetricsMap<S>.Entry> metricsObjects = null;
+ for(MetricsMap<T>.Entry entry : _objects)
+ {
+ MetricsMap<S>.Entry e = entry.getMatching(mapName, helper, mcl);
+ if(e != null)
+ {
+ if(metricsObjects == null)
+ {
+ metricsObjects = new java.util.ArrayList<MetricsMap<S>.Entry>(_objects.size());
+ }
+ metricsObjects.add(e);
+ }
+ }
+
+ if(metricsObjects == null)
+ {
+ return null;
+ }
+
+ try
+ {
+ ObserverImpl obsv = ocl.newInstance();
+ obsv.init(helper, metricsObjects, null);
+ return obsv;
+ }
+ catch(Exception ex)
+ {
+ assert(false);
+ return null;
+ }
+ }
+
+ public MetricsMap<T>.Entry
+ getEntry(MetricsMap<?> map)
+ {
+ for(MetricsMap<T>.Entry e : _objects)
+ {
+ if(e.getMap() == map)
+ {
+ return e;
+ }
+ }
+ return null;
+ }
+
+ private java.util.List<MetricsMap<T>.Entry> _objects;
+ private long _previousDelay = 0;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceMX/ObserverFactory.java b/java-compat/src/Ice/src/main/java/IceMX/ObserverFactory.java
new file mode 100644
index 00000000000..ca06b0a8c00
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceMX/ObserverFactory.java
@@ -0,0 +1,142 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceMX;
+
+import IceInternal.MetricsMap;
+
+public class ObserverFactory<T extends Metrics, O extends Observer<T>>
+{
+ public
+ ObserverFactory(IceInternal.MetricsAdminI metrics, String name, Class<T> cl)
+ {
+ _metrics = metrics;
+ _name = name;
+ _class = cl;
+ _metrics.registerMap(name, _class, new Runnable()
+ {
+ @Override
+ public void
+ run()
+ {
+ update();
+ }
+ });
+ }
+
+ public void
+ destroy()
+ {
+ if(_metrics != null)
+ {
+ _metrics.unregisterMap(_name);
+ }
+ }
+
+ public O
+ getObserver(MetricsHelper<T> helper, Class<O> cl)
+ {
+ return getObserver(helper, null, cl);
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized O
+ getObserver(MetricsHelper<T> helper, Object observer, Class<O> cl)
+ {
+ O old = null;
+ try
+ {
+ old = (O)observer;
+ }
+ catch(ClassCastException ex)
+ {
+ }
+ java.util.List<MetricsMap<T>.Entry> metricsObjects = null;
+ for(MetricsMap<T> m : _maps)
+ {
+ MetricsMap<T>.Entry e = m.getMatching(helper, old != null ? old.getEntry(m) : null);
+ if(e != null)
+ {
+ if(metricsObjects == null)
+ {
+ metricsObjects = new java.util.ArrayList<MetricsMap<T>.Entry>(_maps.size());
+ }
+ metricsObjects.add(e);
+ }
+ }
+
+ if(metricsObjects == null)
+ {
+ if(old != null)
+ {
+ old.detach();
+ }
+ return null;
+ }
+
+ O obsv;
+ try
+ {
+ obsv = cl.newInstance();
+ }
+ catch(Exception ex)
+ {
+ assert(false);
+ return null;
+ }
+ obsv.init(helper, metricsObjects, old);
+ return obsv;
+ }
+
+ public <S extends IceMX.Metrics> void
+ registerSubMap(String subMap, Class<S> cl, java.lang.reflect.Field field)
+ {
+ _metrics.registerSubMap(_name, subMap, cl, field);
+ }
+
+ public boolean
+ isEnabled()
+ {
+ return _enabled;
+ }
+
+ public void
+ update()
+ {
+ Runnable updater;
+ synchronized(this)
+ {
+ _maps.clear();
+ for(MetricsMap<T> m : _metrics.getMaps(_name, _class))
+ {
+ _maps.add(m);
+ }
+ _enabled = !_maps.isEmpty();
+ updater = _updater;
+ }
+
+ if(updater != null)
+ {
+ updater.run();
+ }
+ }
+
+ public synchronized void
+ setUpdater(Runnable updater)
+ {
+ _updater = updater;
+ }
+
+ private final IceInternal.MetricsAdminI _metrics;
+ private final String _name;
+ private final Class<T> _class;
+ private java.util.List<MetricsMap<T>> _maps = new java.util.ArrayList<MetricsMap<T>>();
+ private volatile boolean _enabled;
+ private Runnable _updater;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceMX/ObserverFactoryWithDelegate.java b/java-compat/src/Ice/src/main/java/IceMX/ObserverFactoryWithDelegate.java
new file mode 100644
index 00000000000..9e0e01c2949
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceMX/ObserverFactoryWithDelegate.java
@@ -0,0 +1,48 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceMX;
+
+public class ObserverFactoryWithDelegate<T extends Metrics,
+ OImpl extends ObserverWithDelegate<T, O>,
+ O extends Ice.Instrumentation.Observer>
+ extends ObserverFactory<T, OImpl>
+{
+ public
+ ObserverFactoryWithDelegate(IceInternal.MetricsAdminI metrics, String name, Class<T> cl)
+ {
+ super(metrics, name, cl);
+ }
+
+ @SuppressWarnings("unchecked")
+ public O
+ getObserver(MetricsHelper<T> helper, Class<OImpl> cl, O delegate)
+ {
+ OImpl o = super.getObserver(helper, cl);
+ if(o != null)
+ {
+ o.setDelegate(delegate);
+ return (O)o;
+ }
+ return delegate;
+ }
+
+ @SuppressWarnings("unchecked")
+ public O
+ getObserver(MetricsHelper<T> helper, Object observer, Class<OImpl> cl, O delegate)
+ {
+ OImpl o = super.getObserver(helper, observer, cl);
+ if(o != null)
+ {
+ o.setDelegate(delegate);
+ return (O)o;
+ }
+ return delegate;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceMX/ObserverWithDelegate.java b/java-compat/src/Ice/src/main/java/IceMX/ObserverWithDelegate.java
new file mode 100644
index 00000000000..94b09bb9821
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceMX/ObserverWithDelegate.java
@@ -0,0 +1,74 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceMX;
+
+public class ObserverWithDelegate<T extends Metrics, O extends Ice.Instrumentation.Observer> extends Observer<T>
+{
+ @Override
+ public void
+ attach()
+ {
+ super.attach();
+ if(_delegate != null)
+ {
+ _delegate.attach();
+ }
+ }
+
+ @Override
+ public void
+ detach()
+ {
+ super.detach();
+ if(_delegate != null)
+ {
+ _delegate.detach();
+ }
+ }
+
+ @Override
+ public void
+ failed(String exceptionName)
+ {
+ super.failed(exceptionName);
+ if(_delegate != null)
+ {
+ _delegate.failed(exceptionName);
+ }
+ }
+
+ public O
+ getDelegate()
+ {
+ return _delegate;
+ }
+
+ public void
+ setDelegate(O del)
+ {
+ _delegate = del;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <S extends Metrics, ObserverImpl extends ObserverWithDelegate<S, Obs>,
+ Obs extends Ice.Instrumentation.Observer> Obs
+ getObserver(String mapName, MetricsHelper<S> helper, Class<S> mcl, Class<ObserverImpl> ocl, Obs delegate)
+ {
+ ObserverImpl obsv = super.getObserver(mapName, helper, mcl, ocl);
+ if(obsv != null)
+ {
+ obsv.setDelegate(delegate);
+ return (Obs)obsv;
+ }
+ return delegate;
+ }
+
+ protected O _delegate;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceMX/ObserverWithDelegateI.java b/java-compat/src/Ice/src/main/java/IceMX/ObserverWithDelegateI.java
new file mode 100644
index 00000000000..f146b9f9780
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceMX/ObserverWithDelegateI.java
@@ -0,0 +1,14 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceMX;
+
+public class ObserverWithDelegateI extends ObserverWithDelegate<Metrics, Ice.Instrumentation.Observer>
+{
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/AcceptorI.java b/java-compat/src/Ice/src/main/java/IceSSL/AcceptorI.java
new file mode 100644
index 00000000000..bf21888839e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/AcceptorI.java
@@ -0,0 +1,85 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+final class AcceptorI implements IceInternal.Acceptor
+{
+ @Override
+ public java.nio.channels.ServerSocketChannel fd()
+ {
+ return _delegate.fd();
+ }
+
+ @Override
+ public void setReadyCallback(IceInternal.ReadyCallback callback)
+ {
+ _delegate.setReadyCallback(callback);
+ }
+
+ @Override
+ public void close()
+ {
+ _delegate.close();
+ }
+
+ @Override
+ public IceInternal.EndpointI listen()
+ {
+ _endpoint = _endpoint.endpoint(_delegate.listen());
+ return _endpoint;
+ }
+
+ @Override
+ public IceInternal.Transceiver accept()
+ {
+ //
+ // The plug-in may not be fully initialized.
+ //
+ if(!_instance.initialized())
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plug-in is not initialized";
+ throw ex;
+ }
+
+ return new TransceiverI(_instance, _delegate.accept(), _adapterName, true);
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _delegate.protocol();
+ }
+
+ @Override
+ public String toString()
+ {
+ return _delegate.toString();
+ }
+
+ @Override
+ public String toDetailedString()
+ {
+ return _delegate.toDetailedString();
+ }
+
+ AcceptorI(EndpointI endpoint, Instance instance, IceInternal.Acceptor delegate, String adapterName)
+ {
+ _endpoint = endpoint;
+ _instance = instance;
+ _delegate = delegate;
+ _adapterName = adapterName;
+ }
+
+ private EndpointI _endpoint;
+ private Instance _instance;
+ private IceInternal.Acceptor _delegate;
+ private String _adapterName;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/CertificateVerifier.java b/java-compat/src/Ice/src/main/java/IceSSL/CertificateVerifier.java
new file mode 100644
index 00000000000..4aaa6b91f11
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/CertificateVerifier.java
@@ -0,0 +1,26 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+/**
+ * An application can customize the certificate verification process
+ * by implementing the CertificateVerifier interface.
+ **/
+public interface CertificateVerifier
+{
+ /**
+ * Determines whether a connection should be accepted or rejected.
+ *
+ * @param info The details of the connection.
+ * @return <code>true</code> if the connection should be accepted;
+ * <code>false</code>, otherwise.
+ **/
+ boolean verify(NativeConnectionInfo info);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/ConnectorI.java b/java-compat/src/Ice/src/main/java/IceSSL/ConnectorI.java
new file mode 100644
index 00000000000..d463a89bf3d
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/ConnectorI.java
@@ -0,0 +1,78 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+final class ConnectorI implements IceInternal.Connector
+{
+ @Override
+ public IceInternal.Transceiver connect()
+ {
+ //
+ // The plug-in may not be fully initialized.
+ //
+ if(!_instance.initialized())
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plug-in is not initialized";
+ throw ex;
+ }
+
+ return new TransceiverI(_instance, _delegate.connect(), _host, false);
+ }
+
+ @Override
+ public short type()
+ {
+ return _delegate.type();
+ }
+
+ @Override
+ public String toString()
+ {
+ return _delegate.toString();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return _delegate.hashCode();
+ }
+
+ //
+ // Only for use by EndpointI.
+ //
+ ConnectorI(Instance instance, IceInternal.Connector delegate, String host)
+ {
+ _instance = instance;
+ _delegate = delegate;
+ _host = host;
+ }
+
+ @Override
+ public boolean equals(java.lang.Object obj)
+ {
+ if(!(obj instanceof ConnectorI))
+ {
+ return false;
+ }
+
+ if(this == obj)
+ {
+ return true;
+ }
+
+ ConnectorI p = (ConnectorI)obj;
+ return p._delegate.equals(_delegate);
+ }
+
+ private Instance _instance;
+ private IceInternal.Connector _delegate;
+ private String _host;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/EndpointFactoryI.java b/java-compat/src/Ice/src/main/java/IceSSL/EndpointFactoryI.java
new file mode 100644
index 00000000000..ffe402c6193
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/EndpointFactoryI.java
@@ -0,0 +1,60 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+final class EndpointFactoryI implements IceInternal.EndpointFactory
+{
+ EndpointFactoryI(Instance instance, IceInternal.EndpointFactory delegate)
+ {
+ _instance = instance;
+ _delegate = delegate;
+ }
+
+ @Override
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public IceInternal.EndpointI create(java.util.ArrayList<String> args, boolean oaEndpoint)
+ {
+ return new EndpointI(_instance, _delegate.create(args, oaEndpoint));
+ }
+
+ @Override
+ public IceInternal.EndpointI read(Ice.InputStream s)
+ {
+ return new EndpointI(_instance, _delegate.read(s));
+ }
+
+ @Override
+ public void destroy()
+ {
+ _delegate.destroy();
+ _instance = null;
+ }
+
+ @Override
+ public IceInternal.EndpointFactory clone(IceInternal.ProtocolInstance inst, IceInternal.EndpointFactory delegate)
+ {
+ Instance instance = new Instance(_instance.engine(), inst.type(), inst.protocol());
+ return new EndpointFactoryI(instance, delegate != null ? delegate : _delegate.clone(instance, null));
+ }
+
+ private Instance _instance;
+ private IceInternal.EndpointFactory _delegate;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/EndpointI.java b/java-compat/src/Ice/src/main/java/IceSSL/EndpointI.java
new file mode 100644
index 00000000000..08de48c2f11
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/EndpointI.java
@@ -0,0 +1,260 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+final class EndpointI extends IceInternal.EndpointI
+{
+ public EndpointI(Instance instance, IceInternal.EndpointI delegate)
+ {
+ _instance = instance;
+ _delegate = delegate;
+ }
+
+ @Override
+ public void streamWriteImpl(Ice.OutputStream s)
+ {
+ _delegate.streamWriteImpl(s);
+ }
+
+ //
+ // Return the endpoint information.
+ //
+ @Override
+ public Ice.EndpointInfo getInfo()
+ {
+ IceSSL.EndpointInfo info = new IceSSL.EndpointInfo(_delegate.getInfo(), timeout(), compress())
+ {
+ @Override
+ public short type()
+ {
+ return EndpointI.this.type();
+ }
+
+ @Override
+ public boolean datagram()
+ {
+ return EndpointI.this.datagram();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return EndpointI.this.secure();
+ }
+ };
+ info.compress = info.underlying.compress;
+ info.timeout = info.underlying.timeout;
+ return info;
+ }
+
+ @Override
+ public short type()
+ {
+ return _delegate.type();
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _delegate.protocol();
+ }
+
+ @Override
+ public int timeout()
+ {
+ return _delegate.timeout();
+ }
+
+ @Override
+ public IceInternal.EndpointI timeout(int timeout)
+ {
+ if(timeout == _delegate.timeout())
+ {
+ return this;
+ }
+ else
+ {
+ return new EndpointI(_instance, _delegate.timeout(timeout));
+ }
+ }
+
+ @Override
+ public String connectionId()
+ {
+ return _delegate.connectionId();
+ }
+
+ @Override
+ public IceInternal.EndpointI connectionId(String connectionId)
+ {
+ if(connectionId == _delegate.connectionId())
+ {
+ return this;
+ }
+ else
+ {
+ return new EndpointI(_instance, _delegate.connectionId(connectionId));
+ }
+ }
+
+ @Override
+ public boolean compress()
+ {
+ return _delegate.compress();
+ }
+
+ @Override
+ public IceInternal.EndpointI compress(boolean compress)
+ {
+ if(compress == _delegate.compress())
+ {
+ return this;
+ }
+ else
+ {
+ return new EndpointI(_instance, _delegate.compress(compress));
+ }
+ }
+
+ @Override
+ public boolean datagram()
+ {
+ return _delegate.datagram();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return _delegate.secure();
+ }
+
+ //
+ // Return a server side transceiver for this endpoint, or null if a
+ // transceiver can only be created by an acceptor.
+ //
+ @Override
+ public IceInternal.Transceiver transceiver()
+ {
+ return null;
+ }
+
+ @Override
+ public void connectors_async(Ice.EndpointSelectionType selType, final IceInternal.EndpointI_connectors callback)
+ {
+ Ice.IPEndpointInfo ipInfo = null;
+ for(Ice.EndpointInfo p = _delegate.getInfo(); p != null; p = p.underlying)
+ {
+ if(p instanceof Ice.IPEndpointInfo)
+ {
+ ipInfo = (Ice.IPEndpointInfo)p;
+ }
+ }
+ final String host = ipInfo != null ? ipInfo.host : "";
+ IceInternal.EndpointI_connectors cb = new IceInternal.EndpointI_connectors()
+ {
+ @Override
+ public void connectors(java.util.List<IceInternal.Connector> connectors)
+ {
+ java.util.List<IceInternal.Connector> l = new java.util.ArrayList<IceInternal.Connector>();
+ for(IceInternal.Connector c : connectors)
+ {
+ l.add(new ConnectorI(_instance, c, host));
+ }
+ callback.connectors(l);
+ }
+
+ @Override
+ public void exception(Ice.LocalException ex)
+ {
+ callback.exception(ex);
+ }
+ };
+ _delegate.connectors_async(selType, cb);
+ }
+
+ //
+ // Return an acceptor for this endpoint, or null if no acceptors
+ // is available.
+ //
+ @Override
+ public IceInternal.Acceptor acceptor(String adapterName)
+ {
+ return new AcceptorI(this, _instance, _delegate.acceptor(adapterName), adapterName);
+ }
+
+ public EndpointI endpoint(IceInternal.EndpointI delEndpt)
+ {
+ return new EndpointI(_instance, delEndpt);
+ }
+
+ @Override
+ public java.util.List<IceInternal.EndpointI> expand()
+ {
+ java.util.List<IceInternal.EndpointI> endps = _delegate.expand();
+ java.util.List<IceInternal.EndpointI> l = new java.util.ArrayList<IceInternal.EndpointI>();
+ for(IceInternal.EndpointI e : endps)
+ {
+ l.add(e == _delegate ? this : new EndpointI(_instance, e));
+ }
+ return l;
+ }
+
+ @Override
+ public boolean equivalent(IceInternal.EndpointI endpoint)
+ {
+ if(!(endpoint instanceof EndpointI))
+ {
+ return false;
+ }
+ EndpointI endpointI = (EndpointI)endpoint;
+ return _delegate.equivalent(endpointI._delegate);
+ }
+
+ @Override
+ synchronized public int hashCode()
+ {
+ return _delegate.hashCode();
+ }
+
+ @Override
+ public String options()
+ {
+ return _delegate.options();
+ }
+
+ //
+ // Compare endpoints for sorting purposes
+ //
+ @Override
+ public int compareTo(IceInternal.EndpointI obj) // From java.lang.Comparable
+ {
+ if(!(obj instanceof EndpointI))
+ {
+ return type() < obj.type() ? -1 : 1;
+ }
+
+ EndpointI p = (EndpointI)obj;
+ if(this == p)
+ {
+ return 0;
+ }
+
+ return _delegate.compareTo(p._delegate);
+ }
+
+ @Override
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ return false;
+ }
+
+ private Instance _instance;
+ private IceInternal.EndpointI _delegate;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/Instance.java b/java-compat/src/Ice/src/main/java/IceSSL/Instance.java
new file mode 100644
index 00000000000..53ffac5c29f
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/Instance.java
@@ -0,0 +1,62 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+class Instance extends IceInternal.ProtocolInstance
+{
+ Instance(SSLEngine engine, short type, String protocol)
+ {
+ super(engine.communicator(), type, protocol, true);
+ _engine = engine;
+ }
+
+ SSLEngine engine()
+ {
+ return _engine;
+ }
+
+ int securityTraceLevel()
+ {
+ return _engine.securityTraceLevel();
+ }
+
+ String securityTraceCategory()
+ {
+ return _engine.securityTraceCategory();
+ }
+
+ boolean initialized()
+ {
+ return _engine.initialized();
+ }
+
+ javax.net.ssl.SSLEngine createSSLEngine(boolean incoming, String host, int port)
+ {
+ return _engine.createSSLEngine(incoming, host, port);
+ }
+
+ void traceConnection(String desc, javax.net.ssl.SSLEngine engine, boolean incoming)
+ {
+ _engine.traceConnection(desc, engine, incoming);
+ }
+
+ void verifyPeer(String address, NativeConnectionInfo info, String desc)
+ {
+ _engine.verifyPeer(address, info, desc);
+ }
+
+ void trustManagerFailure(boolean incoming, java.security.cert.CertificateException ex)
+ throws java.security.cert.CertificateException
+ {
+ _engine.trustManagerFailure(incoming, ex);
+ }
+
+ private SSLEngine _engine;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/NativeConnectionInfo.java b/java-compat/src/Ice/src/main/java/IceSSL/NativeConnectionInfo.java
new file mode 100644
index 00000000000..3e726309267
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/NativeConnectionInfo.java
@@ -0,0 +1,28 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+/**
+ *
+ * This class is a native extension of the Slice local class
+ * IceSSL::ConnectionInfo. It provides access to the native Java
+ * certificates.
+ *
+ * @see CertificateVerifier
+ **/
+public class NativeConnectionInfo extends ConnectionInfo
+{
+ /**
+ * The certificate chain. This may be null if the peer did not
+ * supply a certificate. The peer's certificate (if any) is the
+ * first one in the chain.
+ **/
+ public java.security.cert.Certificate[] nativeCerts;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/PasswordCallback.java b/java-compat/src/Ice/src/main/java/IceSSL/PasswordCallback.java
new file mode 100644
index 00000000000..227b7c41361
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/PasswordCallback.java
@@ -0,0 +1,45 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+/**
+ * A password callback is an alternate way to supply the plug-in with
+ * passwords; this avoids using plain text configuration properties.
+ **/
+public interface PasswordCallback
+{
+ /**
+ * Returns the password for the key. If an alias was selected
+ * by setting the <code>IceSSL.Alias</code> property, <code>alias</code>
+ * contains the property's value.
+ *
+ * @param alias The value of the property <code>IceSSL.Alias</code>, if that
+ * property is set; <code>null</code>, otherwise.
+ * @return The password for the key. The return value must not be <code>null</code>.
+ *
+ **/
+ char[] getPassword(String alias);
+
+ /**
+ * Returns the password for validating the truststore.
+ *
+ * @return The password. To skip truststore validation,
+ * return <code>null</code>.
+ **/
+ char[] getTruststorePassword();
+
+ /**
+ * Returns the password for validating the keystore.
+ *
+ * @return The password. To skip keystore validation,
+ * return <code>null</code>.
+ **/
+ char[] getKeystorePassword();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/Plugin.java b/java-compat/src/Ice/src/main/java/IceSSL/Plugin.java
new file mode 100644
index 00000000000..7301c37ed6a
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/Plugin.java
@@ -0,0 +1,94 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+/**
+ * Interface that allows applications to interact with the IceSSL plug-in.
+ **/
+public interface Plugin extends Ice.Plugin
+{
+ /**
+ * Establishes the SSL context. The context must be established before
+ * plug-in is initialized. Therefore, the application must set
+ * the property <code>Ice.InitPlugins</code> to zero, call
+ * <code>setContext</code> to set the context, and finally
+ * invoke {@link PluginManager#initializePlugins}.
+ * <p>
+ * If an application supplies its own SSL context, the
+ * plug-in skips its normal property-based configuration.
+ *
+ * @param context The SSL context for the plug-in.
+ **/
+ void setContext(javax.net.ssl.SSLContext context);
+
+ /**
+ * Returns the SSL context. Use caution when modifying the returned
+ * value: changes made to this value do not affect existing connections.
+ *
+ * @return The SSL context for the plug-in.
+ **/
+ javax.net.ssl.SSLContext getContext();
+
+ /**
+ * Establishes the certificate verifier. This must be
+ * done before any connections are established.
+ *
+ * @param verifier The certificate verifier.
+ **/
+ void setCertificateVerifier(CertificateVerifier verifier);
+
+ /**
+ * Returns the certificate verifier.
+ *
+ * @return The certificate verifier (<code>null</code> if not set).
+ **/
+ CertificateVerifier getCertificateVerifier();
+
+ /**
+ * Establishes the password callback. This must be
+ * done before the plug-in is initialized.
+ *
+ * @param callback The password callback.
+ **/
+ void setPasswordCallback(PasswordCallback callback);
+
+ /**
+ * Returns the password callback.
+ *
+ * @return The password callback (<code>null</code> if not set).
+ **/
+ PasswordCallback getPasswordCallback();
+
+ /**
+ * Supplies an input stream for the keystore. Calling this method
+ * causes IceSSL to ignore the <code>IceSSL.Keystore</code> property.
+ *
+ * @param stream The input stream for the keystore.
+ **/
+ void setKeystoreStream(java.io.InputStream stream);
+
+ /**
+ * Supplies an input stream for the truststore. Calling this method
+ * causes IceSSL to ignore the <code>IceSSL.Truststore</code> property. It is
+ * legal to supply the same input stream as the one for {@link #setKeystoreStream},
+ * in which case IceSSL uses the certificates contained in the keystore.
+ *
+ * @param stream The input stream for the truststore.
+ **/
+ void setTruststoreStream(java.io.InputStream stream);
+
+ /**
+ * Adds an input stream for the random number seed. You may call
+ * this method multiple times if necessary.
+ *
+ * @param stream The input stream for the random number seed.
+ **/
+ void addSeedStream(java.io.InputStream stream);
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/PluginFactory.java b/java-compat/src/Ice/src/main/java/IceSSL/PluginFactory.java
new file mode 100644
index 00000000000..cb8063fe148
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/PluginFactory.java
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+/**
+ * Plug-in factories must implement this interface.
+ **/
+public class PluginFactory implements Ice.PluginFactory
+{
+ /**
+ * Returns a new plug-in.
+ *
+ * @param communicator The communicator for the plug-in.
+ * @param name The name of the plug-in.
+ * @param args The arguments that are specified in the plug-in's configuration.
+ *
+ * @return The new plug-in. <code>null</code> can be returned to indicate
+ * that a general error occurred. Alternatively, <code>create</code> can throw
+ * {@link PluginInitializationException} to provide more detailed information.
+ **/
+ @Override
+ public Ice.Plugin
+ create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginI(communicator);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/PluginI.java b/java-compat/src/Ice/src/main/java/IceSSL/PluginI.java
new file mode 100644
index 00000000000..a57d6e31245
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/PluginI.java
@@ -0,0 +1,108 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+class PluginI implements Plugin
+{
+ public PluginI(Ice.Communicator communicator)
+ {
+ final IceInternal.ProtocolPluginFacade facade = IceInternal.Util.getProtocolPluginFacade(communicator);
+ _engine = new SSLEngine(facade);
+
+ //
+ // Register the endpoint factory. We have to do this now, rather than
+ // in initialize, because the communicator may need to interpret
+ // proxies before the plug-in is fully initialized.
+ //
+
+ // SSL based on TCP
+ IceInternal.EndpointFactory tcp = facade.getEndpointFactory(Ice.TCPEndpointType.value);
+ if(tcp != null)
+ {
+ Instance instance = new Instance(_engine, Ice.SSLEndpointType.value, "ssl");
+ facade.addEndpointFactory(new EndpointFactoryI(instance, tcp.clone(instance, null)));
+ }
+
+ // SSL based on Bluetooth
+ IceInternal.EndpointFactory bluetooth = facade.getEndpointFactory(Ice.BTEndpointType.value);
+ if(bluetooth != null)
+ {
+ Instance instance = new Instance(_engine, Ice.BTSEndpointType.value, "bts");
+ facade.addEndpointFactory(new EndpointFactoryI(instance, bluetooth.clone(instance, null)));
+ }
+ }
+
+ @Override
+ public void initialize()
+ {
+ _engine.initialize();
+ }
+
+ @Override
+ public void destroy()
+ {
+ }
+
+ @Override
+ public void setContext(javax.net.ssl.SSLContext context)
+ {
+ _engine.context(context);
+ }
+
+ @Override
+ public javax.net.ssl.SSLContext getContext()
+ {
+ return _engine.context();
+ }
+
+ @Override
+ public void setCertificateVerifier(CertificateVerifier verifier)
+ {
+ _engine.setCertificateVerifier(verifier);
+ }
+
+ @Override
+ public CertificateVerifier getCertificateVerifier()
+ {
+ return _engine.getCertificateVerifier();
+ }
+
+ @Override
+ public void setPasswordCallback(PasswordCallback callback)
+ {
+ _engine.setPasswordCallback(callback);
+ }
+
+ @Override
+ public PasswordCallback getPasswordCallback()
+ {
+ return _engine.getPasswordCallback();
+ }
+
+ @Override
+ public void setKeystoreStream(java.io.InputStream stream)
+ {
+ _engine.setKeystoreStream(stream);
+ }
+
+ @Override
+ public void setTruststoreStream(java.io.InputStream stream)
+ {
+ _engine.setTruststoreStream(stream);
+ }
+
+ @Override
+ public void addSeedStream(java.io.InputStream stream)
+ {
+ _engine.addSeedStream(stream);
+ }
+
+ private SSLEngine _engine;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/RFC2253.java b/java-compat/src/Ice/src/main/java/IceSSL/RFC2253.java
new file mode 100644
index 00000000000..3d88287ca1b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/RFC2253.java
@@ -0,0 +1,434 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+//
+// See RFC 2253 and RFC 1779.
+//
+class RFC2253
+{
+ static class ParseException extends Ice.LocalException
+ {
+ public ParseException()
+ {
+ }
+
+ public ParseException(String reason)
+ {
+ this.reason = reason;
+ }
+
+ @Override
+ public String
+ ice_id()
+ {
+ return "::RFC2253::ParseException";
+ }
+
+ public String reason;
+ }
+
+ static class RDNPair
+ {
+ String key;
+ String value;
+ }
+
+ static class RDNEntry
+ {
+ java.util.List<RDNPair> rdn = new java.util.LinkedList<RDNPair>();
+ boolean negate = false;
+ }
+
+ static private class ParseState
+ {
+ String data;
+ int pos;
+ }
+
+ public static java.util.List<RDNEntry>
+ parse(String data)
+ throws ParseException
+ {
+ java.util.List<RDNEntry> results = new java.util.LinkedList<RDNEntry>();
+ RDNEntry current = new RDNEntry();
+ ParseState state = new ParseState();
+ state.data = data;
+ state.pos = 0;
+ while(state.pos < state.data.length())
+ {
+ eatWhite(state);
+ if(state.pos < state.data.length() && state.data.charAt(state.pos) == '!')
+ {
+ if(!current.rdn.isEmpty())
+ {
+ throw new ParseException("negation symbol '!' must appear at start of list");
+ }
+ ++state.pos;
+ current.negate = true;
+ }
+ current.rdn.add(parseNameComponent(state));
+ eatWhite(state);
+ if(state.pos < state.data.length() && state.data.charAt(state.pos) == ',')
+ {
+ ++state.pos;
+ }
+ else if(state.pos < state.data.length() && state.data.charAt(state.pos) == ';')
+ {
+ ++state.pos;
+ results.add(current);
+ current = new RDNEntry();
+ }
+ else if(state.pos < state.data.length())
+ {
+ throw new ParseException("expected ',' or ';' at `" + state.data.substring(state.pos) + "'");
+ }
+ }
+ if(!current.rdn.isEmpty())
+ {
+ results.add(current);
+ }
+
+ return results;
+ }
+
+ public static java.util.List<RDNPair>
+ parseStrict(String data)
+ throws ParseException
+ {
+ java.util.List<RDNPair> results = new java.util.LinkedList<RDNPair>();
+ ParseState state = new ParseState();
+ state.data = data;
+ state.pos = 0;
+ while(state.pos < state.data.length())
+ {
+ results.add(parseNameComponent(state));
+ eatWhite(state);
+ if(state.pos < state.data.length() &&
+ (state.data.charAt(state.pos) == ',' || state.data.charAt(state.pos) == ';'))
+ {
+ ++state.pos;
+ }
+ else if(state.pos < state.data.length())
+ {
+ throw new ParseException("expected ',' or ';' at `" + state.data.substring(state.pos) + "'");
+ }
+ }
+ return results;
+ }
+
+ private static RDNPair
+ parseNameComponent(ParseState state)
+ throws ParseException
+ {
+ RDNPair result = parseAttributeTypeAndValue(state);
+ while(state.pos < state.data.length())
+ {
+ eatWhite(state);
+ if(state.pos < state.data.length() && state.data.charAt(state.pos) == '+')
+ {
+ ++state.pos;
+ }
+ else
+ {
+ break;
+ }
+ RDNPair p = parseAttributeTypeAndValue(state);
+ result.value += "+";
+ result.value += p.key;
+ result.value += '=';
+ result.value += p.value;
+ }
+ return result;
+ }
+
+ private static RDNPair
+ parseAttributeTypeAndValue(ParseState state)
+ throws ParseException
+ {
+ RDNPair p = new RDNPair();
+ p.key = parseAttributeType(state);
+ eatWhite(state);
+ if(state.pos >= state.data.length())
+ {
+ throw new ParseException("invalid attribute type/value pair (unexpected end of state.data)");
+ }
+ if(state.data.charAt(state.pos) != '=')
+ {
+ throw new ParseException("invalid attribute type/value pair (missing =)");
+ }
+ ++state.pos;
+ p.value = parseAttributeValue(state);
+ return p;
+ }
+
+ private static String
+ parseAttributeType(ParseState state)
+ throws ParseException
+ {
+ eatWhite(state);
+ if(state.pos >= state.data.length())
+ {
+ throw new ParseException("invalid attribute type (expected end of state.data)");
+ }
+
+ StringBuffer result = new StringBuffer();
+
+ //
+ // RFC 1779.
+ // <key> ::= 1*( <keychar> ) | "OID." <oid> | "oid." <oid>
+ // <oid> ::= <digitString> | <digitstring> "." <oid>
+ // RFC 2253:
+ // attributeType = (ALPHA 1*keychar) | oid
+ // keychar = ALPHA | DIGIT | "-"
+ // oid = 1*DIGIT *("." 1*DIGIT)
+ //
+ // In section 4 of RFC 2253 the document says:
+ // Implementations MUST allow an oid in the attribute type to be
+ // prefixed by one of the character Strings "oid." or "OID.".
+ //
+ // Here we must also check for "oid." and "OID." before parsing
+ // according to the ALPHA KEYCHAR* rule.
+ //
+ // First the OID case.
+ //
+ if(Character.isDigit(state.data.charAt(state.pos)) ||
+ (state.data.length() - state.pos >= 4 && (state.data.substring(state.pos, state.pos + 4).equals("oid.") ||
+ state.data.substring(state.pos, state.pos + 4).equals("OID."))))
+ {
+ if(!Character.isDigit(state.data.charAt(state.pos)))
+ {
+ result.append(state.data.substring(state.pos, state.pos + 4));
+ state.pos += 4;
+ }
+
+ while(true)
+ {
+ // 1*DIGIT
+ while(state.pos < state.data.length() && Character.isDigit(state.data.charAt(state.pos)))
+ {
+ result.append(state.data.charAt(state.pos));
+ ++state.pos;
+ }
+ // "." 1*DIGIT
+ if(state.pos < state.data.length() && state.data.charAt(state.pos) == '.')
+ {
+ result.append(state.data.charAt(state.pos));
+ ++state.pos;
+ // 1*DIGIT must follow "."
+ if(state.pos < state.data.length() && !Character.isDigit(state.data.charAt(state.pos)))
+ {
+ throw new ParseException("invalid attribute type (expected end of state.data)");
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ else if(Character.isUpperCase(state.data.charAt(state.pos)) ||
+ Character.isLowerCase(state.data.charAt(state.pos)))
+ {
+ //
+ // The grammar is wrong in this case. It should be ALPHA
+ // KEYCHAR* otherwise it will not accept "O" as a valid
+ // attribute type.
+ //
+ result.append(state.data.charAt(state.pos));
+ ++state.pos;
+ // 1* KEYCHAR
+ while(state.pos < state.data.length() &&
+ (Character.isDigit(state.data.charAt(state.pos)) ||
+ Character.isUpperCase(state.data.charAt(state.pos)) ||
+ Character.isLowerCase(state.data.charAt(state.pos)) ||
+ state.data.charAt(state.pos) == '-'))
+ {
+ result.append(state.data.charAt(state.pos));
+ ++state.pos;
+ }
+ }
+ else
+ {
+ throw new ParseException("invalid attribute type");
+ }
+ return result.toString();
+ }
+
+ private static String
+ parseAttributeValue(ParseState state)
+ throws ParseException
+ {
+ eatWhite(state);
+ if(state.pos >= state.data.length())
+ {
+ return "";
+ }
+
+ //
+ // RFC 2253
+ // # hexString
+ //
+ StringBuffer result = new StringBuffer();
+ if(state.data.charAt(state.pos) == '#')
+ {
+ result.append(state.data.charAt(state.pos));
+ ++state.pos;
+ while(true)
+ {
+ String h = parseHexPair(state, true);
+ if(h.length() == 0)
+ {
+ break;
+ }
+ result.append(h);
+ }
+ }
+ //
+ // RFC 2253
+ // QUOTATION *( quotechar | pair ) QUOTATION ; only from v2
+ // quotechar = <any character except "\" or QUOTATION >
+ //
+ else if(state.data.charAt(state.pos) == '"')
+ {
+ result.append(state.data.charAt(state.pos));
+ ++state.pos;
+ while(true)
+ {
+ if(state.pos >= state.data.length())
+ {
+ throw new ParseException("invalid attribute value (unexpected end of state.data)");
+ }
+ // final terminating "
+ if(state.data.charAt(state.pos) == '"')
+ {
+ result.append(state.data.charAt(state.pos));
+ ++state.pos;
+ break;
+ }
+ // any character except '\'
+ else if(state.data.charAt(state.pos) != '\\')
+ {
+ result.append(state.data.charAt(state.pos));
+ ++state.pos;
+ }
+ // pair '\'
+ else
+ {
+ result.append(parsePair(state));
+ }
+ }
+ }
+ //
+ // RFC 2253
+ // * (Stringchar | pair)
+ // Stringchar = <any character except one of special, "\" or QUOTATION >
+ //
+ else
+ {
+ while(state.pos < state.data.length())
+ {
+ if(state.data.charAt(state.pos) == '\\')
+ {
+ result.append(parsePair(state));
+ }
+ else if(special.indexOf(state.data.charAt(state.pos)) == -1 && state.data.charAt(state.pos) != '"')
+ {
+ result.append(state.data.charAt(state.pos));
+ ++state.pos;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ return result.toString();
+ }
+
+ //
+ // RFC2253:
+ // pair = "\" ( special | "\" | QUOTATION | hexpair )
+ //
+ private static String
+ parsePair(ParseState state)
+ throws ParseException
+ {
+ String result = "";
+
+ assert(state.data.charAt(state.pos) == '\\');
+ result += state.data.charAt(state.pos);
+ ++state.pos;
+
+ if(state.pos >= state.data.length())
+ {
+ throw new ParseException("invalid escape format (unexpected end of state.data)");
+ }
+
+ if(special.indexOf(state.data.charAt(state.pos)) != -1 || state.data.charAt(state.pos) != '\\' ||
+ state.data.charAt(state.pos) != '"')
+ {
+ result += state.data.charAt(state.pos);
+ ++state.pos;
+ return result;
+ }
+ return parseHexPair(state, false);
+ }
+
+ //
+ // RFC 2253
+ // hexpair = hexchar hexchar
+ //
+ private static String
+ parseHexPair(ParseState state, boolean allowEmpty)
+ throws ParseException
+ {
+ String result = "";
+ if(state.pos < state.data.length() && hexvalid.indexOf(state.data.charAt(state.pos)) != -1)
+ {
+ result += state.data.charAt(state.pos);
+ ++state.pos;
+ }
+ if(state.pos < state.data.length() && hexvalid.indexOf(state.data.charAt(state.pos)) != -1)
+ {
+ result += state.data.charAt(state.pos);
+ ++state.pos;
+ }
+ if(result.length() != 2)
+ {
+ if(allowEmpty && result.length() == 0)
+ {
+ return result;
+ }
+ throw new ParseException("invalid hex format");
+ }
+ return result;
+ }
+
+ //
+ // RFC 2253:
+ //
+ // Implementations MUST allow for space (' ' ASCII 32) characters to be
+ // present between name-component and ',', between attributeTypeAndValue
+ // and '+', between attributeType and '=', and between '=' and
+ // attributeValue. These space characters are ignored when parsing.
+ //
+ private static void
+ eatWhite(ParseState state)
+ {
+ while(state.pos < state.data.length() && state.data.charAt(state.pos) == ' ')
+ {
+ ++state.pos;
+ }
+ }
+
+ private final static String special = ",=+<>#;";
+ private final static String hexvalid = "0123456789abcdefABCDEF";
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/SSLEngine.java b/java-compat/src/Ice/src/main/java/IceSSL/SSLEngine.java
new file mode 100644
index 00000000000..e8da76b6b26
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/SSLEngine.java
@@ -0,0 +1,1314 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.security.cert.*;
+
+class SSLEngine
+{
+ SSLEngine(IceInternal.ProtocolPluginFacade facade)
+ {
+ _communicator = facade.getCommunicator();
+ _logger = _communicator.getLogger();
+ _facade = facade;
+ _securityTraceLevel = _communicator.getProperties().getPropertyAsIntWithDefault("IceSSL.Trace.Security", 0);
+ _securityTraceCategory = "Security";
+ _trustManager = new TrustManager(_communicator);
+ }
+
+ void initialize()
+ {
+ if(_initialized)
+ {
+ return;
+ }
+
+ final String prefix = "IceSSL.";
+ Ice.Properties properties = communicator().getProperties();
+
+ //
+ // Parse the cipher list.
+ //
+ String ciphers = properties.getProperty(prefix + "Ciphers");
+ if(ciphers.length() > 0)
+ {
+ parseCiphers(ciphers);
+ }
+
+ String[] protocols = properties.getPropertyAsList(prefix + "Protocols");
+ if(protocols.length != 0)
+ {
+ java.util.ArrayList<String> l = new java.util.ArrayList<String>();
+ for(String prot : protocols)
+ {
+ String s = prot.toUpperCase();
+ if(s.equals("SSL3") || s.equals("SSLV3"))
+ {
+ l.add("SSLv3");
+ }
+ else if(s.equals("TLS") || s.equals("TLS1") || s.equals("TLSV1") || s.equals("TLS1_0") ||
+ s.equals("TLSV1_0"))
+ {
+ l.add("TLSv1");
+ }
+ else if(s.equals("TLS1_1") || s.equals("TLSV1_1"))
+ {
+ l.add("TLSv1.1");
+ }
+ else if(s.equals("TLS1_2") || s.equals("TLSV1_2"))
+ {
+ l.add("TLSv1.2");
+ }
+ else
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: unrecognized protocol `" + prot + "'";
+ throw e;
+ }
+ }
+ _protocols = new String[l.size()];
+ l.toArray(_protocols);
+ }
+
+ //
+ // CheckCertName determines whether we compare the name in a peer's
+ // certificate against its hostname.
+ //
+ _checkCertName = properties.getPropertyAsIntWithDefault(prefix + "CheckCertName", 0) > 0;
+
+ //
+ // VerifyDepthMax establishes the maximum length of a peer's certificate
+ // chain, including the peer's certificate. A value of 0 means there is
+ // no maximum.
+ //
+ _verifyDepthMax = properties.getPropertyAsIntWithDefault(prefix + "VerifyDepthMax", 3);
+
+ //
+ // VerifyPeer determines whether certificate validation failures abort a connection.
+ //
+ _verifyPeer = properties.getPropertyAsIntWithDefault("IceSSL.VerifyPeer", 2);
+
+ //
+ // Check for a certificate verifier.
+ //
+ final String certVerifierClass = properties.getProperty(prefix + "CertVerifier");
+ if(certVerifierClass.length() > 0)
+ {
+ if(_verifier != null)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: certificate verifier already installed";
+ throw e;
+ }
+
+ Class<?> cls = null;
+ try
+ {
+ cls = _facade.findClass(certVerifierClass);
+ }
+ catch(Throwable ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to load certificate verifier class " + certVerifierClass, ex);
+ }
+
+ try
+ {
+ _verifier = (CertificateVerifier)cls.newInstance();
+ }
+ catch(Throwable ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to instantiate certificate verifier class " + certVerifierClass, ex);
+ }
+ }
+
+ //
+ // Check for a password callback.
+ //
+ final String passwordCallbackClass = properties.getProperty(prefix + "PasswordCallback");
+ if(passwordCallbackClass.length() > 0)
+ {
+ if(_passwordCallback != null)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: password callback already installed";
+ throw e;
+ }
+
+ Class<?> cls = null;
+ try
+ {
+ cls = _facade.findClass(passwordCallbackClass);
+ }
+ catch(Throwable ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to load password callback class " + passwordCallbackClass, ex);
+ }
+
+ try
+ {
+ _passwordCallback = (PasswordCallback)cls.newInstance();
+ }
+ catch(Throwable ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to instantiate password callback class " + passwordCallbackClass, ex);
+ }
+ }
+
+ //
+ // If the user doesn't supply an SSLContext, we need to create one based
+ // on property settings.
+ //
+ if(_context == null)
+ {
+ try
+ {
+ //
+ // Check for a default directory. We look in this directory for
+ // files mentioned in the configuration.
+ //
+ _defaultDir = properties.getProperty(prefix + "DefaultDir");
+
+ //
+ // We need a SecureRandom object.
+ //
+ // NOTE: The JDK recommends obtaining a SecureRandom object like this:
+ //
+ // java.security.SecureRandom rand = java.security.SecureRandom.getInstance("SHA1PRNG");
+ //
+ // However, there is a bug (6202721) which causes it to always use /dev/random,
+ // which can lead to long delays at program startup. The workaround is to use
+ // the default constructor.
+ //
+ java.security.SecureRandom rand = new java.security.SecureRandom();
+
+ //
+ // Check for seed data for the random number generator.
+ //
+ final String seedFiles = properties.getProperty(prefix + "Random");
+ if(seedFiles.length() > 0)
+ {
+ final String[] arr = seedFiles.split(java.io.File.pathSeparator);
+ for(String file : arr)
+ {
+ try
+ {
+ java.io.InputStream seedStream = openResource(file);
+ if(seedStream == null)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: random seed file not found:\n" + file;
+ throw e;
+ }
+
+ _seeds.add(seedStream);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to access random seed file:\n" + file, ex);
+ }
+ }
+ }
+
+ if(!_seeds.isEmpty())
+ {
+ byte[] seed = null;
+ int start = 0;
+ for(InputStream in : _seeds)
+ {
+ try
+ {
+ int num = in.available();
+ if(seed == null)
+ {
+ seed = new byte[num];
+ }
+ else
+ {
+ byte[] tmp = new byte[seed.length + num];
+ System.arraycopy(seed, 0, tmp, 0, seed.length);
+ start = seed.length;
+ seed = tmp;
+ }
+ in.read(seed, start, num);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.PluginInitializationException("IceSSL: error while reading random seed", ex);
+ }
+ finally
+ {
+ try
+ {
+ in.close();
+ }
+ catch(java.io.IOException e)
+ {
+ // Ignore.
+ }
+ }
+ }
+ rand.setSeed(seed);
+ }
+ _seeds.clear();
+
+ //
+ // We call nextInt() in order to force the object to perform any time-consuming
+ // initialization tasks now.
+ //
+ rand.nextInt();
+
+ //
+ // The keystore holds private keys and associated certificates.
+ //
+ String keystorePath = properties.getProperty(prefix + "Keystore");
+
+ //
+ // The password for the keys.
+ //
+ String password = properties.getProperty(prefix + "Password");
+
+ //
+ // The password for the keystore.
+ //
+ String keystorePassword = properties.getProperty(prefix + "KeystorePassword");
+
+ //
+ // The default keystore type is usually "JKS", but the legal values are determined
+ // by the JVM implementation. Other possibilities include "PKCS12" and "BKS".
+ //
+ final String defaultType = java.security.KeyStore.getDefaultType();
+ final String keystoreType = properties.getPropertyWithDefault(prefix + "KeystoreType", defaultType);
+
+ //
+ // The alias of the key to use in authentication.
+ //
+ String alias = properties.getProperty(prefix + "Alias");
+ boolean overrideAlias = !alias.isEmpty(); // Always use the configured alias
+
+ //
+ // The truststore holds the certificates of trusted CAs.
+ //
+ String truststorePath = properties.getProperty(prefix + "Truststore");
+
+ //
+ // The password for the truststore.
+ //
+ String truststorePassword = properties.getProperty(prefix + "TruststorePassword");
+
+ //
+ // The default truststore type is usually "JKS", but the legal values are determined
+ // by the JVM implementation. Other possibilities include "PKCS12" and "BKS".
+ //
+ final String truststoreType =
+ properties.getPropertyWithDefault(prefix + "TruststoreType",
+ java.security.KeyStore.getDefaultType());
+
+ //
+ // Collect the key managers.
+ //
+ javax.net.ssl.KeyManager[] keyManagers = null;
+ java.security.KeyStore keys = null;
+ if(_keystoreStream != null || keystorePath.length() > 0)
+ {
+ java.io.InputStream keystoreStream = null;
+ try
+ {
+ if(_keystoreStream != null)
+ {
+ keystoreStream = _keystoreStream;
+ }
+ else
+ {
+ keystoreStream = openResource(keystorePath);
+ if(keystoreStream == null)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: keystore not found:\n" + keystorePath;
+ throw e;
+ }
+ }
+
+ keys = java.security.KeyStore.getInstance(keystoreType);
+ char[] passwordChars = null;
+ if(keystorePassword.length() > 0)
+ {
+ passwordChars = keystorePassword.toCharArray();
+ }
+ else if(_passwordCallback != null)
+ {
+ passwordChars = _passwordCallback.getKeystorePassword();
+ }
+ else if(keystoreType.equals("BKS") || keystoreType.equals("PKCS12"))
+ {
+ // Bouncy Castle or PKCS12 does not permit null passwords.
+ passwordChars = new char[0];
+ }
+
+ keys.load(keystoreStream, passwordChars);
+
+ if(passwordChars != null)
+ {
+ java.util.Arrays.fill(passwordChars, '\0');
+ }
+ keystorePassword = null;
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to load keystore:\n" + keystorePath, ex);
+ }
+ finally
+ {
+ if(keystoreStream != null)
+ {
+ try
+ {
+ keystoreStream.close();
+ }
+ catch(java.io.IOException e)
+ {
+ // Ignore.
+ }
+ }
+ }
+
+ String algorithm = javax.net.ssl.KeyManagerFactory.getDefaultAlgorithm();
+ javax.net.ssl.KeyManagerFactory kmf = javax.net.ssl.KeyManagerFactory.getInstance(algorithm);
+ char[] passwordChars = new char[0]; // This password cannot be null.
+ if(password.length() > 0)
+ {
+ passwordChars = password.toCharArray();
+ }
+ else if(_passwordCallback != null)
+ {
+ passwordChars = _passwordCallback.getPassword(alias);
+ }
+ kmf.init(keys, passwordChars);
+ if(passwordChars.length > 0)
+ {
+ java.util.Arrays.fill(passwordChars, '\0');
+ }
+ password = null;
+ keyManagers = kmf.getKeyManagers();
+
+ //
+ // If no alias is specified, we look for the first key entry in the key store.
+ //
+ // This is required to force the key manager to always choose a certificate
+ // even if there's no certificate signed by any of the CA names sent by the
+ // server. Ice servers might indeed not always send the CA names of their
+ // trusted roots.
+ //
+ if(alias.isEmpty())
+ {
+ for(java.util.Enumeration<String> e = keys.aliases(); e.hasMoreElements();)
+ {
+ String a = e.nextElement();
+ if(keys.isKeyEntry(a))
+ {
+ alias = a;
+ break;
+ }
+ }
+ }
+
+ if(!alias.isEmpty())
+ {
+ //
+ // If the user selected a specific alias, we need to wrap the key managers
+ // in order to return the desired alias.
+ //
+ if(!keys.isKeyEntry(alias))
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: keystore does not contain an entry with alias `" + alias + "'";
+ throw e;
+ }
+
+ for(int i = 0; i < keyManagers.length; ++i)
+ {
+ keyManagers[i] = new X509KeyManagerI((javax.net.ssl.X509ExtendedKeyManager)keyManagers[i],
+ alias, overrideAlias);
+ }
+ }
+ }
+
+ //
+ // Load the truststore.
+ //
+ java.security.KeyStore ts = null;
+ if(_truststoreStream != null || truststorePath.length() > 0)
+ {
+ //
+ // If the trust store and the key store are the same input
+ // stream or file, don't create another key store.
+ //
+ if((_truststoreStream != null && _truststoreStream == _keystoreStream) ||
+ (truststorePath.length() > 0 && truststorePath.equals(keystorePath)))
+ {
+ assert keys != null;
+ ts = keys;
+ }
+ else
+ {
+ java.io.InputStream truststoreStream = null;
+ try
+ {
+ if(_truststoreStream != null)
+ {
+ truststoreStream = _truststoreStream;
+ }
+ else
+ {
+ truststoreStream = openResource(truststorePath);
+ if(truststoreStream == null)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: truststore not found:\n" + truststorePath;
+ throw e;
+ }
+ }
+
+ ts = java.security.KeyStore.getInstance(truststoreType);
+
+ char[] passwordChars = null;
+ if(truststorePassword.length() > 0)
+ {
+ passwordChars = truststorePassword.toCharArray();
+ }
+ else if(_passwordCallback != null)
+ {
+ passwordChars = _passwordCallback.getTruststorePassword();
+ }
+ else if(truststoreType.equals("BKS") || truststoreType.equals("PKCS12"))
+ {
+ // Bouncy Castle or PKCS12 does not permit null passwords.
+ passwordChars = new char[0];
+ }
+
+ ts.load(truststoreStream, passwordChars);
+
+ if(passwordChars != null)
+ {
+ java.util.Arrays.fill(passwordChars, '\0');
+ }
+ truststorePassword = null;
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to load truststore:\n" + truststorePath, ex);
+ }
+ finally
+ {
+ if(truststoreStream != null)
+ {
+ try
+ {
+ truststoreStream.close();
+ }
+ catch(java.io.IOException e)
+ {
+ // Ignore.
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Collect the trust managers. Use IceSSL.Truststore if
+ // specified, otherwise use the Java root CAs if
+ // Ice.Use.PlatformCAs is enabled. If none of these are enabled,
+ // use the keystore or a dummy trust manager which rejects any
+ // certificate.
+ //
+ javax.net.ssl.TrustManager[] trustManagers = null;
+ {
+ String algorithm = javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm();
+ javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance(algorithm);
+ java.security.KeyStore trustStore = null;
+ if(ts != null)
+ {
+ trustStore = ts;
+ }
+ else if(properties.getPropertyAsInt("IceSSL.UsePlatformCAs") <= 0)
+ {
+ if(keys != null)
+ {
+ trustStore = keys;
+ }
+ else
+ {
+ trustManagers = new javax.net.ssl.TrustManager[]
+ {
+ new javax.net.ssl.X509TrustManager()
+ {
+ @Override
+ public void
+ checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException
+ {
+ throw new CertificateException("no trust anchors");
+ }
+
+ @Override
+ public void
+ checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException
+ {
+ throw new CertificateException("no trust anchors");
+ }
+
+ @Override
+ public X509Certificate[]
+ getAcceptedIssuers()
+ {
+ return new X509Certificate[0];
+ }
+ }
+ };
+ }
+ }
+ else
+ {
+ trustStore = null;
+ }
+
+ //
+ // Attempting to establish an outgoing connection with an empty truststore can
+ // cause hangs that eventually result in an exception such as:
+ //
+ // java.security.InvalidAlgorithmParameterException: the trustAnchors parameter
+ // must be non-empty
+ //
+ if(trustStore != null && trustStore.size() == 0)
+ {
+ throw new Ice.PluginInitializationException("IceSSL: truststore is empty");
+ }
+
+ if(trustManagers == null)
+ {
+ tmf.init(trustStore);
+ trustManagers = tmf.getTrustManagers();
+ }
+ assert(trustManagers != null);
+ }
+
+ //
+ // Create a certificate path validator to build the full
+ // certificate chain of the peer certificate. NOTE: this must
+ // be done before wrapping the trust manager since our wrappers
+ // return an empty list of accepted issuers.
+ //
+ _validator = CertPathValidator.getInstance("PKIX");
+ java.util.Set<TrustAnchor> anchors = new java.util.HashSet<TrustAnchor>();
+ for(javax.net.ssl.TrustManager tm : trustManagers)
+ {
+ X509Certificate[] certs = ((javax.net.ssl.X509TrustManager)tm).getAcceptedIssuers();
+ for(X509Certificate cert : certs)
+ {
+ if(cert.getBasicConstraints() >= 0) // Only add CAs
+ {
+ anchors.add(new TrustAnchor(cert, null));
+ }
+ }
+ }
+ if(!anchors.isEmpty())
+ {
+ _validatorParams = new PKIXParameters(anchors);
+ _validatorParams.setRevocationEnabled(false);
+ }
+
+ //
+ // Wrap each trust manager.
+ //
+ for(int i = 0; i < trustManagers.length; ++i)
+ {
+ trustManagers[i] = new X509TrustManagerI(this, (javax.net.ssl.X509TrustManager)trustManagers[i]);
+ }
+
+ //
+ // Initialize the SSL context.
+ //
+ _context = javax.net.ssl.SSLContext.getInstance("TLS");
+ _context.init(keyManagers, trustManagers, rand);
+ }
+ catch(java.security.GeneralSecurityException ex)
+ {
+ throw new Ice.PluginInitializationException("IceSSL: unable to initialize context", ex);
+ }
+ }
+
+ //
+ // Clear cached input streams.
+ //
+ _seeds.clear();
+ _keystoreStream = null;
+ _truststoreStream = null;
+
+ _initialized = true;
+ }
+
+ Certificate[] getVerifiedCertificateChain(Certificate[] chain)
+ {
+ if(_validator == null)
+ {
+ return chain; // The user provided a custom SSLContext
+ }
+
+ if(_validatorParams == null)
+ {
+ return null; // Couldn't validate the given certificate chain, no trust anchors configured.
+ }
+
+ List<Certificate> certs = new ArrayList<Certificate>(java.util.Arrays.asList(chain));
+ try
+ {
+ CertPath path = CertificateFactory.getInstance("X.509").generateCertPath(certs);
+ CertPathValidatorResult result = _validator.validate(path, _validatorParams);
+ Certificate root = ((PKIXCertPathValidatorResult)result).getTrustAnchor().getTrustedCert();
+ if(!root.equals(chain[chain.length - 1])) // Only add the root certificate if it's not already in the chain
+ {
+ certs.add(root);
+ }
+ return certs.toArray(new Certificate[certs.size()]);
+ }
+ catch(Exception ex)
+ {
+ return null; // Couldn't validate the given certificate chain.
+ }
+ }
+
+ void context(javax.net.ssl.SSLContext context)
+ {
+ if(_initialized)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plug-in is already initialized";
+ throw ex;
+ }
+
+ assert(_context == null);
+ _context = context;
+ }
+
+ javax.net.ssl.SSLContext context()
+ {
+ return _context;
+ }
+
+ void setCertificateVerifier(CertificateVerifier verifier)
+ {
+ _verifier = verifier;
+ }
+
+ CertificateVerifier getCertificateVerifier()
+ {
+ return _verifier;
+ }
+
+ void setPasswordCallback(PasswordCallback callback)
+ {
+ _passwordCallback = callback;
+ }
+
+ PasswordCallback getPasswordCallback()
+ {
+ return _passwordCallback;
+ }
+
+ void setKeystoreStream(java.io.InputStream stream)
+ {
+ if(_initialized)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plugin is already initialized";
+ throw ex;
+ }
+
+ _keystoreStream = stream;
+ }
+
+ void setTruststoreStream(java.io.InputStream stream)
+ {
+ if(_initialized)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plugin is already initialized";
+ throw ex;
+ }
+
+ _truststoreStream = stream;
+ }
+
+ void addSeedStream(java.io.InputStream stream)
+ {
+ _seeds.add(stream);
+ }
+
+ int securityTraceLevel()
+ {
+ return _securityTraceLevel;
+ }
+
+ String securityTraceCategory()
+ {
+ return _securityTraceCategory;
+ }
+
+ boolean initialized()
+ {
+ return _initialized;
+ }
+
+ javax.net.ssl.SSLEngine createSSLEngine(boolean incoming, String host, int port)
+ {
+ javax.net.ssl.SSLEngine engine;
+ if(host != null)
+ {
+ engine = _context.createSSLEngine(host, port);
+ }
+ else
+ {
+ engine = _context.createSSLEngine();
+ }
+ engine.setUseClientMode(!incoming);
+
+ String[] cipherSuites = filterCiphers(engine.getSupportedCipherSuites(), engine.getEnabledCipherSuites());
+ try
+ {
+ engine.setEnabledCipherSuites(cipherSuites);
+ }
+ catch(IllegalArgumentException ex)
+ {
+ throw new Ice.SecurityException("IceSSL: invalid ciphersuite", ex);
+ }
+
+ if(_securityTraceLevel >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("enabling SSL ciphersuites:");
+ for(String suite : cipherSuites)
+ {
+ s.append("\n ");
+ s.append(suite);
+ }
+ _logger.trace(_securityTraceCategory, s.toString());
+ }
+
+ if(_protocols != null)
+ {
+ try
+ {
+ engine.setEnabledProtocols(_protocols);
+ }
+ catch(IllegalArgumentException ex)
+ {
+ throw new Ice.SecurityException("IceSSL: invalid protocol", ex);
+ }
+ }
+ else
+ {
+ //
+ // Disable SSLv3
+ //
+ List<String> protocols = new ArrayList<String>(java.util.Arrays.asList(engine.getEnabledProtocols()));
+ protocols.remove("SSLv3");
+ engine.setEnabledProtocols(protocols.toArray(new String[protocols.size()]));
+ }
+
+
+ if(incoming)
+ {
+ if(_verifyPeer == 0)
+ {
+ engine.setWantClientAuth(false);
+ engine.setNeedClientAuth(false);
+ }
+ else if(_verifyPeer == 1)
+ {
+ engine.setWantClientAuth(true);
+ }
+ else
+ {
+ engine.setNeedClientAuth(true);
+ }
+ }
+
+ try
+ {
+ engine.beginHandshake();
+ }
+ catch(javax.net.ssl.SSLException ex)
+ {
+ throw new Ice.SecurityException("IceSSL: handshake error", ex);
+ }
+
+ return engine;
+ }
+
+ String[] filterCiphers(String[] supportedCiphers, String[] defaultCiphers)
+ {
+ java.util.LinkedList<String> result = new java.util.LinkedList<String>();
+ if(_allCiphers)
+ {
+ for(String cipher : supportedCiphers)
+ {
+ result.add(cipher);
+ }
+ }
+ else if(!_noCiphers)
+ {
+ for(String cipher : defaultCiphers)
+ {
+ result.add(cipher);
+ }
+ }
+
+ if(_ciphers != null)
+ {
+ for(CipherExpression ce : _ciphers)
+ {
+ if(ce.not)
+ {
+ java.util.Iterator<String> e = result.iterator();
+ while(e.hasNext())
+ {
+ String cipher = e.next();
+ if(ce.cipher != null)
+ {
+ if(ce.cipher.equals(cipher))
+ {
+ e.remove();
+ }
+ }
+ else
+ {
+ assert(ce.re != null);
+ java.util.regex.Matcher m = ce.re.matcher(cipher);
+ if(m.find())
+ {
+ e.remove();
+ }
+ }
+ }
+ }
+ else
+ {
+ if(ce.cipher != null)
+ {
+ result.add(0, ce.cipher);
+ }
+ else
+ {
+ assert(ce.re != null);
+ for(String cipher : supportedCiphers)
+ {
+ java.util.regex.Matcher m = ce.re.matcher(cipher);
+ if(m.find())
+ {
+ result.add(0, cipher);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ String[] arr = new String[result.size()];
+ result.toArray(arr);
+ return arr;
+ }
+
+ String[] protocols()
+ {
+ return _protocols;
+ }
+
+ void traceConnection(String desc, javax.net.ssl.SSLEngine engine, boolean incoming)
+ {
+ javax.net.ssl.SSLSession session = engine.getSession();
+ String msg = "SSL summary for " + (incoming ? "incoming" : "outgoing") + " connection\n" +
+ "cipher = " + session.getCipherSuite() + "\n" +
+ "protocol = " + session.getProtocol() + "\n" + desc;
+ _logger.trace(_securityTraceCategory, msg);
+ }
+
+ Ice.Communicator communicator()
+ {
+ return _communicator;
+ }
+
+ void verifyPeer(String address, NativeConnectionInfo info, String desc)
+ {
+ //
+ // IceSSL.VerifyPeer is translated into the proper SSLEngine configuration
+ // for a server, but we have to do it ourselves for a client.
+ //
+ if(!info.incoming)
+ {
+ if(_verifyPeer > 0 && !info.verified)
+ {
+ throw new Ice.SecurityException("IceSSL: server did not supply a certificate");
+ }
+ }
+
+ //
+ // For an outgoing connection, we compare the proxy address (if any) against
+ // fields in the server's certificate (if any).
+ //
+ if(info.nativeCerts != null && info.nativeCerts.length > 0 && address.length() > 0)
+ {
+ X509Certificate cert = (X509Certificate)info.nativeCerts[0];
+
+ //
+ // Extract the IP addresses and the DNS names from the subject
+ // alternative names.
+ //
+ java.util.ArrayList<String> ipAddresses = new java.util.ArrayList<String>();
+ java.util.ArrayList<String> dnsNames = new java.util.ArrayList<String>();
+ try
+ {
+ java.util.Collection<java.util.List<?> > subjectAltNames = cert.getSubjectAlternativeNames();
+ if(subjectAltNames != null)
+ {
+ for(java.util.List<?> l : subjectAltNames)
+ {
+ assert(!l.isEmpty());
+ Integer n = (Integer)l.get(0);
+ if(n.intValue() == 7)
+ {
+ ipAddresses.add((String)l.get(1));
+ }
+ else if(n.intValue() == 2)
+ {
+ dnsNames.add(((String)l.get(1)).toLowerCase());
+ }
+ }
+ }
+ }
+ catch(CertificateParsingException ex)
+ {
+ assert(false);
+ }
+
+ //
+ // Compare the peer's address against the common name as well as
+ // the dnsName and ipAddress values in the subject alternative name.
+ //
+ boolean certNameOK = false;
+ String dn = "";
+ String addrLower = address.toLowerCase();
+ {
+ javax.security.auth.x500.X500Principal principal = cert.getSubjectX500Principal();
+ dn = principal.getName(javax.security.auth.x500.X500Principal.CANONICAL);
+ //
+ // Canonical format is already in lower case.
+ //
+ String cn = "cn=" + addrLower;
+ int pos = dn.indexOf(cn);
+ if(pos >= 0)
+ {
+ //
+ // Ensure we match the entire common name.
+ //
+ certNameOK = (pos + cn.length() == dn.length()) || (dn.charAt(pos + cn.length()) == ',');
+ }
+ }
+
+ //
+ // Compare the peer's address against the dnsName and ipAddress
+ // values in the subject alternative name.
+ //
+ if(!certNameOK)
+ {
+ certNameOK = ipAddresses.contains(addrLower);
+ }
+ if(!certNameOK)
+ {
+ certNameOK = dnsNames.contains(addrLower);
+ }
+
+ //
+ // Log a message if the name comparison fails. If CheckCertName is defined,
+ // we also raise an exception to abort the connection. Don't log a message if
+ // CheckCertName is not defined and a verifier is present.
+ //
+ if(!certNameOK && (_checkCertName || (_securityTraceLevel >= 1 && _verifier == null)))
+ {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("IceSSL: ");
+ if(!_checkCertName)
+ {
+ sb.append("ignoring ");
+ }
+ sb.append("certificate validation failure:\npeer certificate does not have `");
+ sb.append(address);
+ sb.append("' as its commonName or in its subjectAltName extension");
+ if(dn.length() > 0)
+ {
+ sb.append("\nSubject DN: ");
+ sb.append(dn);
+ }
+ if(!dnsNames.isEmpty())
+ {
+ sb.append("\nDNS names found in certificate: ");
+ for(int j = 0; j < dnsNames.size(); ++j)
+ {
+ if(j > 0)
+ {
+ sb.append(", ");
+ }
+ sb.append(dnsNames.get(j));
+ }
+ }
+ if(!ipAddresses.isEmpty())
+ {
+ sb.append("\nIP addresses found in certificate: ");
+ for(int j = 0; j < ipAddresses.size(); ++j)
+ {
+ if(j > 0)
+ {
+ sb.append(", ");
+ }
+ sb.append(ipAddresses.get(j));
+ }
+ }
+ if(_securityTraceLevel >= 1)
+ {
+ _logger.trace(_securityTraceCategory, sb.toString());
+ }
+ if(_checkCertName)
+ {
+ Ice.SecurityException ex = new Ice.SecurityException();
+ ex.reason = sb.toString();
+ throw ex;
+ }
+ }
+ }
+
+ if(_verifyDepthMax > 0 && info.nativeCerts != null && info.nativeCerts.length > _verifyDepthMax)
+ {
+ String msg = (info.incoming ? "incoming" : "outgoing") + " connection rejected:\n" +
+ "length of peer's certificate chain (" + info.nativeCerts.length + ") exceeds maximum of " +
+ _verifyDepthMax + "\n" + desc;
+ if(_securityTraceLevel >= 1)
+ {
+ _logger.trace(_securityTraceCategory, msg);
+ }
+ Ice.SecurityException ex = new Ice.SecurityException();
+ ex.reason = msg;
+ throw ex;
+ }
+
+ if(!_trustManager.verify(info, desc))
+ {
+ String msg = (info.incoming ? "incoming" : "outgoing") + " connection rejected by trust manager\n" + desc;
+ if(_securityTraceLevel >= 1)
+ {
+ _logger.trace(_securityTraceCategory, msg);
+ }
+ Ice.SecurityException ex = new Ice.SecurityException();
+ ex.reason = msg;
+ throw ex;
+ }
+
+ if(_verifier != null && !_verifier.verify(info))
+ {
+ String msg = (info.incoming ? "incoming" : "outgoing") + " connection rejected by certificate verifier\n" +
+ desc;
+ if(_securityTraceLevel >= 1)
+ {
+ _logger.trace(_securityTraceCategory, msg);
+ }
+ Ice.SecurityException ex = new Ice.SecurityException();
+ ex.reason = msg;
+ throw ex;
+ }
+ }
+
+ void trustManagerFailure(boolean incoming, CertificateException ex)
+ throws CertificateException
+ {
+ if(_verifyPeer == 0)
+ {
+ if(_securityTraceLevel >= 1)
+ {
+ String msg = "ignoring peer verification failure";
+ if(_securityTraceLevel > 1)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ msg += ":\n" + sw.toString();
+ }
+ _logger.trace(_securityTraceCategory, msg);
+ }
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ private void parseCiphers(String ciphers)
+ {
+ java.util.ArrayList<CipherExpression> cipherList = new java.util.ArrayList<CipherExpression>();
+ String[] expr = ciphers.split("[ \t]+");
+ for(int i = 0; i < expr.length; ++i)
+ {
+ if(expr[i].equals("ALL"))
+ {
+ if(i != 0)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: `ALL' must be first in cipher list `" + ciphers + "'";
+ throw ex;
+ }
+ _allCiphers = true;
+ }
+ else if(expr[i].equals("NONE"))
+ {
+ if(i != 0)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: `NONE' must be first in cipher list `" + ciphers + "'";
+ throw ex;
+ }
+ _noCiphers = true;
+ }
+ else
+ {
+ CipherExpression ce = new CipherExpression();
+ String exp = expr[i];
+ if(exp.charAt(0) == '!')
+ {
+ ce.not = true;
+ if(exp.length() > 1)
+ {
+ exp = exp.substring(1);
+ }
+ else
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: invalid cipher expression `" + exp + "'";
+ throw ex;
+ }
+ }
+
+ if(exp.charAt(0) == '(')
+ {
+ if(!exp.endsWith(")"))
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: invalid cipher expression `" + exp + "'";
+ throw ex;
+ }
+
+ try
+ {
+ ce.re = java.util.regex.Pattern.compile(exp.substring(1, exp.length() - 2));
+ }
+ catch(java.util.regex.PatternSyntaxException ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: invalid cipher expression `" + exp + "'", ex);
+ }
+ }
+ else
+ {
+ ce.cipher = exp;
+ }
+
+ cipherList.add(ce);
+ }
+ }
+ _ciphers = new CipherExpression[cipherList.size()];
+ cipherList.toArray(_ciphers);
+ }
+
+ private java.io.InputStream openResource(String path)
+ throws java.io.IOException
+ {
+ boolean isAbsolute = false;
+ try
+ {
+ new java.net.URL(path);
+ isAbsolute = true;
+ }
+ catch(java.net.MalformedURLException ex)
+ {
+ java.io.File f = new java.io.File(path);
+ isAbsolute = f.isAbsolute();
+ }
+
+ java.io.InputStream stream = IceInternal.Util.openResource(getClass().getClassLoader(), path);
+
+ //
+ // If the first attempt fails and IceSSL.DefaultDir is defined and the original path is relative,
+ // we prepend the default directory and try again.
+ //
+ if(stream == null && _defaultDir.length() > 0 && !isAbsolute)
+ {
+ stream = IceInternal.Util.openResource(getClass().getClassLoader(),
+ _defaultDir + java.io.File.separator + path);
+ }
+
+ if(stream != null)
+ {
+ stream = new java.io.BufferedInputStream(stream);
+ }
+
+ return stream;
+ }
+
+ private static class CipherExpression
+ {
+ boolean not;
+ String cipher;
+ java.util.regex.Pattern re;
+ }
+
+ private Ice.Communicator _communicator;
+ private Ice.Logger _logger;
+ private IceInternal.ProtocolPluginFacade _facade;
+ private int _securityTraceLevel;
+ private String _securityTraceCategory;
+ private boolean _initialized;
+ private javax.net.ssl.SSLContext _context;
+ private String _defaultDir;
+ private CipherExpression[] _ciphers;
+ private boolean _allCiphers;
+ private boolean _noCiphers;
+ private String[] _protocols;
+ private boolean _checkCertName;
+ private int _verifyDepthMax;
+ private int _verifyPeer;
+ private CertificateVerifier _verifier;
+ private PasswordCallback _passwordCallback;
+ private TrustManager _trustManager;
+
+ private InputStream _keystoreStream;
+ private InputStream _truststoreStream;
+ private List<InputStream> _seeds = new ArrayList<InputStream>();
+
+ private CertPathValidator _validator;
+ private PKIXParameters _validatorParams;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/TransceiverI.java b/java-compat/src/Ice/src/main/java/IceSSL/TransceiverI.java
new file mode 100644
index 00000000000..d34a83acdae
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/TransceiverI.java
@@ -0,0 +1,588 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+import java.nio.*;
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.*;
+
+final class TransceiverI implements IceInternal.Transceiver
+{
+ @Override
+ public java.nio.channels.SelectableChannel fd()
+ {
+ return _delegate.fd();
+ }
+
+ @Override
+ public void setReadyCallback(IceInternal.ReadyCallback callback)
+ {
+ _readyCallback = callback;
+ _delegate.setReadyCallback(callback);
+ }
+
+ @Override
+ public int initialize(IceInternal.Buffer readBuffer, IceInternal.Buffer writeBuffer)
+ {
+ if(!_isConnected)
+ {
+ int status = _delegate.initialize(readBuffer, writeBuffer);
+ if(status != IceInternal.SocketOperation.None)
+ {
+ return status;
+ }
+ _isConnected = true;
+
+ Ice.IPConnectionInfo ipInfo = null;
+ for(Ice.ConnectionInfo p = _delegate.getInfo(); p != null; p = p.underlying)
+ {
+ if(p instanceof Ice.IPConnectionInfo)
+ {
+ ipInfo = (Ice.IPConnectionInfo)p;
+ }
+ }
+ final String host = _incoming ? (ipInfo != null ? ipInfo.remoteAddress : "") : _host;
+ final int port = ipInfo != null ? ipInfo.remotePort : -1;
+ _engine = _instance.createSSLEngine(_incoming, host, port);
+ _appInput = ByteBuffer.allocateDirect(_engine.getSession().getApplicationBufferSize() * 2);
+ int bufSize = _engine.getSession().getPacketBufferSize() * 2;
+ _netInput = new IceInternal.Buffer(ByteBuffer.allocateDirect(bufSize * 2));
+ _netOutput = new IceInternal.Buffer(ByteBuffer.allocateDirect(bufSize * 2));
+ }
+
+ int status = handshakeNonBlocking();
+ if(status != IceInternal.SocketOperation.None)
+ {
+ return status;
+ }
+
+ //
+ // Additional verification.
+ //
+ _instance.verifyPeer(_host, (NativeConnectionInfo)getInfo(), _delegate.toString());
+
+ if(_instance.securityTraceLevel() >= 1)
+ {
+ _instance.traceConnection(_delegate.toString(), _engine, _incoming);
+ }
+ return IceInternal.SocketOperation.None;
+ }
+
+ @Override
+ public int closing(boolean initiator, Ice.LocalException ex)
+ {
+ // If we are initiating the connection closure, wait for the peer
+ // to close the TCP/IP connection. Otherwise, close immediately.
+ return initiator ? IceInternal.SocketOperation.Read : IceInternal.SocketOperation.None;
+ }
+
+ @Override
+ public void close()
+ {
+ if(_engine != null)
+ {
+ try
+ {
+ //
+ // Send the close_notify message.
+ //
+ _engine.closeOutbound();
+ _netOutput.b.clear();
+ while(!_engine.isOutboundDone())
+ {
+ _engine.wrap(_emptyBuffer, _netOutput.b);
+ try
+ {
+ //
+ // Note: we can't block to send the close_notify message. In some cases, the
+ // close_notify message might therefore not be received by the peer. This is
+ // not a big issue since the Ice protocol isn't subject to truncation attacks.
+ //
+ flushNonBlocking();
+ }
+ catch(Ice.LocalException ex)
+ {
+ // Ignore.
+ }
+ }
+ }
+ catch(SSLException ex)
+ {
+ //
+ // We can't throw in close.
+ //
+ // Ice.SecurityException se = new Ice.SecurityException(
+ // "IceSSL: SSL failure while shutting down socket", ex);
+ //
+ }
+
+ try
+ {
+ _engine.closeInbound();
+ }
+ catch(SSLException ex)
+ {
+ //
+ // SSLEngine always raises an exception with this message:
+ //
+ // Inbound closed before receiving peer's close_notify: possible truncation attack?
+ //
+ // We would probably need to wait for a response in shutdown() to avoid this.
+ // For now, we'll ignore this exception.
+ //
+ //_instance.logger().error("IceSSL: error during close\n" + ex.getMessage());
+ }
+ }
+
+ _delegate.close();
+ }
+
+ @Override
+ public IceInternal.EndpointI bind()
+ {
+ assert(false);
+ return null;
+ }
+
+ @Override
+ public int write(IceInternal.Buffer buf)
+ {
+ if(!_isConnected)
+ {
+ return _delegate.write(buf);
+ }
+
+ int status = writeNonBlocking(buf.b);
+ assert(status == IceInternal.SocketOperation.None || status == IceInternal.SocketOperation.Write);
+ return status;
+ }
+
+ @Override
+ public int read(IceInternal.Buffer buf)
+ {
+ if(!_isConnected)
+ {
+ return _delegate.read(buf);
+ }
+
+ _readyCallback.ready(IceInternal.SocketOperation.Read, false);
+
+ //
+ // Try to satisfy the request from data we've already decrypted.
+ //
+ fill(buf.b);
+
+ //
+ // Read and decrypt more data if necessary. Note that we might read
+ // more data from the socket than is actually necessary to fill the
+ // caller's stream.
+ //
+ try
+ {
+ while(buf.b.hasRemaining())
+ {
+ _netInput.b.flip();
+ SSLEngineResult result = _engine.unwrap(_netInput.b, _appInput);
+ _netInput.b.compact();
+
+ Status status = result.getStatus();
+ assert status != Status.BUFFER_OVERFLOW;
+
+ if(status == Status.CLOSED)
+ {
+ throw new Ice.ConnectionLostException();
+ }
+ // Android API 21 SSLEngine doesn't report underflow, so look at the absence of
+ // network data and application data to signal a network read.
+ else if(status == Status.BUFFER_UNDERFLOW || (_appInput.position() == 0 && _netInput.b.position() == 0))
+ {
+ int s = _delegate.read(_netInput);
+ if(s != IceInternal.SocketOperation.None && _netInput.b.position() == 0)
+ {
+ return s;
+ }
+ continue;
+ }
+
+ fill(buf.b);
+ }
+
+ // If there is no more application data, do one further unwrap to ensure
+ // that the SSLEngine has no buffered data (Android R21 and greater only).
+ if(_appInput.position() == 0)
+ {
+ _netInput.b.flip();
+ _engine.unwrap(_netInput.b, _appInput);
+ _netInput.b.compact();
+
+ // Don't check the status here since we may have already filled
+ // the buffer with a complete request which must be processed.
+ }
+ }
+ catch(SSLException ex)
+ {
+ throw new Ice.SecurityException("IceSSL: error during read", ex);
+ }
+
+ //
+ // Indicate whether more data is available.
+ //
+ if(_netInput.b.position() > 0 || _appInput.position() > 0)
+ {
+ _readyCallback.ready(IceInternal.SocketOperation.Read, true);
+ }
+
+ return IceInternal.SocketOperation.None;
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _delegate.protocol();
+ }
+
+ @Override
+ public String toString()
+ {
+ return _delegate.toString();
+ }
+
+ @Override
+ public String toDetailedString()
+ {
+ return toString();
+ }
+
+ @Override
+ public Ice.ConnectionInfo getInfo()
+ {
+ NativeConnectionInfo info = new NativeConnectionInfo();
+ info.underlying = _delegate.getInfo();
+ info.incoming = _incoming;
+ info.adapterName = _adapterName;
+ if(_engine != null)
+ {
+ SSLSession session = _engine.getSession();
+ info.cipher = session.getCipherSuite();
+ try
+ {
+ java.security.cert.Certificate[] pcerts = session.getPeerCertificates();
+ java.security.cert.Certificate[] vcerts = _instance.engine().getVerifiedCertificateChain(pcerts);
+ info.verified = vcerts != null;
+ info.nativeCerts = vcerts != null ? vcerts : pcerts;
+ java.util.ArrayList<String> certs = new java.util.ArrayList<String>();
+ for(java.security.cert.Certificate c : info.nativeCerts)
+ {
+ StringBuilder s = new StringBuilder("-----BEGIN CERTIFICATE-----\n");
+ s.append(IceUtilInternal.Base64.encode(c.getEncoded()));
+ s.append("\n-----END CERTIFICATE-----");
+ certs.add(s.toString());
+ }
+ info.certs = certs.toArray(new String[certs.size()]);
+ }
+ catch(javax.net.ssl.SSLPeerUnverifiedException ex)
+ {
+ // No peer certificates.
+ }
+ catch(java.security.cert.CertificateEncodingException ex)
+ {
+ }
+ }
+ return info;
+ }
+
+ @Override
+ public void setBufferSize(int rcvSize, int sndSize)
+ {
+ _delegate.setBufferSize(rcvSize, sndSize);
+ }
+
+ @Override
+ public void checkSendSize(IceInternal.Buffer buf)
+ {
+ _delegate.checkSendSize(buf);
+ }
+
+ TransceiverI(Instance instance, IceInternal.Transceiver delegate, String hostOrAdapterName, boolean incoming)
+ {
+ _instance = instance;
+ _delegate = delegate;
+ _incoming = incoming;
+ if(_incoming)
+ {
+ _adapterName = hostOrAdapterName;
+ }
+ else
+ {
+ _host = hostOrAdapterName;
+ }
+ }
+
+ private int handshakeNonBlocking()
+ {
+ try
+ {
+ HandshakeStatus status = _engine.getHandshakeStatus();
+ while(!_engine.isOutboundDone() && !_engine.isInboundDone())
+ {
+ SSLEngineResult result = null;
+ switch(status)
+ {
+ case FINISHED:
+ case NOT_HANDSHAKING:
+ {
+ return IceInternal.SocketOperation.None;
+ }
+ case NEED_TASK:
+ {
+ Runnable task;
+ while((task = _engine.getDelegatedTask()) != null)
+ {
+ task.run();
+ }
+ status = _engine.getHandshakeStatus();
+ break;
+ }
+ case NEED_UNWRAP:
+ {
+ if(_netInput.b.position() == 0)
+ {
+ int s = _delegate.read(_netInput);
+ if(s != IceInternal.SocketOperation.None && _netInput.b.position() == 0)
+ {
+ return s;
+ }
+ }
+
+ //
+ // The engine needs more data. We might already have enough data in
+ // the _netInput buffer to satisfy the engine. If not, the engine
+ // responds with BUFFER_UNDERFLOW and we'll read from the socket.
+ //
+ _netInput.b.flip();
+ result = _engine.unwrap(_netInput.b, _appInput);
+ _netInput.b.compact();
+ //
+ // FINISHED is only returned from wrap or unwrap, not from engine.getHandshakeResult().
+ //
+ status = result.getHandshakeStatus();
+ switch(result.getStatus())
+ {
+ case BUFFER_OVERFLOW:
+ {
+ assert(false);
+ break;
+ }
+ case BUFFER_UNDERFLOW:
+ {
+ assert(status == javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_UNWRAP);
+ int position = _netInput.b.position();
+ int s = _delegate.read(_netInput);
+ if(s != IceInternal.SocketOperation.None && _netInput.b.position() == position)
+ {
+ return s;
+ }
+ break;
+ }
+ case CLOSED:
+ {
+ throw new Ice.ConnectionLostException();
+ }
+ case OK:
+ {
+ break;
+ }
+ }
+ break;
+ }
+ case NEED_WRAP:
+ {
+ //
+ // The engine needs to send a message.
+ //
+ result = _engine.wrap(_emptyBuffer, _netOutput.b);
+ if(result.bytesProduced() > 0)
+ {
+ int s = flushNonBlocking();
+ if(s != IceInternal.SocketOperation.None)
+ {
+ return s;
+ }
+ }
+
+ //
+ // FINISHED is only returned from wrap or unwrap, not from engine.getHandshakeResult().
+ //
+ status = result.getHandshakeStatus();
+ break;
+ }
+ }
+
+ if(result != null)
+ {
+ switch(result.getStatus())
+ {
+ case BUFFER_OVERFLOW:
+ assert(false);
+ break;
+ case BUFFER_UNDERFLOW:
+ // Need to read again.
+ assert(status == HandshakeStatus.NEED_UNWRAP);
+ break;
+ case CLOSED:
+ throw new Ice.ConnectionLostException();
+ case OK:
+ break;
+ }
+ }
+ }
+ }
+ catch(SSLException ex)
+ {
+ throw new Ice.SecurityException("IceSSL: handshake error", ex);
+ }
+ return IceInternal.SocketOperation.None;
+ }
+
+ private int writeNonBlocking(ByteBuffer buf)
+ {
+ //
+ // This method has two purposes: encrypt the application's message buffer into our
+ // _netOutput buffer, and write the contents of _netOutput to the socket without
+ // blocking.
+ //
+ try
+ {
+ while(buf.hasRemaining() || _netOutput.b.position() > 0)
+ {
+ if(buf.hasRemaining())
+ {
+ //
+ // Encrypt the buffer.
+ //
+ SSLEngineResult result = _engine.wrap(buf, _netOutput.b);
+ switch(result.getStatus())
+ {
+ case BUFFER_OVERFLOW:
+ //
+ // Need to make room in _netOutput.b.
+ //
+ break;
+ case BUFFER_UNDERFLOW:
+ assert(false);
+ break;
+ case CLOSED:
+ throw new Ice.ConnectionLostException();
+ case OK:
+ break;
+ }
+ }
+
+ //
+ // Write the encrypted data to the socket. We continue writing until we've written
+ // all of _netOutput, or until flushNonBlocking indicates that it cannot write
+ // (i.e., by returning SocketOperation.Write).
+ //
+ if(_netOutput.b.position() > 0)
+ {
+ int s = flushNonBlocking();
+ if(s != IceInternal.SocketOperation.None)
+ {
+ return s;
+ }
+ }
+ }
+ }
+ catch(SSLException ex)
+ {
+ throw new Ice.SecurityException("IceSSL: error while encoding message", ex);
+ }
+
+ assert(_netOutput.b.position() == 0);
+ return IceInternal.SocketOperation.None;
+ }
+
+ private int flushNonBlocking()
+ {
+ _netOutput.b.flip();
+
+ try
+ {
+ int s = _delegate.write(_netOutput);
+ if(s != IceInternal.SocketOperation.None)
+ {
+ _netOutput.b.compact();
+ return s;
+ }
+ }
+ catch(Ice.SocketException ex)
+ {
+ throw new Ice.ConnectionLostException(ex);
+ }
+ _netOutput.b.clear();
+ return IceInternal.SocketOperation.None;
+ }
+
+ private void fill(ByteBuffer buf)
+ {
+ _appInput.flip();
+ if(_appInput.hasRemaining())
+ {
+ int bytesAvailable = _appInput.remaining();
+ int bytesNeeded = buf.remaining();
+ if(bytesAvailable > bytesNeeded)
+ {
+ bytesAvailable = bytesNeeded;
+ }
+ if(buf.hasArray())
+ {
+ //
+ // Copy directly into the destination buffer's backing array.
+ //
+ byte[] arr = buf.array();
+ _appInput.get(arr, buf.arrayOffset() + buf.position(), bytesAvailable);
+ buf.position(buf.position() + bytesAvailable);
+ }
+ else if(_appInput.hasArray())
+ {
+ //
+ // Copy directly from the source buffer's backing array.
+ //
+ byte[] arr = _appInput.array();
+ buf.put(arr, _appInput.arrayOffset() + _appInput.position(), bytesAvailable);
+ _appInput.position(_appInput.position() + bytesAvailable);
+ }
+ else
+ {
+ //
+ // Copy using a temporary array.
+ //
+ byte[] arr = new byte[bytesAvailable];
+ _appInput.get(arr);
+ buf.put(arr);
+ }
+ }
+ _appInput.compact();
+ }
+
+ private Instance _instance;
+ private IceInternal.Transceiver _delegate;
+ private javax.net.ssl.SSLEngine _engine;
+ private String _host = "";
+ private String _adapterName = "";
+ private boolean _incoming;
+ private IceInternal.ReadyCallback _readyCallback;
+ private boolean _isConnected = false;
+
+ private ByteBuffer _appInput; // Holds clear-text data to be read by the application.
+ private IceInternal.Buffer _netInput; // Holds encrypted data read from the socket.
+ private IceInternal.Buffer _netOutput; // Holds encrypted data to be written to the socket.
+ private static ByteBuffer _emptyBuffer = ByteBuffer.allocate(0); // Used during handshaking.
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/TrustManager.java b/java-compat/src/Ice/src/main/java/IceSSL/TrustManager.java
new file mode 100644
index 00000000000..ba17851dee8
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/TrustManager.java
@@ -0,0 +1,362 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+class TrustManager
+{
+ TrustManager(Ice.Communicator communicator)
+ {
+ assert communicator != null;
+ _communicator = communicator;
+ Ice.Properties properties = communicator.getProperties();
+ _traceLevel = properties.getPropertyAsInt("IceSSL.Trace.Security");
+ String key = null;
+ try
+ {
+ key = "IceSSL.TrustOnly";
+ parse(properties.getProperty(key), _rejectAll, _acceptAll);
+ key = "IceSSL.TrustOnly.Client";
+ parse(properties.getProperty(key), _rejectClient, _acceptClient);
+ key = "IceSSL.TrustOnly.Server";
+ parse(properties.getProperty(key), _rejectAllServer, _acceptAllServer);
+ java.util.Map<String, String> dict = properties.getPropertiesForPrefix("IceSSL.TrustOnly.Server.");
+ for(java.util.Map.Entry<String, String> p : dict.entrySet())
+ {
+ key = p.getKey();
+ String name = key.substring("IceSSL.TrustOnly.Server.".length());
+ java.util.List<java.util.List<RFC2253.RDNPair> > reject =
+ new java.util.LinkedList<java.util.List<RFC2253.RDNPair> >();
+ java.util.List<java.util.List<RFC2253.RDNPair> > accept =
+ new java.util.LinkedList<java.util.List<RFC2253.RDNPair> >();
+ parse(p.getValue(), reject, accept);
+ if(!reject.isEmpty())
+ {
+ _rejectServer.put(name, reject);
+ }
+ if(!accept.isEmpty())
+ {
+ _acceptServer.put(name, accept);
+ }
+ }
+ }
+ catch(RFC2253.ParseException e)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: invalid property " + key + ":\n" + e.reason;
+ throw ex;
+ }
+ }
+
+ boolean
+ verify(NativeConnectionInfo info, String desc)
+ {
+ java.util.List<java.util.List<java.util.List<RFC2253.RDNPair> > >
+ reject = new java.util.LinkedList<java.util.List<java.util.List<RFC2253.RDNPair> > >(),
+ accept = new java.util.LinkedList<java.util.List<java.util.List<RFC2253.RDNPair> > >();
+
+ if(!_rejectAll.isEmpty())
+ {
+ reject.add(_rejectAll);
+ }
+ if(info.incoming)
+ {
+ if(!_rejectAllServer.isEmpty())
+ {
+ reject.add(_rejectAllServer);
+ }
+ if(info.adapterName.length() > 0)
+ {
+ java.util.List<java.util.List<RFC2253.RDNPair> > p = _rejectServer.get(info.adapterName);
+ if(p != null)
+ {
+ reject.add(p);
+ }
+ }
+ }
+ else
+ {
+ if(!_rejectClient.isEmpty())
+ {
+ reject.add(_rejectClient);
+ }
+ }
+
+ if(!_acceptAll.isEmpty())
+ {
+ accept.add(_acceptAll);
+ }
+ if(info.incoming)
+ {
+ if(!_acceptAllServer.isEmpty())
+ {
+ accept.add(_acceptAllServer);
+ }
+ if(info.adapterName.length() > 0)
+ {
+ java.util.List<java.util.List<RFC2253.RDNPair> > p = _acceptServer.get(info.adapterName);
+ if(p != null)
+ {
+ accept.add(p);
+ }
+ }
+ }
+ else
+ {
+ if(!_acceptClient.isEmpty())
+ {
+ accept.add(_acceptClient);
+ }
+ }
+
+ //
+ // If there is nothing to match against, then we accept the cert.
+ //
+ if(reject.isEmpty() && accept.isEmpty())
+ {
+ return true;
+ }
+
+ //
+ // If there is no certificate then we match false.
+ //
+ if(info.nativeCerts != null && info.nativeCerts.length > 0)
+ {
+ javax.security.auth.x500.X500Principal subjectDN = ((java.security.cert.X509Certificate)info.nativeCerts[0]).getSubjectX500Principal();
+ String subjectName = subjectDN.getName(javax.security.auth.x500.X500Principal.RFC2253);
+ assert subjectName != null;
+ try
+ {
+ //
+ // Decompose the subject DN into the RDNs.
+ //
+ if(_traceLevel > 0)
+ {
+ if(info.incoming)
+ {
+ _communicator.getLogger().trace("Security", "trust manager evaluating client:\n" +
+ "subject = " + subjectName + "\n" +
+ "adapter = " + info.adapterName + "\n" +
+ desc);
+ }
+ else
+ {
+ _communicator.getLogger().trace("Security", "trust manager evaluating server:\n" +
+ "subject = " + subjectName + "\n" + desc);
+ }
+ }
+ java.util.List<RFC2253.RDNPair> dn = RFC2253.parseStrict(subjectName);
+
+ //
+ // Fail if we match anything in the reject set.
+ //
+ for(java.util.List<java.util.List<RFC2253.RDNPair>> matchSet : reject)
+ {
+ if(_traceLevel > 1)
+ {
+ StringBuilder s = new StringBuilder("trust manager rejecting PDNs:\n");
+ stringify(matchSet, s);
+ _communicator.getLogger().trace("Security", s.toString());
+ }
+ if(match(matchSet, dn))
+ {
+ return false;
+ }
+ }
+
+ //
+ // Succeed if we match anything in the accept set.
+ //
+ for(java.util.List<java.util.List<RFC2253.RDNPair>> matchSet : accept)
+ {
+ if(_traceLevel > 1)
+ {
+ StringBuilder s = new StringBuilder("trust manager accepting PDNs:\n");
+ stringify(matchSet, s);
+ _communicator.getLogger().trace("Security", s.toString());
+ }
+ if(match(matchSet, dn))
+ {
+ return true;
+ }
+ }
+ }
+ catch(RFC2253.ParseException e)
+ {
+ _communicator.getLogger().warning(
+ "IceSSL: unable to parse certificate DN `" + subjectName + "'\nreason: " + e.reason);
+ }
+
+ //
+ // At this point we accept the connection if there are no explicit accept rules.
+ //
+ return accept.isEmpty();
+ }
+
+ return false;
+ }
+
+ private boolean
+ match(java.util.List<java.util.List<RFC2253.RDNPair> > matchSet, java.util.List<RFC2253.RDNPair> subject)
+ {
+ for(java.util.List<RFC2253.RDNPair> r : matchSet)
+ {
+ if(matchRDNs(r, subject))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean
+ matchRDNs(java.util.List<RFC2253.RDNPair> match, java.util.List<RFC2253.RDNPair> subject)
+ {
+ for(RFC2253.RDNPair matchRDN : match)
+ {
+ boolean found = false;
+ for(RFC2253.RDNPair subjectRDN : subject)
+ {
+ if(matchRDN.key.equals(subjectRDN.key))
+ {
+ found = true;
+ if(!matchRDN.value.equals(subjectRDN.value))
+ {
+ return false;
+ }
+ }
+ }
+ if(!found)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void
+ parse(String value, java.util.List<java.util.List<RFC2253.RDNPair> > reject,
+ java.util.List<java.util.List<RFC2253.RDNPair> > accept)
+ throws RFC2253.ParseException
+ {
+ //
+ // Java X500Principal.getName says:
+ //
+ // If "RFC2253" is specified as the format, this method emits
+ // the attribute type keywords defined in RFC 2253 (CN, L, ST,
+ // O, OU, C, STREET, DC, UID). Any other attribute type is
+ // emitted as an OID. Under a strict reading, RFC 2253 only
+ // specifies a UTF-8 string representation. The String
+ // returned by this method is the Unicode string achieved by
+ // decoding this UTF-8 representation.
+ //
+ // This means that things like emailAddress and such will be turned into
+ // something like:
+ //
+ // 1.2.840.113549.1.9.1=#160e696e666f407a65726f632e636f6d
+ //
+ // The left hand side is the OID (see
+ // http://www.columbia.edu/~ariel/ssleay/asn1-oids.html) for a
+ // list. The right hand side is a BER encoding of the value.
+ //
+ // This means that the user input, unless it uses the
+ // unfriendly OID format, will not directly match the
+ // principal.
+ //
+ // Two possible solutions:
+ //
+ // Have the RFC2253 parser convert anything that is not CN, L,
+ // ST, O, OU, C, STREET, DC, UID into OID format, and have it
+ // convert the values into a BER encoding.
+ //
+ // Send the user data through X500Principal to string form and
+ // then through the RFC2253 encoder. This uses the
+ // X500Principal to do the encoding for us.
+ //
+ // The latter is much simpler, however, it means we need to
+ // send the data through the parser twice because we split the
+ // DNs on ';' which cannot be blindly split because of quotes,
+ // \ and such.
+ //
+ java.util.List<RFC2253.RDNEntry> l = RFC2253.parse(value);
+ for(RFC2253.RDNEntry e : l)
+ {
+ StringBuilder v = new StringBuilder();
+ boolean first = true;
+ for(RFC2253.RDNPair pair : e.rdn)
+ {
+ if(!first)
+ {
+ v.append(",");
+ }
+ first = false;
+ v.append(pair.key);
+ v.append("=");
+ v.append(pair.value);
+ }
+ javax.security.auth.x500.X500Principal princ = new javax.security.auth.x500.X500Principal(v.toString());
+ String subjectName = princ.getName(javax.security.auth.x500.X500Principal.RFC2253);
+ if(e.negate)
+ {
+ reject.add(RFC2253.parseStrict(subjectName));
+ }
+ else
+ {
+ accept.add(RFC2253.parseStrict(subjectName));
+ }
+ }
+ }
+
+ private static void
+ stringify(java.util.List<java.util.List<RFC2253.RDNPair>> matchSet, StringBuilder s)
+ {
+ boolean addSemi = false;
+ for(java.util.List<RFC2253.RDNPair> rdnSet : matchSet)
+ {
+ if(addSemi)
+ {
+ s.append(';');
+ }
+ addSemi = true;
+ boolean addComma = false;
+ for(RFC2253.RDNPair rdn : rdnSet)
+ {
+ if(addComma)
+ {
+ s.append(',');
+ }
+ addComma = true;
+ s.append(rdn.key);
+ s.append('=');
+ s.append(rdn.value);
+ }
+ }
+ }
+
+ private Ice.Communicator _communicator;
+ private int _traceLevel;
+
+ private java.util.List<java.util.List<RFC2253.RDNPair> > _rejectAll =
+ new java.util.LinkedList<java.util.List<RFC2253.RDNPair> >();
+ private java.util.List<java.util.List<RFC2253.RDNPair> > _rejectClient =
+ new java.util.LinkedList<java.util.List<RFC2253.RDNPair> >();
+ private java.util.List<java.util.List<RFC2253.RDNPair> > _rejectAllServer =
+ new java.util.LinkedList<java.util.List<RFC2253.RDNPair> >();
+ private java.util.Map<String, java.util.List<java.util.List<RFC2253.RDNPair> > > _rejectServer =
+ new java.util.HashMap<String, java.util.List<java.util.List<RFC2253.RDNPair> > >();
+
+ private java.util.List<java.util.List<RFC2253.RDNPair> > _acceptAll =
+ new java.util.LinkedList<java.util.List<RFC2253.RDNPair> >();
+ private java.util.List<java.util.List<RFC2253.RDNPair> > _acceptClient =
+ new java.util.LinkedList<java.util.List<RFC2253.RDNPair> >();
+ private java.util.List<java.util.List<RFC2253.RDNPair> > _acceptAllServer =
+ new java.util.LinkedList<java.util.List<RFC2253.RDNPair> >();
+ private java.util.Map<String, java.util.List<java.util.List<RFC2253.RDNPair> > > _acceptServer =
+ new java.util.HashMap<String, java.util.List<java.util.List<RFC2253.RDNPair> > >();
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/Util.java b/java-compat/src/Ice/src/main/java/IceSSL/Util.java
new file mode 100644
index 00000000000..53a71e15896
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/Util.java
@@ -0,0 +1,72 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+public final class Util
+{
+ //
+ // Create a certificate from a PEM-encoded string.
+ //
+ public static java.security.cert.X509Certificate
+ createCertificate(String certPEM)
+ throws java.security.cert.CertificateException
+ {
+ final String header = "-----BEGIN CERTIFICATE-----";
+ final String footer = "-----END CERTIFICATE-----";
+
+ //
+ // The generateCertificate method requires that its input begin
+ // with the PEM header.
+ //
+ int pos = certPEM.indexOf(header);
+ if(pos == -1)
+ {
+ certPEM = header + "\n" + certPEM;
+ }
+ else if(pos > 0)
+ {
+ certPEM = certPEM.substring(pos);
+ }
+
+ //
+ // Add the footer if necessary.
+ //
+ if(certPEM.indexOf(footer) == -1)
+ {
+ certPEM = certPEM + footer;
+ }
+
+ byte[] bytes = null;
+ try
+ {
+ bytes = certPEM.getBytes("UTF8");
+ }
+ catch(java.io.UnsupportedEncodingException ex)
+ {
+ assert(false);
+ return null;
+ }
+
+ java.io.ByteArrayInputStream in = new java.io.ByteArrayInputStream(bytes);
+ java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
+ return (java.security.cert.X509Certificate)cf.generateCertificate(in);
+ }
+
+ public final static String jdkTarget = "1.5";
+
+ //
+ // Needed by the test scripts to determine the JDK target of the SSL plug-in.
+ //
+ public static void
+ main(String[] args)
+ {
+ System.out.println(jdkTarget);
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/X509KeyManagerI.java b/java-compat/src/Ice/src/main/java/IceSSL/X509KeyManagerI.java
new file mode 100644
index 00000000000..70ca764bfa1
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/X509KeyManagerI.java
@@ -0,0 +1,114 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+import javax.net.ssl.X509ExtendedKeyManager;
+
+final class X509KeyManagerI extends X509ExtendedKeyManager
+{
+ X509KeyManagerI(javax.net.ssl.X509ExtendedKeyManager del, String alias, boolean override)
+ {
+ _delegate = del;
+ _alias = alias;
+ _override = override; // Always use the configured alias, don't check for acceptable issuers
+ }
+
+ @Override
+ public String
+ chooseClientAlias(String[] keyType, java.security.Principal[] issuers, java.net.Socket socket)
+ {
+ if(!_override) // Don't bother checking for acceptable issuers if the user configured IceSSL.Alias
+ {
+ String alias = _delegate.chooseClientAlias(keyType, issuers, socket);
+ if(alias != null && !alias.isEmpty())
+ {
+ return alias;
+ }
+ }
+ return _alias;
+ }
+
+ @Override
+ public String
+ chooseEngineClientAlias(String[] keyType, java.security.Principal[] issuers, javax.net.ssl.SSLEngine engine)
+ {
+ if(!_override) // Don't bother checking for acceptable issuers if the user configured IceSSL.Alias
+ {
+ String alias = _delegate.chooseEngineClientAlias(keyType, issuers, engine);
+ if(alias != null && !alias.isEmpty())
+ {
+ return alias;
+ }
+ }
+ return _alias;
+ }
+
+ @Override
+ public String
+ chooseServerAlias(String keyType, java.security.Principal[] issuers, java.net.Socket socket)
+ {
+ if(!_override) // Don't bother checking for acceptable issuers if the user configured IceSSL.Alias
+ {
+ String alias = _delegate.chooseServerAlias(keyType, issuers, socket);
+ if(alias != null && !alias.isEmpty())
+ {
+ return alias;
+ }
+ }
+ return _alias;
+ }
+
+ @Override
+ public String
+ chooseEngineServerAlias(String keyType, java.security.Principal[] issuers, javax.net.ssl.SSLEngine engine)
+ {
+ if(!_override) // Don't bother checking for acceptable issuers if the user configured IceSSL.Alias
+ {
+ String alias = _delegate.chooseEngineServerAlias(keyType, issuers, engine);
+ if(alias != null && !alias.isEmpty())
+ {
+ return alias;
+ }
+ }
+ return _alias;
+ }
+
+ @Override
+ public java.security.cert.X509Certificate[]
+ getCertificateChain(String alias)
+ {
+ return _delegate.getCertificateChain(alias);
+ }
+
+ @Override
+ public String[]
+ getClientAliases(String keyType, java.security.Principal[] issuers)
+ {
+ return _delegate.getClientAliases(keyType, issuers);
+ }
+
+ @Override
+ public String[]
+ getServerAliases(String keyType, java.security.Principal[] issuers)
+ {
+ return _delegate.getServerAliases(keyType, issuers);
+ }
+
+ @Override
+ public java.security.PrivateKey
+ getPrivateKey(String alias)
+ {
+ return _delegate.getPrivateKey(alias);
+ }
+
+ private javax.net.ssl.X509ExtendedKeyManager _delegate;
+ private String _alias;
+ private boolean _override;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceSSL/X509TrustManagerI.java b/java-compat/src/Ice/src/main/java/IceSSL/X509TrustManagerI.java
new file mode 100644
index 00000000000..57d03e5200e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceSSL/X509TrustManagerI.java
@@ -0,0 +1,82 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceSSL;
+
+final class X509TrustManagerI implements javax.net.ssl.X509TrustManager
+{
+ X509TrustManagerI(SSLEngine engine, javax.net.ssl.X509TrustManager delegate)
+ {
+ _engine = engine;
+ _delegate = delegate;
+ }
+
+ @Override
+ public void
+ checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType)
+ throws java.security.cert.CertificateException
+ {
+ //
+ // Do not invoke the wrapped trust manager for anonymous ciphers.
+ //
+ // Possible values for authType are "DH_anon" and "ECDH_anon" (IBM JDK).
+ //
+ if(authType.indexOf("DH_anon") == -1)
+ {
+ try
+ {
+ _delegate.checkClientTrusted(chain, authType);
+ }
+ catch(java.security.cert.CertificateException ex)
+ {
+ _engine.trustManagerFailure(true, ex);
+ }
+ }
+ }
+
+ @Override
+ public void
+ checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType)
+ throws java.security.cert.CertificateException
+ {
+ //
+ // Do not invoke the wrapped trust manager for anonymous ciphers.
+ //
+ // Possible values for authType are "DH_anon" and "ECDH_anon" (IBM JDK).
+ //
+ if(authType.indexOf("DH_anon") == -1)
+ {
+ try
+ {
+ _delegate.checkServerTrusted(chain, authType);
+ }
+ catch(java.security.cert.CertificateException ex)
+ {
+ _engine.trustManagerFailure(false, ex);
+ }
+ }
+ }
+
+ @Override
+ public java.security.cert.X509Certificate[]
+ getAcceptedIssuers()
+ {
+ //
+ // This method is used to send CA names to the client as part of the CertificateRequest
+ // message sent by the server to request a client certificate. We want the client to always
+ // send its certificate so we don't provide any CAs here.
+ //
+ //return _delegate.getAcceptedIssuers();
+ return EMPTY;
+ }
+
+ private SSLEngine _engine;
+ private javax.net.ssl.X509TrustManager _delegate;
+ private java.security.cert.X509Certificate[] EMPTY = new java.security.cert.X509Certificate[0];
+}
diff --git a/java-compat/src/Ice/src/main/java/IceUtilInternal/Assert.java b/java-compat/src/Ice/src/main/java/IceUtilInternal/Assert.java
new file mode 100644
index 00000000000..545bed9c635
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceUtilInternal/Assert.java
@@ -0,0 +1,45 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceUtilInternal;
+
+public final class Assert
+{
+ //
+ // The JVM ignores exceptions raised in finalizers, therefore finalizers
+ // that use assertions should call this method instead of assert().
+ //
+ public static void
+ FinalizerAssert(boolean b)
+ {
+ if(!b)
+ {
+ //
+ // Create a Throwable to obtain the stack trace.
+ //
+ Throwable t = new Throwable();
+ StackTraceElement[] trace = t.getStackTrace();
+ if(trace.length > 1)
+ {
+ //
+ // Skip the first frame, which represents this method.
+ //
+ System.err.println("Assertion failure:");
+ for(StackTraceElement e : trace)
+ {
+ System.err.println("\tat " + e);
+ }
+ }
+ else
+ {
+ System.err.println("Assertion failure (no stack trace information)");
+ }
+ }
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceUtilInternal/Base64.java b/java-compat/src/Ice/src/main/java/IceUtilInternal/Base64.java
new file mode 100644
index 00000000000..661a464649e
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceUtilInternal/Base64.java
@@ -0,0 +1,270 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceUtilInternal;
+
+public class Base64
+{
+
+public static String
+encode(byte[] plainSeq)
+{
+ if(plainSeq == null || plainSeq.length == 0)
+ {
+ return "";
+ }
+
+ int base64Bytes = (((plainSeq.length * 4) / 3) + 1);
+ int newlineBytes = (((base64Bytes * 2) / 76) + 1);
+ int totalBytes = base64Bytes + newlineBytes;
+
+ StringBuilder retval = new StringBuilder(totalBytes);
+
+ int by1;
+ int by2;
+ int by3;
+ int by4;
+ int by5;
+ int by6;
+ int by7;
+
+ for(int i = 0; i < plainSeq.length; i += 3)
+ {
+ by1 = plainSeq[i] & 0xff;
+ by2 = 0;
+ by3 = 0;
+
+ if((i + 1) < plainSeq.length)
+ {
+ by2 = plainSeq[i+1] & 0xff;
+ }
+
+ if((i + 2) < plainSeq.length)
+ {
+ by3 = plainSeq[i+2] & 0xff;
+ }
+
+ by4 = (by1 >> 2) & 0xff;
+ by5 = (((by1 & 0x3) << 4) | (by2 >> 4)) & 0xff;
+ by6 = (((by2 & 0xf) << 2) | (by3 >> 6)) & 0xff;
+ by7 = by3 & 0x3f;
+
+ retval.append(encode((byte)by4));
+ retval.append(encode((byte)by5));
+
+ if((i + 1) < plainSeq.length)
+ {
+ retval.append(encode((byte)by6));
+ }
+ else
+ {
+ retval.append('=');
+ }
+
+ if((i + 2) < plainSeq.length)
+ {
+ retval.append(encode((byte)by7));
+ }
+ else
+ {
+ retval.append('=');
+ }
+ }
+
+ StringBuilder outString = new StringBuilder(totalBytes);
+ int iter = 0;
+
+ while((retval.length() - iter) > 76)
+ {
+ outString.append(retval.substring(iter, iter + 76));
+ outString.append("\r\n");
+ iter += 76;
+ }
+
+ outString.append(retval.substring(iter));
+
+ return outString.toString();
+}
+
+public static byte[]
+decode(String str)
+{
+ StringBuilder newStr = new StringBuilder(str.length());
+
+ for(int j = 0; j < str.length(); j++)
+ {
+ char c = str.charAt(j);
+ if(isBase64(c))
+ {
+ newStr.append(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.
+ int totalBytes = (newStr.length() * 3 / 4) + 1;
+
+ java.nio.ByteBuffer retval = java.nio.ByteBuffer.allocate(totalBytes);
+
+ int by1;
+ int by2;
+ int by3;
+ int by4;
+
+ char c1, c2, c3, c4;
+
+ int pos = 0;
+ for(int i = 0; i < newStr.length(); i += 4)
+ {
+ c1 = 'A';
+ c2 = 'A';
+ c3 = 'A';
+ c4 = 'A';
+
+ c1 = newStr.charAt(i);
+
+ if((i + 1) < newStr.length())
+ {
+ c2 = newStr.charAt(i + 1);
+ }
+
+ if((i + 2) < newStr.length())
+ {
+ c3 = newStr.charAt(i + 2);
+ }
+
+ if((i + 3) < newStr.length())
+ {
+ c4 = newStr.charAt(i + 3);
+ }
+
+ by1 = decode(c1) & 0xff;
+ by2 = decode(c2) & 0xff;
+ by3 = decode(c3) & 0xff;
+ by4 = decode(c4) & 0xff;
+
+ retval.put((byte)((by1 << 2) | (by2 >> 4)));
+ ++pos;
+
+ if(c3 != '=')
+ {
+ retval.put((byte)(((by2 & 0xf) << 4) | (by3 >> 2)));
+ ++pos;
+ }
+
+ if(c4 != '=')
+ {
+ retval.put((byte)(((by3 & 0x3) << 6) | by4));
+ ++pos;
+ }
+ }
+
+ byte[] arr = new byte[pos];
+ System.arraycopy(retval.array(), 0, arr, 0, pos);
+ return arr;
+}
+
+public static boolean
+isBase64(char 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;
+}
+
+private static char
+encode(byte uc)
+{
+ if(uc < 26)
+ {
+ return (char)('A' + uc);
+ }
+
+ if(uc < 52)
+ {
+ return (char)('a' + (uc - 26));
+ }
+
+ if(uc < 62)
+ {
+ return (char)('0' + (uc - 52));
+ }
+
+ if(uc == 62)
+ {
+ return '+';
+ }
+
+ return '/';
+}
+
+private static byte
+decode(char c)
+{
+ if(c >= 'A' && c <= 'Z')
+ {
+ return (byte)(c - 'A');
+ }
+
+ if(c >= 'a' && c <= 'z')
+ {
+ return (byte)(c - 'a' + 26);
+ }
+
+ if(c >= '0' && c <= '9')
+ {
+ return (byte)(c - '0' + 52);
+ }
+
+ if(c == '+')
+ {
+ return 62;
+ }
+
+ return 63;
+}
+
+}
diff --git a/java-compat/src/Ice/src/main/java/IceUtilInternal/Options.java b/java-compat/src/Ice/src/main/java/IceUtilInternal/Options.java
new file mode 100644
index 00000000000..a16c0ed56ac
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceUtilInternal/Options.java
@@ -0,0 +1,403 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceUtilInternal;
+
+public final class Options
+{
+ static public final class BadQuote extends Exception
+ {
+ BadQuote(String message)
+ {
+ super(message);
+ }
+ }
+
+ static public String[]
+ split(String line)
+ throws BadQuote
+ {
+ final String IFS = " \t\n";
+ final int NormalState = 1;
+ final int DoubleQuoteState = 2;
+ final int SingleQuoteState = 3;
+ final int ANSIQuoteState = 4;
+
+ line = line.trim();
+ if(line.length() == 0)
+ {
+ return new String[0];
+ }
+
+ int state = NormalState;
+
+ StringBuilder arg = new StringBuilder(128);
+ java.util.List<String> vec = new java.util.ArrayList<String>();
+
+ for(int i = 0; i < line.length(); ++i)
+ {
+ char c = line.charAt(i);
+ switch(state)
+ {
+ case NormalState:
+ {
+ switch(c)
+ {
+ case '\\':
+ {
+ //
+ // Ignore a backslash at the end of the string,
+ // and strip backslash-newline pairs. If a
+ // backslash is followed by a space, single quote,
+ // double quote, or dollar sign, we drop the backslash
+ // and write the space, single quote, double quote,
+ // or dollar sign. This is necessary to allow quotes
+ // to be escaped. Dropping the backslash preceding a
+ // space deviates from bash quoting rules, but is
+ // necessary so we don't drop backslashes from Windows
+ // path names.)
+ //
+ if(i < line.length() - 1 && line.charAt(++i) != '\n')
+ {
+ switch(line.charAt(i))
+ {
+ case ' ':
+ case '$':
+ case '\\':
+ case '"':
+ {
+ arg.append(line.charAt(i));
+ break;
+ }
+ default:
+ {
+ arg.append('\\');
+ arg.append(line.charAt(i));
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case '\'':
+ {
+ state = SingleQuoteState;
+ break;
+ }
+ case '"':
+ {
+ state = DoubleQuoteState;
+ break;
+ }
+ case '$':
+ {
+ if(i < line.length() - 1 && line.charAt(i + 1) == '\'')
+ {
+ state = ANSIQuoteState; // Bash uses $'<text>' to allow ANSI escape sequences within <text>.
+ ++i;
+ }
+ else
+ {
+ arg.append('$');
+ }
+ break;
+ }
+ default:
+ {
+ if(IFS.indexOf(line.charAt(i)) != -1)
+ {
+ vec.add(arg.toString());
+ arg = new StringBuilder(128);
+
+ //
+ // Move to start of next argument.
+ //
+ while(++i < line.length() && IFS.indexOf(line.charAt(i)) != -1);
+ --i;
+ }
+ else
+ {
+ arg.append(line.charAt(i));
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case DoubleQuoteState:
+ {
+ //
+ // Within double quotes, only backslash retains its special
+ // meaning, and only if followed by double quote, backslash,
+ // or newline. If not followed by one of these characters,
+ // both the backslash and the character are preserved.
+ //
+ if(c == '\\' && i < line.length() - 1)
+ {
+ switch(c = line.charAt(++i))
+ {
+ case '"':
+ case '\\':
+ case '\n':
+ {
+ arg.append(c);
+ break;
+ }
+ default:
+ {
+ arg.append('\\');
+ arg.append(c);
+ break;
+ }
+ }
+ }
+ else if(c == '"') // End of double-quote mode.
+ {
+ state = NormalState;
+ }
+ else
+ {
+ arg.append(c); // Everything else is taken literally.
+ }
+ break;
+ }
+ case SingleQuoteState:
+ {
+ if(c == '\'') // End of single-quote mode.
+ {
+ state = NormalState;
+ }
+ else
+ {
+ arg.append(c); // Everything else is taken literally.
+ }
+ break;
+ }
+ case ANSIQuoteState:
+ {
+ switch(c)
+ {
+ case '\\':
+ {
+ if(i == line.length() - 1)
+ {
+ break;
+ }
+ switch(c = line.charAt(++i))
+ {
+ //
+ // Single-letter escape sequences.
+ //
+ case 'a':
+ {
+ arg.append('\007');
+ break;
+ }
+ case 'b':
+ {
+ arg.append('\b');
+ break;
+ }
+ case 'f':
+ {
+ arg.append('\f');
+ break;
+ }
+ case 'n':
+ {
+ arg.append('\n');
+ break;
+ }
+ case 'r':
+ {
+ arg.append('\r');
+ break;
+ }
+ case 't':
+ {
+ arg.append('\t');
+ break;
+ }
+ case 'v':
+ {
+ arg.append('\013');
+ break;
+ }
+ case '\\':
+ {
+ arg.append('\\');
+ break;
+ }
+ case '\'':
+ {
+ arg.append('\'');
+ break;
+ }
+ case 'e': // Not ANSI-C, but used by bash.
+ {
+ arg.append('\033');
+ break;
+ }
+
+ //
+ // Process up to three octal digits.
+ //
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ final String octalDigits = "01234567";
+ short us = 0;
+ int j;
+ for(j = i;
+ j < i + 3 && j < line.length() && octalDigits.indexOf(c = line.charAt(j)) != -1;
+ ++j)
+ {
+ us = (short)(us * 8 + c - '0');
+ }
+ i = j - 1;
+ arg.append((char)us);
+ break;
+ }
+
+ //
+ // Process up to two hex digits.
+ //
+ case 'x':
+ {
+ final String hexDigits = "0123456789abcdefABCDEF";
+ if(i < line.length() - 1 && hexDigits.indexOf(line.charAt(i + 1)) == -1)
+ {
+ arg.append('\\');
+ arg.append('x');
+ break;
+ }
+
+ short s = 0;
+ int j;
+ for(j = i + 1;
+ j < i + 3 && j < line.length() && hexDigits.indexOf(c = line.charAt(j)) != -1;
+ ++j)
+ {
+ s *= 16;
+ if(Character.isDigit(c))
+ {
+ s += (short)(c - '0');
+ }
+ else if(Character.isLowerCase(c))
+ {
+ s += (short)(c - 'a' + 10);
+ }
+ else
+ {
+ s += (short)(c - 'A' + 10);
+ }
+ }
+ i = j - 1;
+ arg.append((char)s);
+ break;
+ }
+
+ //
+ // Process control-chars.
+ //
+ case 'c':
+ {
+ c = line.charAt(++i);
+ if((Character.toUpperCase(c) >= 'A' && Character.toUpperCase(c) <= 'Z') ||
+ c == '@' ||
+ (c >= '[' && c <= '_'))
+ {
+ arg.append((char)(Character.toUpperCase(c) - '@'));
+ }
+ else
+ {
+ //
+ // Bash does not define what should happen if a \c
+ // is not followed by a recognized control character.
+ // We simply treat this case like other unrecognized
+ // escape sequences, that is, we preserve the escape
+ // sequence unchanged.
+ //
+ arg.append('\\');
+ arg.append('c');
+ arg.append(c);
+ }
+ break;
+ }
+
+ //
+ // If inside an ANSI-quoted string, a backslash isn't followed by
+ // one of the recognized characters, both the backslash and the
+ // character are preserved.
+ //
+ default:
+ {
+ arg.append('\\');
+ arg.append(c);
+ break;
+ }
+ }
+ break;
+ }
+ case '\'': // End of ANSI-quote mode.
+ {
+ state = NormalState;
+ break;
+ }
+ default:
+ {
+ arg.append(c); // Everything else is taken literally.
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ assert(false);
+ break;
+ }
+ }
+
+ switch(state)
+ {
+ case NormalState:
+ {
+ vec.add(arg.toString());
+ break;
+ }
+ case SingleQuoteState:
+ {
+ throw new BadQuote("missing closing single quote");
+ }
+ case DoubleQuoteState:
+ {
+ throw new BadQuote("missing closing double quote");
+ }
+ case ANSIQuoteState:
+ {
+ throw new BadQuote("unterminated $' quote");
+ }
+ default:
+ {
+ assert(false);
+ break;
+ }
+ }
+
+ return vec.toArray(new String[0]);
+ }
+
+
+}
diff --git a/java-compat/src/Ice/src/main/java/IceUtilInternal/OutputBase.java b/java-compat/src/Ice/src/main/java/IceUtilInternal/OutputBase.java
new file mode 100644
index 00000000000..7638be77c0b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceUtilInternal/OutputBase.java
@@ -0,0 +1,188 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceUtilInternal;
+
+public class OutputBase
+{
+ public
+ OutputBase()
+ {
+ _out = null;
+ _pos = 0;
+ _indent = 0;
+ _indentSize = 4;
+ _useTab = true;
+ _separator = true;
+ }
+
+ public
+ OutputBase(java.io.PrintWriter out)
+ {
+ _out = out;
+ _pos = 0;
+ _indent = 0;
+ _indentSize = 4;
+ _useTab = true;
+ _separator = true;
+ }
+
+ public
+ OutputBase(String s)
+ {
+ _out = null;
+ _pos = 0;
+ _indent = 0;
+ _indentSize = 4;
+ _useTab = true;
+ _separator = true;
+
+ open(s);
+ }
+
+ public void
+ setIndent(int indentSize)
+ {
+ _indentSize = indentSize;
+ }
+
+ public void
+ setUseTab(boolean useTab)
+ {
+ _useTab = useTab;
+ }
+
+ public void
+ open(String s)
+ {
+ try
+ {
+ java.io.FileWriter fw = new java.io.FileWriter(s);
+ java.io.BufferedWriter bw = new java.io.BufferedWriter(fw);
+ _out = new java.io.PrintWriter(bw);
+ }
+ catch(java.io.IOException ex)
+ {
+ }
+ }
+
+ public void
+ print(String s)
+ {
+ final char[] arr = s.toCharArray();
+ for(int i = 0; i < arr.length; i++)
+ {
+ if(arr[i] == '\n')
+ {
+ _pos = 0;
+ }
+ else
+ {
+ ++_pos;
+ }
+ }
+
+ _out.print(s);
+ }
+
+ public void
+ inc()
+ {
+ _indent += _indentSize;
+ }
+
+ public void
+ dec()
+ {
+ assert(_indent >= _indentSize);
+ _indent -= _indentSize;
+ }
+
+ public void
+ useCurrentPosAsIndent()
+ {
+ _indentSave.addFirst(_indent);
+ _indent = _pos;
+ }
+
+ public void
+ zeroIndent()
+ {
+ _indentSave.addFirst(_indent);
+ _indent = 0;
+ }
+
+ public void
+ restoreIndent()
+ {
+ assert(!_indentSave.isEmpty());
+ _indent = _indentSave.removeFirst().intValue();
+ }
+
+ public void
+ nl()
+ {
+ _out.println();
+ _pos = 0;
+ _separator = true;
+
+ int indent = _indent;
+
+ if(_useTab)
+ {
+ while(indent >= 8)
+ {
+ indent -= 8;
+ _out.print('\t');
+ _pos += 8;
+ }
+ }
+ else
+ {
+ while(indent >= _indentSize)
+ {
+ indent -= _indentSize;
+ _out.print(" ");
+ _pos += _indentSize;
+ }
+ }
+
+ while(indent > 0)
+ {
+ --indent;
+ _out.print(' ');
+ ++_pos;
+ }
+
+ _out.flush();
+ }
+
+ public void
+ sp()
+ {
+ if(_separator)
+ {
+ _out.println();
+ }
+ }
+
+ public boolean
+ valid()
+ {
+ return (_out != null);
+ }
+
+ protected java.io.PrintWriter _out;
+ protected int _pos;
+ protected int _indent;
+ protected int _indentSize;
+ protected java.util.LinkedList<Integer> _indentSave = new java.util.LinkedList<Integer>();
+ protected boolean _useTab;
+ protected boolean _separator;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceUtilInternal/StopWatch.java b/java-compat/src/Ice/src/main/java/IceUtilInternal/StopWatch.java
new file mode 100644
index 00000000000..137a8cad364
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceUtilInternal/StopWatch.java
@@ -0,0 +1,42 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceUtilInternal;
+
+public class StopWatch
+{
+ public void
+ start()
+ {
+ _s = System.nanoTime();
+ }
+
+ public long
+ stop()
+ {
+ assert(isStarted());
+ long d = (System.nanoTime() - _s) / 1000;
+ _s = 0;
+ return d;
+ }
+
+ public boolean
+ isStarted()
+ {
+ return _s != 0;
+ }
+
+ public long
+ delay()
+ {
+ return (System.nanoTime() - _s) / 1000;
+ }
+
+ private long _s = 0;
+}
diff --git a/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java b/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java
new file mode 100644
index 00000000000..953359c5c4b
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java
@@ -0,0 +1,540 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceUtilInternal;
+
+public final class StringUtil
+{
+ //
+ // Return the index of the first character in str to
+ // appear in match, starting from 0. Returns -1 if none is
+ // found.
+ //
+ public static int
+ findFirstOf(String str, String match)
+ {
+ return findFirstOf(str, match, 0);
+ }
+
+ //
+ // Return the index of the first character in str to
+ // appear in match, starting from start. Returns -1 if none is
+ // found.
+ //
+ public static int
+ findFirstOf(String str, String match, int start)
+ {
+ final int len = str.length();
+ for(int i = start; i < len; i++)
+ {
+ char 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 0. Returns -1 if none is
+ // found.
+ //
+ public static int
+ findFirstNotOf(String str, String match)
+ {
+ return findFirstNotOf(str, match, 0);
+ }
+
+ //
+ // Return the index of the first character in str which does
+ // not appear in match, starting from start. Returns -1 if none is
+ // found.
+ //
+ public static int
+ findFirstNotOf(String str, String match, int start)
+ {
+ final int len = str.length();
+ for(int i = start; i < len; i++)
+ {
+ char 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.
+ //
+ private static void
+ encodeChar(byte b, StringBuilder sb, String special)
+ {
+ switch(b)
+ {
+ case (byte)'\\':
+ {
+ sb.append("\\\\");
+ break;
+ }
+ case (byte)'\'':
+ {
+ sb.append("\\'");
+ break;
+ }
+ case (byte)'"':
+ {
+ sb.append("\\\"");
+ break;
+ }
+ case (byte)'\b':
+ {
+ sb.append("\\b");
+ break;
+ }
+ case (byte)'\f':
+ {
+ sb.append("\\f");
+ break;
+ }
+ case (byte)'\n':
+ {
+ sb.append("\\n");
+ break;
+ }
+ case (byte)'\r':
+ {
+ sb.append("\\r");
+ break;
+ }
+ case (byte)'\t':
+ {
+ sb.append("\\t");
+ break;
+ }
+ default:
+ {
+ if(!(b >= 32 && b <= 126))
+ {
+ sb.append('\\');
+ String octal = Integer.toOctalString(b < 0 ? b + 256 : b);
+ //
+ // 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(int j = octal.length(); j < 3; j++)
+ {
+ sb.append('0');
+ }
+ sb.append(octal);
+ }
+ else if(special != null && special.indexOf((char)b) != -1)
+ {
+ sb.append('\\');
+ sb.append((char)b);
+ }
+ else
+ {
+ sb.append((char)b);
+ }
+ }
+ }
+ }
+
+ //
+ // 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.
+ //
+ public static String
+ escapeString(String s, String special)
+ {
+ if(special != null)
+ {
+ for(int i = 0; i < special.length(); ++i)
+ {
+ if(special.charAt(i) < 32 || special.charAt(i) > 126)
+ {
+ throw new IllegalArgumentException("special characters must be in ASCII range 32-126");
+ }
+ }
+ }
+
+ byte[] bytes = null;
+ try
+ {
+ bytes = s.getBytes("UTF8");
+ }
+ catch(java.io.UnsupportedEncodingException ex)
+ {
+ assert(false);
+ return null;
+ }
+
+ StringBuilder result = new StringBuilder(bytes.length);
+ for(int i = 0; i < bytes.length; i++)
+ {
+ encodeChar(bytes[i], result, special);
+ }
+
+ return result.toString();
+ }
+
+ private static char
+ checkChar(String s, int pos)
+ {
+ char c = s.charAt(pos);
+ if(!(c >= 32 && c <= 126))
+ {
+ String msg;
+ if(pos > 0)
+ {
+ msg = "character after `" + s.substring(0, pos) + "'";
+ }
+ else
+ {
+ msg = "first character";
+ }
+ msg += " is not a printable ASCII character (ordinal " + (int)c + ")";
+ throw new IllegalArgumentException(msg);
+ }
+ return c;
+ }
+
+ //
+ // Decode the character or escape sequence starting at start and return it.
+ // newStart is set to the index of the first character following the decoded character
+ // or escape sequence.
+ //
+ private static char decodeChar(String s, int start, int end, Ice.Holder<Integer> nextStart)
+ {
+ assert(start >= 0);
+ assert(start < end);
+ assert(end <= s.length());
+
+ char c;
+
+ if(s.charAt(start) != '\\')
+ {
+ c = checkChar(s, start++);
+ }
+ else
+ {
+ if(start + 1 == end)
+ {
+ throw new IllegalArgumentException("trailing backslash");
+ }
+ switch(s.charAt(++start))
+ {
+ case '\\':
+ case '\'':
+ case '"':
+ {
+ c = s.charAt(start++);
+ break;
+ }
+ case 'b':
+ {
+ ++start;
+ c = '\b';
+ break;
+ }
+ case 'f':
+ {
+ ++start;
+ c = '\f';
+ break;
+ }
+ case 'n':
+ {
+ ++start;
+ c = '\n';
+ break;
+ }
+ case 'r':
+ {
+ ++start;
+ c = '\r';
+ break;
+ }
+ case 't':
+ {
+ ++start;
+ c = '\t';
+ break;
+ }
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ int val = 0;
+ for(int j = 0; j < 3 && start < end; ++j)
+ {
+ int charVal = s.charAt(start++) - '0';
+ if(charVal < 0 || charVal > 7)
+ {
+ --start;
+ break;
+ }
+ val = val * 8 + charVal;
+ }
+ if(val > 255)
+ {
+ String msg = "octal value \\" + Integer.toOctalString(val) + " (" + val + ") is out of range";
+ throw new IllegalArgumentException(msg);
+ }
+ c = (char)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.
+ //
+ private static void
+ decodeString(String s, int start, int end, StringBuilder sb)
+ {
+ Ice.Holder<Integer> nextStart = new Ice.Holder<Integer>();
+ while(start < end)
+ {
+ sb.append(decodeChar(s, start, end, nextStart));
+ start = nextStart.value;
+ }
+ }
+
+ //
+ // Remove escape sequences added by escapeString. Throws IllegalArgumentException
+ // for an invalid input string.
+ //
+ public static String
+ unescapeString(String s, int start, int end)
+ {
+ assert(start >= 0 && start <= end && end <= s.length());
+
+ StringBuilder sb = new StringBuilder(end - start);
+ decodeString(s, start, end, sb);
+ String decodedString = sb.toString();
+
+ byte[] arr = new byte[decodedString.length()];
+ for(int i = 0; i < arr.length; ++i)
+ {
+ arr[i] = (byte)decodedString.charAt(i);
+ }
+
+ try
+ {
+ return new String(arr, 0, arr.length, "UTF8");
+ }
+ catch(java.io.UnsupportedEncodingException ex)
+ {
+ throw new IllegalArgumentException("unsupported encoding", ex);
+ }
+ }
+
+ //
+ // Join a list of strings using the given delimiter.
+ //
+ public static String
+ joinString(java.util.List<String> values, String delimiter)
+ {
+ StringBuffer s = new StringBuffer();
+ boolean first = true;
+ for(String v : values)
+ {
+ if(!first)
+ {
+ s.append(delimiter);
+ }
+ s.append(v);
+ first = false;
+ }
+ return s.toString();
+ }
+
+ //
+ // Split string helper; returns null for unmatched quotes
+ //
+ static public String[]
+ splitString(String str, String delim)
+ {
+ java.util.List<String> l = new java.util.ArrayList<String>();
+ char[] arr = new char[str.length()];
+ int pos = 0;
+
+ int n = 0;
+ char quoteChar = '\0';
+ while(pos < str.length())
+ {
+ if(quoteChar == '\0' && (str.charAt(pos) == '"' || str.charAt(pos) == '\''))
+ {
+ quoteChar = str.charAt(pos++);
+ continue; // Skip the quote.
+ }
+ else if(quoteChar == '\0' && str.charAt(pos) == '\\' && pos + 1 < str.length() &&
+ (str.charAt(pos + 1) == '"' || str.charAt(pos + 1) == '\''))
+ {
+ ++pos; // Skip the backslash
+ }
+ else if(quoteChar != '\0' && str.charAt(pos) == '\\' && pos + 1 < str.length() &&
+ str.charAt(pos + 1) == quoteChar)
+ {
+ ++pos; // Skip the backslash
+ }
+ else if(quoteChar != '\0' && str.charAt(pos) == quoteChar)
+ {
+ ++pos;
+ quoteChar = '\0';
+ continue; // Skip the quote.
+ }
+ else if(delim.indexOf(str.charAt(pos)) != -1)
+ {
+ if(quoteChar == '\0')
+ {
+ ++pos;
+ if(n > 0)
+ {
+ l.add(new String(arr, 0, n));
+ n = 0;
+ }
+ continue;
+ }
+ }
+
+ if(pos < str.length())
+ {
+ arr[n++] = str.charAt(pos++);
+ }
+ }
+
+ if(n > 0)
+ {
+ l.add(new String(arr, 0, n));
+ }
+ if(quoteChar != '\0')
+ {
+ return null; // Unmatched quote.
+ }
+ return l.toArray(new String[0]);
+ }
+
+ public static int
+ checkQuote(String s)
+ {
+ return checkQuote(s, 0);
+ }
+
+ //
+ // 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.
+ //
+ public static int
+ checkQuote(String s, int start)
+ {
+ char quoteChar = s.charAt(start);
+ if(quoteChar == '"' || quoteChar == '\'')
+ {
+ start++;
+ final int len = s.length();
+ int 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
+ }
+
+ public static boolean
+ match(String s, String pat, boolean emptyMatch)
+ {
+ assert(s.length() > 0);
+ assert(pat.length() > 0);
+
+ //
+ // If pattern does not contain a wildcard just compare strings.
+ //
+ int beginIndex = pat.indexOf('*');
+ if(beginIndex < 0)
+ {
+ return s.equals(pat);
+ }
+
+ //
+ // Make sure start of the strings match
+ //
+ if(beginIndex > s.length() || !s.substring(0, beginIndex).equals(pat.substring(0, beginIndex)))
+ {
+ return false;
+ }
+
+ //
+ // Make sure there is something present in the middle to match the
+ // wildcard. If emptyMatch is true, allow a match of "".
+ //
+ int endLength = pat.length() - beginIndex - 1;
+ if(endLength == 0)
+ {
+ return true;
+ }
+ if(endLength > s.length())
+ {
+ return false;
+ }
+ int endIndex = s.length() - endLength;
+ if(endIndex < beginIndex || (!emptyMatch && endIndex == beginIndex))
+ {
+ return false;
+ }
+
+ //
+ // Make sure end of the strings match
+ //
+ if(!s.substring(endIndex, s.length() - endIndex).equals(
+ pat.substring(beginIndex + 1, pat.length() - beginIndex - 1)))
+ {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/java-compat/src/Ice/src/main/java/IceUtilInternal/XMLOutput.java b/java-compat/src/Ice/src/main/java/IceUtilInternal/XMLOutput.java
new file mode 100644
index 00000000000..8d6f4ab9569
--- /dev/null
+++ b/java-compat/src/Ice/src/main/java/IceUtilInternal/XMLOutput.java
@@ -0,0 +1,275 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceUtilInternal;
+
+public class XMLOutput extends OutputBase
+{
+ public
+ XMLOutput()
+ {
+ super();
+ _se = false;
+ _text = false;
+ _sgml = false;
+ _escape = false;
+ }
+
+ public
+ XMLOutput(java.io.PrintWriter writer)
+ {
+ super(writer);
+ _se = false;
+ _text = false;
+ _sgml = false;
+ _escape = false;
+ }
+
+ public
+ XMLOutput(String s)
+ {
+ super(s);
+ _se = false;
+ _text = false;
+ _sgml = false;
+ _escape = false;
+ }
+
+ public void
+ setSGML(boolean sgml)
+ {
+ _sgml = true;
+ }
+
+ @Override
+ public void
+ print(String s)
+ {
+ if(_se)
+ {
+ _out.print('>');
+ _se = false;
+ }
+ _text = true;
+
+ if(_escape)
+ {
+ String escaped = escape(s);
+ super.print(escaped);
+ }
+ else
+ {
+ super.print(s);
+ }
+ }
+
+ public XMLOutput
+ write(String s)
+ {
+ print(s);
+ return this;
+ }
+
+ @Override
+ public void
+ nl()
+ {
+ if(_se)
+ {
+ _se = false;
+ _out.print('>');
+ }
+ super.nl();
+ }
+
+ public XMLOutput
+ se(String element)
+ {
+ nl();
+
+ //
+ // If we're not in SGML mode the output of the '>' character is
+ // deferred until either the end-element (in which case a /> is
+ // emitted) or until something is displayed.
+ //
+ if(_escape)
+ {
+ _out.print('<');
+ _out.print(escape(element));
+ }
+ else
+ {
+ _out.print('<');
+ _out.print(element);
+ }
+ _se = true;
+ _text = false;
+
+ int pos = element.indexOf(' ');
+ if(pos == -1)
+ {
+ pos = element.indexOf('\t');
+ }
+ if(pos == -1)
+ {
+ _elementStack.addFirst(element);
+ }
+ else
+ {
+ _elementStack.addFirst(element.substring(0, pos));
+ }
+
+ ++_pos; // TODO: ???
+ inc();
+ _separator = false;
+ return this;
+ }
+
+ public XMLOutput
+ ee()
+ {
+ String element = _elementStack.removeFirst();
+
+ dec();
+ if(_se)
+ {
+ //
+ // SGML (docbook) doesn't support <foo/>
+ //
+ if(_sgml)
+ {
+ _out.print("></");
+ _out.print(element);
+ _out.print(">");
+ }
+ else
+ {
+ _out.print("/>");
+ }
+ }
+ else
+ {
+ if(!_text)
+ {
+ nl();
+ }
+ _out.print("</");
+ _out.print(element);
+ _out.print(">");
+ }
+ --_pos; // TODO: ???
+
+ _se = false;
+ _text = false;
+ return this;
+ }
+
+ public XMLOutput
+ attr(String name, String value)
+ {
+ //
+ // Precondition: Attributes can only be attached to elements.
+ //
+ assert(_se);
+ _out.print(" ");
+ _out.print(name);
+ _out.print("=\"");
+ _out.print(escape(value));
+ _out.print("\"");
+ return this;
+ }
+
+ public XMLOutput
+ startEscapes()
+ {
+ _escape = true;
+ return this;
+ }
+
+ public XMLOutput
+ endEscapes()
+ {
+ _escape = false;
+ return this;
+ }
+
+ public String
+ currentElement()
+ {
+ if(_elementStack.size() > 0)
+ {
+ return _elementStack.getFirst();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ private String
+ escape(String input)
+ {
+ String v = input;
+
+ //
+ // Find out whether there is a reserved character to avoid
+ // conversion if not necessary.
+ //
+ final String allReserved = "<>'\"&";
+ boolean hasReserved = false;
+ char[] arr = input.toCharArray();
+ for(int i = 0; i < arr.length; i++)
+ {
+ if(allReserved.indexOf(arr[i]) != -1)
+ {
+ hasReserved = true;
+ break;
+ }
+ }
+ if(hasReserved)
+ {
+ //
+ // First convert all & to &amp;
+ //
+ if(v.indexOf('&') != -1)
+ {
+ v = v.replaceAll("&", "&amp;");
+ }
+
+ //
+ // Next convert remaining reserved characters.
+ //
+ if(v.indexOf('>') != -1)
+ {
+ v = v.replaceAll(">", "&gt;");
+ }
+ if(v.indexOf('<') != -1)
+ {
+ v = v.replaceAll("<", "&lt;");
+ }
+ if(v.indexOf('\'') != -1)
+ {
+ v = v.replaceAll("'", "&apos;");
+ }
+ if(v.indexOf('"') != -1)
+ {
+ v = v.replaceAll("\"", "&quot;");
+ }
+ }
+ return v;
+ }
+
+ private java.util.LinkedList<String> _elementStack = new java.util.LinkedList<String>();
+
+ boolean _se;
+ boolean _text;
+
+ private boolean _sgml;
+ private boolean _escape;
+}
diff --git a/java-compat/src/IceBT/build.gradle b/java-compat/src/IceBT/build.gradle
new file mode 100644
index 00000000000..190900f0f07
--- /dev/null
+++ b/java-compat/src/IceBT/build.gradle
@@ -0,0 +1,37 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+sourceCompatibility = iceSourceCompatibility
+targetCompatibility = iceTargetCompatibility
+
+project.ext.displayName = "IceBT Compat"
+project.ext.description = "Bluetooth support for Ice"
+
+slice {
+ java {
+ set1 {
+ args = "--ice"
+ files = fileTree(dir: "$sliceDir/IceBT", includes:['*.ice'], excludes:["*F.ice"])
+ }
+ }
+}
+
+dependencies {
+ compile project(':ice-compat')
+}
+
+apply from: "$rootProject.projectDir/../java/gradle/library.gradle"
+
+jar {
+ //
+ // The classes in src/main/java/android/bluetooth are stubs that allow us to compile the IceBT transport
+ // plug-in without requiring an Android SDK. These classes are excluded from the IceBT JAR file.
+ //
+ exclude("android/**")
+}
diff --git a/java-compat/src/IceBT/src/main/java/IceBT/AcceptorI.java b/java-compat/src/IceBT/src/main/java/IceBT/AcceptorI.java
new file mode 100644
index 00000000000..553e13ae149
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/IceBT/AcceptorI.java
@@ -0,0 +1,224 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBT;
+
+import android.bluetooth.BluetoothSocket;
+import android.bluetooth.BluetoothServerSocket;
+import java.util.UUID;
+
+final class AcceptorI implements IceInternal.Acceptor
+{
+ @Override
+ public java.nio.channels.ServerSocketChannel fd()
+ {
+ return null;
+ }
+
+ @Override
+ public void setReadyCallback(IceInternal.ReadyCallback callback)
+ {
+ _readyCallback = callback;
+ }
+
+ @Override
+ public void close()
+ {
+ synchronized(this)
+ {
+ _closed = true;
+ }
+
+ if(_socket != null)
+ {
+ try
+ {
+ _socket.close(); // Wakes up the thread blocked in accept().
+ }
+ catch(Exception ex)
+ {
+ // Ignore.
+ }
+ }
+ if(_thread != null)
+ {
+ try
+ {
+ _thread.join();
+ }
+ catch(Exception ex)
+ {
+ // Ignore.
+ }
+ }
+ }
+
+ @Override
+ public IceInternal.EndpointI listen()
+ {
+ try
+ {
+ //
+ // We always listen using the "secure" method.
+ //
+ _socket = _instance.bluetoothAdapter().listenUsingRfcommWithServiceRecord(_name, _uuid);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+
+ //
+ // Use a helper thread to perform the blocking accept() calls.
+ //
+ _thread = new Thread()
+ {
+ public void run()
+ {
+ runAccept();
+ }
+ };
+ _thread.start();
+
+ return _endpoint;
+ }
+
+ @Override
+ public synchronized IceInternal.Transceiver accept()
+ {
+ if(_exception != null)
+ {
+ throw new Ice.SocketException(_exception);
+ }
+
+ //
+ // accept() should only be called when we have at least one socket ready.
+ //
+ assert(!_pending.isEmpty());
+
+ BluetoothSocket socket = _pending.pop();
+
+ //
+ // Update our status with the thread pool.
+ //
+ _readyCallback.ready(IceInternal.SocketOperation.Read, !_pending.isEmpty());
+
+ return new TransceiverI(_instance, socket, _uuid, _adapterName);
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer("local address = ");
+ s.append(_instance.bluetoothAdapter().getAddress());
+ return s.toString();
+ }
+
+ @Override
+ public String toDetailedString()
+ {
+ StringBuffer s = new StringBuffer(toString());
+ if(!_name.isEmpty())
+ {
+ s.append("\nservice name = '");
+ s.append(_name);
+ s.append("'");
+ }
+ if(_uuid != null)
+ {
+ s.append("\nservice uuid = ");
+ s.append(_uuid.toString());
+ }
+ return s.toString();
+ }
+
+ AcceptorI(EndpointI endpoint, Instance instance, String adapterName, UUID uuid, String name)
+ {
+ _endpoint = endpoint;
+ _instance = instance;
+ _adapterName = adapterName;
+ _name = name;
+ _uuid = uuid;
+
+ _pending = new java.util.Stack<BluetoothSocket>();
+ _closed = false;
+ }
+
+ private void runAccept()
+ {
+ try
+ {
+ while(true)
+ {
+ BluetoothSocket socket = _socket.accept();
+ synchronized(this)
+ {
+ _pending.push(socket);
+
+ //
+ // Notify the thread pool that we are ready to "read". The thread pool will invoke accept()
+ // and we can return a new transceiver.
+ //
+ _readyCallback.ready(IceInternal.SocketOperation.Read, true);
+ }
+ }
+ }
+ catch(Exception ex)
+ {
+ synchronized(this)
+ {
+ if(!_closed)
+ {
+ _exception = ex;
+ _readyCallback.ready(IceInternal.SocketOperation.Read, true);
+ }
+ }
+ }
+
+ //
+ // Close any remaining incoming sockets that haven't been accepted yet.
+ //
+ java.util.Stack<BluetoothSocket> pending;
+ synchronized(this)
+ {
+ pending = _pending;
+ _pending = null;
+ }
+
+ for(BluetoothSocket s : pending)
+ {
+ try
+ {
+ s.close();
+ }
+ catch(Exception ex)
+ {
+ // Ignore.
+ }
+ }
+ }
+
+ private EndpointI _endpoint;
+ private Instance _instance;
+ private String _adapterName;
+ private String _name;
+ private UUID _uuid;
+ private IceInternal.ReadyCallback _readyCallback;
+ private BluetoothServerSocket _socket;
+ private java.util.Stack<BluetoothSocket> _pending;
+ private Thread _thread;
+ private Exception _exception;
+ private boolean _closed;
+}
diff --git a/java-compat/src/IceBT/src/main/java/IceBT/ConnectorI.java b/java-compat/src/IceBT/src/main/java/IceBT/ConnectorI.java
new file mode 100644
index 00000000000..e8c8e8d47f5
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/IceBT/ConnectorI.java
@@ -0,0 +1,109 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBT;
+
+import java.util.UUID;
+
+final class ConnectorI implements IceInternal.Connector
+{
+ @Override
+ public IceInternal.Transceiver connect()
+ {
+ return new TransceiverI(_instance, _addr, _uuid, _connectionId);
+ }
+
+ @Override
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ if(!_addr.isEmpty())
+ {
+ buf.append(_addr);
+ }
+ if(_uuid != null)
+ {
+ if(!_addr.isEmpty())
+ {
+ buf.append(';');
+ }
+ buf.append(_uuid.toString());
+ }
+ return buf.toString();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return _hashCode;
+ }
+
+ //
+ // Only for use by EndpointI.
+ //
+ ConnectorI(Instance instance, String addr, UUID uuid, int timeout, String connectionId)
+ {
+ _instance = instance;
+ _addr = addr;
+ _uuid = uuid;
+ _timeout = timeout;
+ _connectionId = connectionId;
+
+ _hashCode = 5381;
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _addr);
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _uuid);
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _timeout);
+ _hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _connectionId);
+ }
+
+ @Override
+ public boolean equals(java.lang.Object obj)
+ {
+ if(!(obj instanceof ConnectorI))
+ {
+ return false;
+ }
+
+ if(this == obj)
+ {
+ return true;
+ }
+
+ ConnectorI p = (ConnectorI)obj;
+ if(!_uuid.equals(p._uuid))
+ {
+ return false;
+ }
+
+ if(_timeout != p._timeout)
+ {
+ return false;
+ }
+
+ if(!_connectionId.equals(p._connectionId))
+ {
+ return false;
+ }
+
+ return _addr.equals(p._addr);
+ }
+
+ private Instance _instance;
+ private String _addr;
+ private UUID _uuid;
+ private int _timeout;
+ private String _connectionId;
+ private int _hashCode;
+}
diff --git a/java-compat/src/IceBT/src/main/java/IceBT/EndpointFactoryI.java b/java-compat/src/IceBT/src/main/java/IceBT/EndpointFactoryI.java
new file mode 100644
index 00000000000..5ffc5141907
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/IceBT/EndpointFactoryI.java
@@ -0,0 +1,59 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBT;
+
+final class EndpointFactoryI implements IceInternal.EndpointFactory
+{
+ EndpointFactoryI(Instance instance)
+ {
+ _instance = instance;
+ }
+
+ @Override
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public IceInternal.EndpointI create(java.util.ArrayList<String> args, boolean oaEndpoint)
+ {
+ EndpointI endpt = new EndpointI(_instance);
+ endpt.initWithOptions(args, oaEndpoint);
+ return endpt;
+ }
+
+ @Override
+ public IceInternal.EndpointI read(Ice.InputStream s)
+ {
+ return new EndpointI(_instance, s);
+ }
+
+ @Override
+ public void destroy()
+ {
+ _instance.destroy();
+ _instance = null;
+ }
+
+ @Override
+ public IceInternal.EndpointFactory clone(IceInternal.ProtocolInstance inst, IceInternal.EndpointFactory del)
+ {
+ return new EndpointFactoryI(new Instance(_instance.communicator(), inst.type(), inst.protocol()));
+ }
+
+ private Instance _instance;
+}
diff --git a/java-compat/src/IceBT/src/main/java/IceBT/EndpointI.java b/java-compat/src/IceBT/src/main/java/IceBT/EndpointI.java
new file mode 100644
index 00000000000..7576f458fae
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/IceBT/EndpointI.java
@@ -0,0 +1,551 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBT;
+
+import android.bluetooth.BluetoothAdapter;
+import java.util.UUID;
+
+final class EndpointI extends IceInternal.EndpointI
+{
+ public EndpointI(Instance instance, String addr, UUID uuid, String name, int channel, int timeout,
+ String connectionId, boolean compress)
+ {
+ _instance = instance;
+ _addr = addr;
+ _uuid = uuid;
+ _name = name;
+ _channel = channel;
+ _timeout = timeout;
+ _connectionId = connectionId;
+ _compress = compress;
+ hashInit();
+ }
+
+ public EndpointI(Instance instance)
+ {
+ _instance = instance;
+ _addr = "";
+ _uuid = null;
+ _name = "";
+ _channel = 0;
+ _timeout = instance.defaultTimeout();
+ _connectionId = "";
+ _compress = false;
+ }
+
+ public EndpointI(Instance instance, Ice.InputStream s)
+ {
+ _instance = instance;
+
+ //
+ // _name and _channel are not marshaled.
+ //
+ _name = "";
+ _channel = 0;
+
+ _addr = s.readString().toUpperCase();
+ if(!BluetoothAdapter.checkBluetoothAddress(_addr))
+ {
+ throw new Ice.MarshalException("invalid address `" + _addr + "' in endpoint");
+ }
+
+ try
+ {
+ _uuid = UUID.fromString(s.readString());
+ }
+ catch(IllegalArgumentException ex)
+ {
+ throw new Ice.MarshalException("invalid UUID for Bluetooth endpoint", ex);
+ }
+
+ _timeout = s.readInt();
+ _compress = s.readBool();
+ hashInit();
+ }
+
+ @Override
+ public void streamWriteImpl(Ice.OutputStream s)
+ {
+ //
+ // _name and _channel are not marshaled.
+ //
+ s.writeString(_addr);
+ s.writeString(_uuid.toString());
+ s.writeInt(_timeout);
+ s.writeBool(_compress);
+ }
+
+ @Override
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public int timeout()
+ {
+ return _timeout;
+ }
+
+ @Override
+ public IceInternal.EndpointI timeout(int timeout)
+ {
+ if(timeout == _timeout)
+ {
+ return this;
+ }
+ else
+ {
+ return new EndpointI(_instance, _addr, _uuid, _name, _channel, timeout, _connectionId, _compress);
+ }
+ }
+
+ @Override
+ public String connectionId()
+ {
+ return _connectionId;
+ }
+
+ @Override
+ public IceInternal.EndpointI connectionId(String connectionId)
+ {
+ if(connectionId.equals(_connectionId))
+ {
+ return this;
+ }
+ else
+ {
+ return new EndpointI(_instance, _addr, _uuid, _name, _channel, _timeout, connectionId, _compress);
+ }
+ }
+
+ @Override
+ public boolean compress()
+ {
+ return _compress;
+ }
+
+ @Override
+ public IceInternal.EndpointI compress(boolean compress)
+ {
+ if(compress == _compress)
+ {
+ return this;
+ }
+ else
+ {
+ return new EndpointI(_instance, _addr, _uuid, _name, _channel, _timeout, _connectionId, compress);
+ }
+ }
+
+ @Override
+ public boolean datagram()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return _instance.secure();
+ }
+
+ @Override
+ public IceInternal.Transceiver transceiver()
+ {
+ return null;
+ }
+
+ @Override
+ public void connectors_async(Ice.EndpointSelectionType selType, IceInternal.EndpointI_connectors callback)
+ {
+ java.util.List<IceInternal.Connector> conns = new java.util.ArrayList<IceInternal.Connector>();
+ conns.add(new ConnectorI(_instance, _addr, _uuid, _timeout, _connectionId));
+ callback.connectors(conns);
+ }
+
+ @Override
+ public IceInternal.Acceptor acceptor(String adapterName)
+ {
+ return new AcceptorI(this, _instance, adapterName, _uuid, _name);
+ }
+
+ @Override
+ public java.util.List<IceInternal.EndpointI> expand()
+ {
+ java.util.List<IceInternal.EndpointI> endps = new java.util.ArrayList<IceInternal.EndpointI>();
+ endps.add(this);
+ return endps;
+ }
+
+ @Override
+ public boolean equivalent(IceInternal.EndpointI endpoint)
+ {
+ if(!(endpoint instanceof EndpointI))
+ {
+ return false;
+ }
+ EndpointI btEndpointI = (EndpointI)endpoint;
+ return btEndpointI.type() == type() && btEndpointI._addr.equals(_addr) && btEndpointI._uuid.equals(_uuid) &&
+ btEndpointI._channel == _channel;
+ }
+
+ @Override
+ public String options()
+ {
+ //
+ // 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.
+ //
+ String s = "";
+
+ if(_addr != null && _addr.length() > 0)
+ {
+ s += " -a ";
+ boolean addQuote = _addr.indexOf(':') != -1;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ s += _addr;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ }
+
+ if(_uuid != null)
+ {
+ s += " -u ";
+ String uuidStr = _uuid.toString();
+ boolean addQuote = uuidStr.indexOf(':') != -1;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ s += uuidStr;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ }
+
+ if(_channel > 0)
+ {
+ s += " -c " + _channel;
+ }
+
+ if(_timeout == -1)
+ {
+ s += " -t infinite";
+ }
+ else
+ {
+ s += " -t " + _timeout;
+ }
+
+ if(_compress)
+ {
+ s += " -z";
+ }
+
+ return s;
+ }
+
+ public void initWithOptions(java.util.ArrayList<String> args, boolean oaEndpoint)
+ {
+ super.initWithOptions(args);
+
+ if(_addr.length() == 0)
+ {
+ _addr = _instance.defaultHost();
+ if(_addr == null)
+ {
+ _addr = "";
+ }
+ }
+
+ if(_addr.length() == 0 || _addr.equals("*"))
+ {
+ if(oaEndpoint)
+ {
+ //
+ // Ignore a missing address, we always use the default adapter anyway.
+ //
+ }
+ else
+ {
+ throw new Ice.EndpointParseException(
+ "a device address must be specified using the -a option or Ice.Default.Host");
+ }
+ }
+
+ if(_name.length() == 0)
+ {
+ _name = "Ice Service";
+ }
+
+ if(_uuid == null)
+ {
+ if(oaEndpoint)
+ {
+ //
+ // Generate a UUID for object adapters that don't specify one.
+ //
+ _uuid = UUID.randomUUID();
+ }
+ else
+ {
+ throw new Ice.EndpointParseException("a UUID must be specified using the -u option");
+ }
+ }
+
+ hashInit();
+ }
+
+ @Override
+ public Ice.EndpointInfo getInfo()
+ {
+ EndpointInfo info = new EndpointInfo()
+ {
+ @Override
+ public short type()
+ {
+ return EndpointI.this.type();
+ }
+
+ @Override
+ public boolean datagram()
+ {
+ return EndpointI.this.datagram();
+ }
+
+ @Override
+ public boolean secure()
+ {
+ return EndpointI.this.secure();
+ }
+ };
+ info.addr = _addr;
+ info.uuid = _uuid.toString();
+ return info;
+ }
+
+ @Override
+ public int compareTo(IceInternal.EndpointI obj) // From java.lang.Comparable
+ {
+ if(!(obj instanceof EndpointI))
+ {
+ return type() < obj.type() ? -1 : 1;
+ }
+
+ EndpointI p = (EndpointI)obj;
+ if(this == p)
+ {
+ return 0;
+ }
+
+ int v = _addr.compareTo(p._addr);
+ if(v != 0)
+ {
+ return v;
+ }
+
+ v = _uuid.toString().compareTo(p._uuid.toString());
+ if(v != 0)
+ {
+ return v;
+ }
+
+ if(_channel < p._channel)
+ {
+ return -1;
+ }
+ else if(p._channel < _channel)
+ {
+ return 1;
+ }
+
+ if(_timeout < p._timeout)
+ {
+ return -1;
+ }
+ else if(p._timeout < _timeout)
+ {
+ return 1;
+ }
+
+ v = _connectionId.compareTo(p._connectionId);
+ if(v != 0)
+ {
+ return v;
+ }
+
+ if(!_compress && p._compress)
+ {
+ return -1;
+ }
+ else if(!p._compress && _compress)
+ {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return _hashValue;
+ }
+
+ @Override
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ if(super.checkOption(option, argument, endpoint))
+ {
+ return true;
+ }
+
+ if(option.equals("-a"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -a option in endpoint " + endpoint);
+ }
+ if(!argument.equals("*") && !BluetoothAdapter.checkBluetoothAddress(argument.toUpperCase()))
+ {
+ throw new Ice.EndpointParseException("invalid address provided for -a option in endpoint " + endpoint);
+ }
+ _addr = argument.toUpperCase(); // Android requires a hardware address to use upper case letters.
+ }
+ else if(option.equals("-u"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -u option in endpoint " + endpoint);
+ }
+ try
+ {
+ _uuid = UUID.fromString(argument);
+ }
+ catch(IllegalArgumentException ex)
+ {
+ throw new Ice.EndpointParseException("invalid UUID for Bluetooth endpoint", ex);
+ }
+ }
+ else if(option.equals("-c"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -c option in endpoint " + endpoint);
+ }
+
+ try
+ {
+ _channel = Integer.parseInt(argument);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid channel value `" + argument +
+ "' in endpoint " + endpoint);
+ }
+
+ if(_channel < 0 || _channel > 30) // RFCOMM channel limit is 30
+ {
+ throw new Ice.EndpointParseException("channel value `" + argument +
+ "' out of range in endpoint " + endpoint);
+ }
+ }
+ else if(option.equals("-t"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -t option in endpoint " + endpoint);
+ }
+
+ if(argument.equals("infinite"))
+ {
+ _timeout = -1;
+ }
+ else
+ {
+ try
+ {
+ _timeout = Integer.parseInt(argument);
+ if(_timeout < 1)
+ {
+ throw new Ice.EndpointParseException("invalid timeout value `" + argument + "' in endpoint " +
+ endpoint);
+ }
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid timeout value `" + argument + "' in endpoint " +
+ endpoint);
+ }
+ }
+ }
+ else if(option.equals("-z"))
+ {
+ if(argument != null)
+ {
+ throw new Ice.EndpointParseException("unexpected argument `" + argument +
+ "' provided for -z option in " + endpoint);
+ }
+
+ _compress = true;
+ }
+ else if(option.equals("--name"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for --name option in endpoint " + endpoint);
+ }
+
+ _name = argument;
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void hashInit()
+ {
+ int h = 5381;
+ h = IceInternal.HashUtil.hashAdd(h, _addr);
+ h = IceInternal.HashUtil.hashAdd(h, _uuid.toString());
+ h = IceInternal.HashUtil.hashAdd(h, _timeout);
+ h = IceInternal.HashUtil.hashAdd(h, _connectionId);
+ h = IceInternal.HashUtil.hashAdd(h, _compress);
+ _hashValue = h;
+ }
+
+ private Instance _instance;
+ private String _addr;
+ private UUID _uuid;
+ private String _name;
+ private int _channel;
+ private int _timeout;
+ private String _connectionId;
+ private boolean _compress;
+ private int _hashValue;
+}
diff --git a/java-compat/src/IceBT/src/main/java/IceBT/Instance.java b/java-compat/src/IceBT/src/main/java/IceBT/Instance.java
new file mode 100644
index 00000000000..db5d516adcb
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/IceBT/Instance.java
@@ -0,0 +1,54 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBT;
+
+import android.bluetooth.BluetoothAdapter;
+
+class Instance extends IceInternal.ProtocolInstance
+{
+ Instance(Ice.Communicator communicator, short type, String protocol)
+ {
+ //
+ // We consider the transport to be "secure" because it uses the secure versions Android's Bluetooth API
+ // methods for establishing and accepting connections. The boolean argument below sets secure=true.
+ //
+ super(communicator, type, protocol, true);
+
+ _communicator = communicator;
+
+ _bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ if(_bluetoothAdapter == null)
+ {
+ throw new Ice.PluginInitializationException("bluetooth adapter not available");
+ }
+ else if(!_bluetoothAdapter.isEnabled())
+ {
+ throw new Ice.PluginInitializationException("bluetooth is not enabled");
+ }
+ }
+
+ void destroy()
+ {
+ _communicator = null;
+ }
+
+ Ice.Communicator communicator()
+ {
+ return _communicator;
+ }
+
+ BluetoothAdapter bluetoothAdapter()
+ {
+ return _bluetoothAdapter;
+ }
+
+ private Ice.Communicator _communicator;
+ private BluetoothAdapter _bluetoothAdapter;
+}
diff --git a/java-compat/src/IceBT/src/main/java/IceBT/PluginFactory.java b/java-compat/src/IceBT/src/main/java/IceBT/PluginFactory.java
new file mode 100644
index 00000000000..fc523108cae
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/IceBT/PluginFactory.java
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBT;
+
+/**
+ * Plug-in factories must implement this interface.
+ **/
+public class PluginFactory implements Ice.PluginFactory
+{
+ /**
+ * Returns a new plug-in.
+ *
+ * @param communicator The communicator for the plug-in.
+ * @param name The name of the plug-in.
+ * @param args The arguments that are specified in the plug-in's configuration.
+ *
+ * @return The new plug-in. <code>null</code> can be returned to indicate
+ * that a general error occurred. Alternatively, <code>create</code> can throw
+ * {@link PluginInitializationException} to provide more detailed information.
+ **/
+ @Override
+ public Ice.Plugin
+ create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginI(communicator);
+ }
+}
diff --git a/java-compat/src/IceBT/src/main/java/IceBT/PluginI.java b/java-compat/src/IceBT/src/main/java/IceBT/PluginI.java
new file mode 100644
index 00000000000..bee179f55ca
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/IceBT/PluginI.java
@@ -0,0 +1,43 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBT;
+
+class PluginI implements Ice.Plugin
+{
+ public PluginI(Ice.Communicator communicator)
+ {
+ final IceInternal.ProtocolPluginFacade facade = IceInternal.Util.getProtocolPluginFacade(communicator);
+
+ //
+ // Register the endpoint factory. We have to do this now, rather than
+ // in initialize, because the communicator may need to interpret
+ // proxies before the plug-in is fully initialized.
+ //
+ EndpointFactoryI factory = new EndpointFactoryI(new Instance(communicator, Ice.BTEndpointType.value, "bt"));
+ facade.addEndpointFactory(factory);
+
+ IceInternal.EndpointFactory sslFactory = facade.getEndpointFactory(Ice.SSLEndpointType.value);
+ if(sslFactory != null)
+ {
+ Instance instance = new Instance(communicator, Ice.BTSEndpointType.value, "bts");
+ facade.addEndpointFactory(sslFactory.clone(instance, new EndpointFactoryI(instance)));
+ }
+ }
+
+ @Override
+ public void initialize()
+ {
+ }
+
+ @Override
+ public void destroy()
+ {
+ }
+}
diff --git a/java-compat/src/IceBT/src/main/java/IceBT/TransceiverI.java b/java-compat/src/IceBT/src/main/java/IceBT/TransceiverI.java
new file mode 100644
index 00000000000..fe6df651826
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/IceBT/TransceiverI.java
@@ -0,0 +1,693 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBT;
+
+import java.lang.Thread;
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.util.UUID;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+
+final class TransceiverI implements IceInternal.Transceiver
+{
+ @Override
+ public java.nio.channels.SelectableChannel fd()
+ {
+ //
+ // Android doesn't provide non-blocking APIs for Bluetooth.
+ //
+ return null;
+ }
+
+ @Override
+ public void setReadyCallback(IceInternal.ReadyCallback callback)
+ {
+ _readyCallback = callback;
+ }
+
+ @Override
+ public synchronized int initialize(IceInternal.Buffer readBuffer, IceInternal.Buffer writeBuffer)
+ {
+ if(_exception != null)
+ {
+ throw _exception;
+ //throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+
+ if(_state == StateConnecting)
+ {
+ //
+ // Wait until the connect thread is finished.
+ //
+ return IceInternal.SocketOperation.Read;
+ }
+ else if(_state == StateConnected)
+ {
+ //
+ // Update our Read state to indicate whether we still have more data waiting to be read.
+ //
+ _readyCallback.ready(IceInternal.SocketOperation.Read, _readBuffer.b.position() > 0);
+ }
+
+ return IceInternal.SocketOperation.None;
+ }
+
+ @Override
+ public int closing(boolean initiator, Ice.LocalException ex)
+ {
+ //
+ // If we are initiating the connection closure, wait for the peer
+ // to close the connection. Otherwise, close immediately.
+ //
+ return initiator ? IceInternal.SocketOperation.Read : IceInternal.SocketOperation.None;
+ }
+
+ @Override
+ public void close()
+ {
+ Thread connectThread = null, readThread = null, writeThread = null;
+
+ synchronized(this)
+ {
+ //
+ // Close the socket first in order to interrupt the helper threads.
+ //
+ if(_socket != null)
+ {
+ try
+ {
+ _socket.close();
+ }
+ catch(java.io.IOException ex)
+ {
+ // Ignore.
+ }
+ _socket = null;
+ }
+
+ connectThread = _connectThread;
+ _connectThread = null;
+ readThread = _readThread;
+ _readThread = null;
+ writeThread = _writeThread;
+ _writeThread = null;
+
+ _state = StateClosed;
+
+ if(writeThread != null)
+ {
+ notifyAll(); // Wake up the read/write threads.
+ }
+ }
+
+ if(connectThread != null)
+ {
+ try
+ {
+ connectThread.join();
+ }
+ catch(InterruptedException ex)
+ {
+ // Ignore.
+ }
+ }
+
+ if(readThread != null)
+ {
+ try
+ {
+ readThread.join();
+ }
+ catch(InterruptedException ex)
+ {
+ // Ignore.
+ }
+ }
+
+ if(writeThread != null)
+ {
+ try
+ {
+ writeThread.join();
+ }
+ catch(InterruptedException ex)
+ {
+ // Ignore.
+ }
+ }
+ }
+
+ @Override
+ public IceInternal.EndpointI bind()
+ {
+ assert(false);
+ return null;
+ }
+
+ @Override
+ public synchronized int write(IceInternal.Buffer buf)
+ {
+ if(_exception != null)
+ {
+ throw _exception;
+ //throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+
+ //
+ // Accept up to _sndSize bytes in our internal buffer.
+ //
+ final int capacity = _sndSize - _writeBuffer.b.position();
+ if(capacity > 0)
+ {
+ final int num = Math.min(capacity, buf.b.remaining());
+ _writeBuffer.expand(num);
+ final int lim = buf.b.limit(); // Save the current limit.
+ buf.b.limit(buf.b.position() + num); // Temporarily change the limit.
+ _writeBuffer.b.put(buf.b); // Copy to our internal buffer.
+ buf.b.limit(lim); // Restore the previous limit.
+
+ notifyAll(); // We've added data to the internal buffer, so wake up the write thread.
+ }
+
+ return buf.b.hasRemaining() ? IceInternal.SocketOperation.Write : IceInternal.SocketOperation.None;
+ }
+
+ @Override
+ public synchronized int read(IceInternal.Buffer buf)
+ {
+ if(_exception != null)
+ {
+ throw _exception;
+ //throw (Ice.LocalException) _exception.fillInStackTrace();
+ }
+
+ //
+ // Copy the requested amount of data from our internal buffer to the given buffer.
+ //
+ _readBuffer.b.flip();
+ if(_readBuffer.b.hasRemaining())
+ {
+ int bytesAvailable = _readBuffer.b.remaining();
+ int bytesNeeded = buf.b.remaining();
+ if(bytesAvailable > bytesNeeded)
+ {
+ bytesAvailable = bytesNeeded;
+ }
+ if(buf.b.hasArray())
+ {
+ //
+ // Copy directly into the destination buffer's backing array.
+ //
+ byte[] arr = buf.b.array();
+ _readBuffer.b.get(arr, buf.b.arrayOffset() + buf.b.position(), bytesAvailable);
+ buf.b.position(buf.b.position() + bytesAvailable);
+ }
+ else if(_readBuffer.b.hasArray())
+ {
+ //
+ // Copy directly from the source buffer's backing array.
+ //
+ byte[] arr = _readBuffer.b.array();
+ buf.b.put(arr, _readBuffer.b.arrayOffset() + _readBuffer.b.position(), bytesAvailable);
+ _readBuffer.b.position(_readBuffer.b.position() + bytesAvailable);
+ }
+ else
+ {
+ //
+ // Copy using a temporary array.
+ //
+ byte[] arr = new byte[bytesAvailable];
+ _readBuffer.b.get(arr);
+ buf.b.put(arr);
+ }
+ }
+ _readBuffer.b.compact();
+
+ //
+ // The read thread will temporarily stop reading if we exceed our configured limit.
+ //
+ if(_readBuffer.b.position() < _rcvSize)
+ {
+ notifyAll();
+ }
+
+ //
+ // Update our Read state to indicate whether we still have more data waiting to be read.
+ //
+ _readyCallback.ready(IceInternal.SocketOperation.Read, _readBuffer.b.position() > 0);
+
+ return buf.b.hasRemaining() ? IceInternal.SocketOperation.Read : IceInternal.SocketOperation.None;
+ }
+
+ @Override
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ @Override
+ public String toString()
+ {
+ return _desc;
+ }
+
+ @Override
+ public String toDetailedString()
+ {
+ return toString();
+ }
+
+ @Override
+ public Ice.ConnectionInfo getInfo()
+ {
+ ConnectionInfo info = new ConnectionInfo();
+ info.incoming = _adapterName != null;
+ info.adapterName = _adapterName != null ? _adapterName : "";
+ info.connectionId = _connectionId;
+ info.rcvSize = _rcvSize;
+ info.sndSize = _sndSize;
+ info.localAddress = BluetoothAdapter.getDefaultAdapter().getAddress();
+ //info.localChannel - not available, use default value of -1
+ info.remoteAddress = _remoteAddr;
+ //info.remoteChannel - not available, use default value of -1
+ info.uuid = _uuid.toString();
+ return info;
+ }
+
+ @Override
+ public synchronized void setBufferSize(int rcvSize, int sndSize)
+ {
+ _rcvSize = Math.max(1024, rcvSize);
+ _sndSize = Math.max(1024, sndSize);
+ }
+
+ @Override
+ public void checkSendSize(IceInternal.Buffer buf)
+ {
+ }
+
+ //
+ // Used by ConnectorI.
+ //
+ TransceiverI(Instance instance, String remoteAddr, UUID uuid, String connectionId)
+ {
+ _instance = instance;
+ _remoteAddr = remoteAddr;
+ _uuid = uuid;
+ _connectionId = connectionId;
+ _state = StateConnecting;
+
+ init();
+
+ BluetoothAdapter adapter = _instance.bluetoothAdapter();
+ assert(adapter != null);
+
+ BluetoothDevice device = null;
+ try
+ {
+ device = adapter.getRemoteDevice(_remoteAddr);
+ }
+ catch(IllegalArgumentException ex)
+ {
+ //
+ // Illegal address - This should have been detected by the endpoint.
+ //
+ assert(false);
+ throw new Ice.SocketException(ex);
+ }
+
+ try
+ {
+ //
+ // We always connect using the "secure" method.
+ //
+ _socket = device.createRfcommSocketToServiceRecord(_uuid);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.SocketException(ex);
+ }
+
+ _connectThread = new Thread()
+ {
+ public void run()
+ {
+ String name = "IceBT.ConnectThread";
+ if(_remoteAddr != null && !_remoteAddr.isEmpty())
+ {
+ name += "-" + _remoteAddr;
+ }
+ if(_uuid != null)
+ {
+ name += "-" + _uuid.toString();
+ }
+ setName(name);
+
+ runConnectThread();
+ }
+ };
+ _connectThread.start();
+ }
+
+ //
+ // Used by AcceptorI.
+ //
+ TransceiverI(Instance instance, BluetoothSocket socket, UUID uuid, String adapterName)
+ {
+ _instance = instance;
+ _remoteAddr = socket.getRemoteDevice().getAddress();
+ _uuid = uuid;
+ _connectionId = "";
+ _adapterName = adapterName;
+ _socket = socket;
+ _state = StateConnected;
+
+ init();
+
+ startReadWriteThreads();
+ }
+
+ private void init()
+ {
+ _desc = "local address = " + _instance.bluetoothAdapter().getAddress();
+ if(_remoteAddr != null && !_remoteAddr.isEmpty())
+ {
+ _desc += "\nremote address = " + _remoteAddr;
+ }
+ if(_uuid != null)
+ {
+ _desc += "\nservice uuid = " + _uuid.toString();
+ }
+
+ final int defaultBufSize = 128 * 1024;
+ _rcvSize = _instance.properties().getPropertyAsIntWithDefault("IceBT.RcvSize", defaultBufSize);
+ _sndSize = _instance.properties().getPropertyAsIntWithDefault("IceBT.SndSize", defaultBufSize);
+
+ _readBuffer = new IceInternal.Buffer(false);
+ _writeBuffer = new IceInternal.Buffer(false);
+ }
+
+ private synchronized void exception(Ice.LocalException ex)
+ {
+ if(_exception == null)
+ {
+ _exception = ex;
+ }
+ }
+
+ private void runConnectThread()
+ {
+ //
+ // Always cancel discovery prior to a connect attempt.
+ //
+ _instance.bluetoothAdapter().cancelDiscovery();
+
+ try
+ {
+ //
+ // This can block for several seconds.
+ //
+ _socket.connect();
+ }
+ catch(java.io.IOException ex)
+ {
+ exception(new Ice.ConnectFailedException(ex));
+ }
+
+ synchronized(this)
+ {
+ _connectThread = null;
+
+ if(_exception == null)
+ {
+ //
+ // Connect succeeded.
+ //
+ _state = StateConnected;
+
+ startReadWriteThreads();
+ }
+ }
+
+ //
+ // This causes the Ice run time to invoke initialize() again.
+ //
+ _readyCallback.ready(IceInternal.SocketOperation.Read, true);
+ }
+
+ private void startReadWriteThreads()
+ {
+ String s = "";
+ if(_remoteAddr != null && !_remoteAddr.isEmpty())
+ {
+ s += "-" + _remoteAddr;
+ }
+ if(_uuid != null)
+ {
+ s += "-" + _uuid.toString();
+ }
+ final String suffix = s;
+
+ _readThread = new Thread()
+ {
+ public void run()
+ {
+ setName("IceBT.ReadThread" + suffix);
+
+ runReadThread();
+ }
+ };
+ _readThread.start();
+
+ _writeThread = new Thread()
+ {
+ public void run()
+ {
+ setName("IceBT.WriteThread" + suffix);
+
+ runWriteThread();
+ }
+ };
+ _writeThread.start();
+ }
+
+ private void runReadThread()
+ {
+ java.io.InputStream in = null;
+
+ try
+ {
+ byte[] buf = null;
+
+ synchronized(this)
+ {
+ if(_socket == null)
+ {
+ return;
+ }
+ in = _socket.getInputStream();
+
+ buf = new byte[_rcvSize];
+ }
+
+ while(true)
+ {
+ ByteBuffer b = null;
+
+ synchronized(this)
+ {
+ //
+ // If we've read too much data, wait until the application consumes some before we read again.
+ //
+ while(_state == StateConnected && _exception == null && _readBuffer.b.position() > _rcvSize)
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ break;
+ }
+ }
+
+ if(_state != StateConnected || _exception != null)
+ {
+ break;
+ }
+ }
+
+ int num = in.read(buf);
+ if(num > 0)
+ {
+ synchronized(this)
+ {
+ _readBuffer.expand(num);
+ _readBuffer.b.put(buf, 0, num);
+ _readyCallback.ready(IceInternal.SocketOperation.Read, true);
+
+ if(buf.length != _rcvSize)
+ {
+ //
+ // Application must have called setBufferSize.
+ //
+ buf = new byte[_rcvSize];
+ }
+ }
+ }
+ }
+ }
+ catch(java.io.IOException ex)
+ {
+ exception(new Ice.SocketException(ex));
+ //
+ // Mark as ready for reading so that the Ice run time will invoke read() and we can report the exception.
+ //
+ _readyCallback.ready(IceInternal.SocketOperation.Read, true);
+ }
+ catch(Ice.LocalException ex)
+ {
+ exception(ex);
+ //
+ // Mark as ready for reading so that the Ice run time will invoke read() and we can report the exception.
+ //
+ _readyCallback.ready(IceInternal.SocketOperation.Read, true);
+ }
+ finally
+ {
+ if(in != null)
+ {
+ try
+ {
+ in.close();
+ }
+ catch(java.io.IOException ex)
+ {
+ // Ignore.
+ }
+ }
+ }
+ }
+
+ private void runWriteThread()
+ {
+ java.io.OutputStream out = null;
+
+ try
+ {
+ synchronized(this)
+ {
+ if(_socket == null)
+ {
+ return;
+ }
+ out = _socket.getOutputStream();
+ }
+
+ boolean done = false;
+ while(!done)
+ {
+ ByteBuffer b = null;
+
+ synchronized(this)
+ {
+ while(_state == StateConnected && _exception == null && _writeBuffer.b.position() == 0)
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException ex)
+ {
+ break;
+ }
+ }
+
+ if(_state != StateConnected || _exception != null)
+ {
+ done = true;
+ }
+
+ b = _writeBuffer.b; // Adopt the ByteBuffer.
+ _writeBuffer.clear();
+ }
+
+ assert(b != null && b.hasArray());
+ b.flip();
+ if(b.hasRemaining() && !done)
+ {
+ //
+ // write() blocks until all the data has been written.
+ //
+ out.write(b.array(), b.arrayOffset(), b.remaining());
+ }
+
+ // TBD: Recycle the buffer?
+
+ synchronized(this)
+ {
+ //
+ // After the write is complete, indicate whether we can accept more data.
+ //
+ _readyCallback.ready(IceInternal.SocketOperation.Write, _writeBuffer.b.position() < _sndSize);
+ }
+ }
+ }
+ catch(java.io.IOException ex)
+ {
+ exception(new Ice.SocketException(ex));
+ }
+ finally
+ {
+ if(out != null)
+ {
+ try
+ {
+ out.close();
+ }
+ catch(java.io.IOException ex)
+ {
+ // Ignore.
+ }
+ }
+ }
+ }
+
+ private Instance _instance;
+ private String _remoteAddr;
+ private UUID _uuid;
+ private String _connectionId;
+ private String _adapterName;
+
+ private BluetoothSocket _socket;
+
+ private static final int StateConnecting = 0;
+ private static final int StateConnected = 1;
+ private static final int StateClosed = 2;
+ private int _state;
+
+ private Thread _connectThread;
+ private Thread _readThread;
+ private Thread _writeThread;
+
+ private Ice.LocalException _exception;
+
+ private int _rcvSize;
+ private int _sndSize;
+
+ private IceInternal.Buffer _readBuffer;
+ private IceInternal.Buffer _writeBuffer;
+
+ private String _desc;
+
+ private IceInternal.ReadyCallback _readyCallback;
+}
diff --git a/java-compat/src/IceBT/src/main/java/IceBT/Util.java b/java-compat/src/IceBT/src/main/java/IceBT/Util.java
new file mode 100644
index 00000000000..ffb07e0a2f5
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/IceBT/Util.java
@@ -0,0 +1,14 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBT;
+
+public final class Util
+{
+}
diff --git a/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothAdapter.java b/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothAdapter.java
new file mode 100644
index 00000000000..8d00d879d3b
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothAdapter.java
@@ -0,0 +1,55 @@
+//
+// This is a placeholder for the Android API. It is not included in the IceBT JAR file.
+//
+
+package android.bluetooth;
+
+public final class BluetoothAdapter
+{
+ public boolean cancelDiscovery()
+ {
+ return false;
+ }
+
+ public boolean isEnabled()
+ {
+ return false;
+ }
+
+ public String getAddress()
+ {
+ return "";
+ }
+
+ public static boolean checkBluetoothAddress(String address)
+ {
+ return false;
+ }
+
+ public static BluetoothAdapter getDefaultAdapter()
+ {
+ return null;
+ }
+
+ public BluetoothDevice getRemoteDevice(byte[] address)
+ {
+ return null;
+ }
+
+ public BluetoothDevice getRemoteDevice(String address)
+ {
+ return null;
+ }
+
+ public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, java.util.UUID uuid)
+ throws java.io.IOException
+ {
+ return null;
+ }
+
+ public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, java.util.UUID uuid)
+ throws java.io.IOException
+ {
+ return null;
+ }
+}
diff --git a/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothDevice.java b/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothDevice.java
new file mode 100644
index 00000000000..7fbee8880de
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothDevice.java
@@ -0,0 +1,25 @@
+//
+// This is a placeholder for the Android API. It is not included in the IceBT JAR file.
+//
+
+package android.bluetooth;
+
+public final class BluetoothDevice
+{
+ public BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID uuid)
+ throws java.io.IOException
+ {
+ return null;
+ }
+
+ public BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID uuid)
+ throws java.io.IOException
+ {
+ return null;
+ }
+
+ public String getAddress()
+ {
+ return "";
+ }
+}
diff --git a/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothServerSocket.java b/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothServerSocket.java
new file mode 100644
index 00000000000..c6e6f2a6978
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothServerSocket.java
@@ -0,0 +1,19 @@
+//
+// This is a placeholder for the Android API. It is not included in the IceBT JAR file.
+//
+
+package android.bluetooth;
+
+public final class BluetoothServerSocket implements java.io.Closeable
+{
+ public BluetoothSocket accept()
+ throws java.io.IOException
+ {
+ return null;
+ }
+
+ public void close()
+ throws java.io.IOException
+ {
+ }
+}
diff --git a/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothSocket.java b/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothSocket.java
new file mode 100644
index 00000000000..80470a11a52
--- /dev/null
+++ b/java-compat/src/IceBT/src/main/java/android/bluetooth/BluetoothSocket.java
@@ -0,0 +1,40 @@
+//
+// This is a placeholder for the Android API. It is not included in the IceBT JAR file.
+//
+
+package android.bluetooth;
+
+public final class BluetoothSocket implements java.io.Closeable
+{
+ public void close()
+ throws java.io.IOException
+ {
+ }
+
+ public void connect()
+ throws java.io.IOException
+ {
+ }
+
+ public java.io.InputStream getInputStream()
+ throws java.io.IOException
+ {
+ return null;
+ }
+
+ public java.io.OutputStream getOutputStream()
+ throws java.io.IOException
+ {
+ return null;
+ }
+
+ public BluetoothDevice getRemoteDevice()
+ {
+ return null;
+ }
+
+ public boolean isConnected()
+ {
+ return false;
+ }
+}
diff --git a/java-compat/src/IceBox/build.gradle b/java-compat/src/IceBox/build.gradle
new file mode 100644
index 00000000000..19aac05e3d3
--- /dev/null
+++ b/java-compat/src/IceBox/build.gradle
@@ -0,0 +1,29 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+sourceCompatibility = iceSourceCompatibility
+targetCompatibility = iceTargetCompatibility
+
+project.ext.displayName = "IceBox Compat"
+project.ext.description = "IceBox is an easy-to-use framework for Ice application services"
+
+slice {
+ java {
+ set1 {
+ args = "--ice --tie --checksum IceBox.SliceChecksums"
+ files = fileTree(dir: "$sliceDir/IceBox", includes:['*.ice'], excludes:["*F.ice"])
+ }
+ }
+}
+
+dependencies {
+ compile project(':ice-compat')
+}
+
+apply from: "$rootProject.projectDir/../java/gradle/library.gradle"
diff --git a/java-compat/src/IceBox/src/main/java/IceBox/Admin.java b/java-compat/src/IceBox/src/main/java/IceBox/Admin.java
new file mode 100644
index 00000000000..52e39ee771e
--- /dev/null
+++ b/java-compat/src/IceBox/src/main/java/IceBox/Admin.java
@@ -0,0 +1,184 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBox;
+
+public final class Admin
+{
+ private static class Client extends Ice.Application
+ {
+ private void
+ usage()
+ {
+ System.err.println(
+ "Usage: " + appName() + " [options] [command...]\n" +
+ "Options:\n" +
+ "-h, --help Show this message.\n" +
+ "\n" +
+ "Commands:\n" +
+ "start SERVICE Start a service.\n" +
+ "stop SERVICE Stop a service.\n" +
+ "shutdown Shutdown the server.");
+ }
+
+ @Override
+ public int
+ run(String[] args)
+ {
+ java.util.List<String> commands = new java.util.ArrayList<String>();
+
+ int idx = 0;
+ while(idx < args.length)
+ {
+ if(args[idx].equals("-h") || args[idx].equals("--help"))
+ {
+ usage();
+ return 1;
+ }
+ else if(args[idx].charAt(0) == '-')
+ {
+ System.err.println(appName() + ": unknown option `" + args[idx] + "'");
+ usage();
+ return 1;
+ }
+ else
+ {
+ commands.add(args[idx]);
+ ++idx;
+ }
+ }
+
+ if(commands.isEmpty())
+ {
+ usage();
+ return 0;
+ }
+
+ Ice.ObjectPrx base = communicator().propertyToProxy("IceBoxAdmin.ServiceManager.Proxy");
+
+ if(base == null)
+ {
+ //
+ // The old deprecated way to retrieve the service manager proxy
+ //
+
+ Ice.Properties properties = communicator().getProperties();
+
+ Ice.Identity managerIdentity = new Ice.Identity();
+ managerIdentity.category = properties.getPropertyWithDefault("IceBox.InstanceName", "IceBox");
+ managerIdentity.name = "ServiceManager";
+
+ String managerProxy;
+ if(properties.getProperty("Ice.Default.Locator").length() == 0)
+ {
+ String managerEndpoints = properties.getProperty("IceBox.ServiceManager.Endpoints");
+ if(managerEndpoints.length() == 0)
+ {
+ System.err.println(appName() + ": property `IceBoxAdmin.ServiceManager.Proxy' is not set");
+ return 1;
+ }
+
+ managerProxy = "\"" + Ice.Util.identityToString(managerIdentity) + "\" :" + managerEndpoints;
+ }
+ else
+ {
+ String managerAdapterId = properties.getProperty("IceBox.ServiceManager.AdapterId");
+ if(managerAdapterId.length() == 0)
+ {
+ System.err.println(appName() + ": property `IceBoxAdmin.ServiceManager.Proxy' is not set");
+ return 1;
+ }
+
+ managerProxy = "\"" + Ice.Util.identityToString(managerIdentity) + "\" @" + managerAdapterId;
+ }
+
+ base = communicator().stringToProxy(managerProxy);
+ }
+
+ IceBox.ServiceManagerPrx manager = IceBox.ServiceManagerPrxHelper.checkedCast(base);
+ if(manager == null)
+ {
+ System.err.println(appName() + ": `" + base.toString() + "' is not an IceBox::ServiceManager");
+ return 1;
+ }
+
+ for(int i = 0; i < commands.size(); i++)
+ {
+ String command = commands.get(i);
+ if(command.equals("shutdown"))
+ {
+ manager.shutdown();
+ }
+ else if(command.equals("start"))
+ {
+ if(++i >= commands.size())
+ {
+ System.err.println(appName() + ": no service name specified.");
+ return 1;
+ }
+
+ String service = commands.get(i);
+ try
+ {
+ manager.startService(service);
+ }
+ catch(IceBox.NoSuchServiceException ex)
+ {
+ System.err.println(appName() + ": unknown service `" + service + "'");
+ return 1;
+ }
+ catch(IceBox.AlreadyStartedException ex)
+ {
+ System.err.println(appName() + "service already started.");
+ }
+ }
+ else if(command.equals("stop"))
+ {
+ if(++i >= commands.size())
+ {
+ System.err.println(appName() + ": no service name specified.");
+ return 1;
+ }
+
+ String service = commands.get(i);
+ try
+ {
+ manager.stopService(service);
+ }
+ catch(IceBox.NoSuchServiceException ex)
+ {
+ System.err.println(appName() + ": unknown service `" + service + "'");
+ return 1;
+ }
+ catch(IceBox.AlreadyStoppedException ex)
+ {
+ System.err.println(appName() + "service already stopped.");
+ }
+ }
+ else
+ {
+ System.err.println(appName() + ": unknown command `" + command + "'");
+ usage();
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+ }
+
+ public static void
+ main(String[] args)
+ {
+ Client app = new Client();
+ int rc = app.main("IceBox.Admin", args);
+
+ System.exit(rc);
+ }
+}
diff --git a/java-compat/src/IceBox/src/main/java/IceBox/Server.java b/java-compat/src/IceBox/src/main/java/IceBox/Server.java
new file mode 100644
index 00000000000..f6147ea423b
--- /dev/null
+++ b/java-compat/src/IceBox/src/main/java/IceBox/Server.java
@@ -0,0 +1,79 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBox;
+
+public final class Server extends Ice.Application
+{
+ private static void
+ usage()
+ {
+ System.err.println("Usage: IceBox.Server [options] --Ice.Config=<file>\n");
+ System.err.println(
+ "Options:\n" +
+ "-h, --help Show this message.\n"
+ );
+ }
+
+ public static void
+ main(String[] args)
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.setProperty("Ice.Admin.DelayCreation", "1");
+
+ Server server = new Server();
+ System.exit(server.main("IceBox.Server", args, initData));
+ }
+
+ @Override
+ public int
+ run(String[] args)
+ {
+ final String prefix = "IceBox.Service.";
+ Ice.Properties properties = communicator().getProperties();
+ java.util.Map<String, String> services = properties.getPropertiesForPrefix(prefix);
+ java.util.List<String> argSeq = new java.util.ArrayList<String>(args.length);
+ for(String s : args)
+ {
+ argSeq.add(s);
+ }
+
+ for(java.util.Map.Entry<String, String> entry : services.entrySet())
+ {
+ String name = entry.getKey().substring(prefix.length());
+ for(int i = 0; i < argSeq.size(); ++i)
+ {
+ if(argSeq.get(i).startsWith("--" + name))
+ {
+ argSeq.remove(i);
+ i--;
+ }
+ }
+ }
+
+ for(String arg : argSeq)
+ {
+ if(arg.equals("-h") || arg.equals("--help"))
+ {
+ usage();
+ return 0;
+ }
+ else
+ {
+ System.err.println("Server: unknown option `" + arg + "'");
+ usage();
+ return 1;
+ }
+ }
+
+ ServiceManagerI serviceManagerImpl = new ServiceManagerI(communicator(), args);
+ return serviceManagerImpl.run();
+ }
+}
diff --git a/java-compat/src/IceBox/src/main/java/IceBox/ServiceManagerI.java b/java-compat/src/IceBox/src/main/java/IceBox/ServiceManagerI.java
new file mode 100644
index 00000000000..ceefc3170ff
--- /dev/null
+++ b/java-compat/src/IceBox/src/main/java/IceBox/ServiceManagerI.java
@@ -0,0 +1,1178 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceBox;
+
+import java.net.URLEncoder;
+
+//
+// NOTE: the class isn't final on purpose to allow users to eventually
+// extend it.
+//
+public class ServiceManagerI extends _ServiceManagerDisp
+{
+ public
+ ServiceManagerI(Ice.Communicator communicator, String[] args)
+ {
+ _communicator = communicator;
+ _logger = _communicator.getLogger();
+
+ Ice.Properties props = _communicator.getProperties();
+
+ if(props.getProperty("Ice.Admin.Enabled").isEmpty())
+ {
+ _adminEnabled = !props.getProperty("Ice.Admin.Endpoints").isEmpty();
+ }
+ else
+ {
+ _adminEnabled = props.getPropertyAsInt("Ice.Admin.Enabled") > 0;
+ }
+
+ if(_adminEnabled)
+ {
+ String[] facetFilter = props.getPropertyAsList("Ice.Admin.Facets");
+ if(facetFilter.length > 0)
+ {
+ _adminFacetFilter = new java.util.HashSet<String>(java.util.Arrays.asList(facetFilter));
+ }
+ else
+ {
+ _adminFacetFilter = new java.util.HashSet<String>();
+ }
+ }
+
+ _argv = args;
+ _traceServiceObserver = props.getPropertyAsInt("IceBox.Trace.ServiceObserver");
+ _observerCompletedCB = new Ice.Callback()
+ {
+ @Override
+ public void completed(Ice.AsyncResult result)
+ {
+ try
+ {
+ result.throwLocalException();
+ }
+ catch(Ice.LocalException ex)
+ {
+ ServiceObserverPrx observer = ServiceObserverPrxHelper.uncheckedCast(result.getProxy());
+ synchronized(ServiceManagerI.this)
+ {
+ if(_observers.remove(observer))
+ {
+ observerRemoved(observer, ex);
+ }
+ }
+ }
+ }
+ };
+ }
+
+ @Override
+ public java.util.Map<String, String>
+ getSliceChecksums(Ice.Current current)
+ {
+ return SliceChecksums.checksums;
+ }
+
+ @Override
+ public void
+ startService(String name, Ice.Current current)
+ throws AlreadyStartedException, NoSuchServiceException
+ {
+ ServiceInfo info = null;
+ synchronized(this)
+ {
+ //
+ // Search would be more efficient if services were contained in
+ // a map, but order is required for shutdown.
+ //
+ for(ServiceInfo p : _services)
+ {
+ if(p.name.equals(name))
+ {
+ if(p.status == StatusStarted)
+ {
+ throw new AlreadyStartedException();
+ }
+ p.status = StatusStarting;
+ info = p.clone();
+ break;
+ }
+ }
+ if(info == null)
+ {
+ throw new NoSuchServiceException();
+ }
+ _pendingStatusChanges = true;
+ }
+
+ boolean started = false;
+ try
+ {
+ info.service.start(name, info.communicator == null ? _sharedCommunicator : info.communicator, info.args);
+ started = true;
+ }
+ catch(java.lang.Exception e)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ _logger.warning("ServiceManager: exception while starting service " + info.name + ":\n" + sw.toString());
+ }
+
+ synchronized(this)
+ {
+ for(ServiceInfo p : _services)
+ {
+ if(p.name.equals(name))
+ {
+ if(started)
+ {
+ p.status = StatusStarted;
+
+ java.util.List<String> services = new java.util.ArrayList<String>();
+ services.add(name);
+ servicesStarted(services, _observers);
+ }
+ else
+ {
+ p.status = StatusStopped;
+ }
+ break;
+ }
+ }
+ _pendingStatusChanges = false;
+ notifyAll();
+ }
+ }
+
+ @Override
+ public void
+ stopService(String name, Ice.Current current)
+ throws AlreadyStoppedException, NoSuchServiceException
+ {
+ ServiceInfo info = null;
+ synchronized(this)
+ {
+ //
+ // Search would be more efficient if services were contained in
+ // a map, but order is required for shutdown.
+ //
+ for(ServiceInfo p : _services)
+ {
+ if(p.name.equals(name))
+ {
+ if(p.status == StatusStopped)
+ {
+ throw new AlreadyStoppedException();
+ }
+ p.status = StatusStopping;
+ info = p.clone();
+ break;
+ }
+ }
+ if(info == null)
+ {
+ throw new NoSuchServiceException();
+ }
+ _pendingStatusChanges = true;
+ }
+
+ boolean stopped = false;
+ try
+ {
+ info.service.stop();
+ stopped = true;
+ }
+ catch(java.lang.Exception e)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ _logger.warning("ServiceManager: exception while stopping service " + info.name + ":\n" + sw.toString());
+ }
+
+ synchronized(this)
+ {
+ for(ServiceInfo p : _services)
+ {
+ if(p.name.equals(name))
+ {
+ if(stopped)
+ {
+ p.status = StatusStopped;
+
+ java.util.List<String> services = new java.util.ArrayList<String>();
+ services.add(name);
+ servicesStopped(services, _observers);
+ }
+ else
+ {
+ p.status = StatusStarted;
+ }
+ break;
+ }
+ }
+ _pendingStatusChanges = false;
+ notifyAll();
+ }
+ }
+
+ @Override
+ public void
+ addObserver(final ServiceObserverPrx observer, Ice.Current current)
+ {
+ java.util.List<String> activeServices = new java.util.LinkedList<String>();
+
+ //
+ // Null observers and duplicate registrations are ignored
+ //
+
+ synchronized(this)
+ {
+ if(observer != null && _observers.add(observer))
+ {
+ if(_traceServiceObserver >= 1)
+ {
+ _logger.trace("IceBox.ServiceObserver",
+ "Added service observer " + _communicator.proxyToString(observer));
+ }
+
+ for(ServiceInfo info: _services)
+ {
+ if(info.status == StatusStarted)
+ {
+ activeServices.add(info.name);
+ }
+ }
+ }
+ }
+
+ if(activeServices.size() > 0)
+ {
+ observer.begin_servicesStarted(activeServices.toArray(new String[0]), _observerCompletedCB);
+ }
+ }
+
+ @Override
+ public void
+ shutdown(Ice.Current current)
+ {
+ _communicator.shutdown();
+ }
+
+ public int
+ run()
+ {
+ try
+ {
+ Ice.Properties properties = _communicator.getProperties();
+
+ //
+ // Create an object adapter. Services probably should NOT share
+ // this object adapter, as the endpoint(s) for this object adapter
+ // will most likely need to be firewalled for security reasons.
+ //
+ Ice.ObjectAdapter adapter = null;
+ if(properties.getProperty("IceBox.ServiceManager.Endpoints").length() != 0)
+ {
+ adapter = _communicator.createObjectAdapter("IceBox.ServiceManager");
+
+ Ice.Identity identity = new Ice.Identity();
+ identity.category = properties.getPropertyWithDefault("IceBox.InstanceName", "IceBox");
+ identity.name = "ServiceManager";
+ adapter.add(this, identity);
+ }
+
+ //
+ // Parse the property set with the prefix "IceBox.Service.". These
+ // properties should have the following format:
+ //
+ // IceBox.Service.Foo=[jar-or-dir:]Package.Foo [args]
+ //
+ // We parse the service properties specified in IceBox.LoadOrder
+ // first, then the ones from remaining services.
+ //
+ final String prefix = "IceBox.Service.";
+ java.util.Map<String, String> services = properties.getPropertiesForPrefix(prefix);
+ String[] loadOrder = properties.getPropertyAsList("IceBox.LoadOrder");
+ java.util.List<StartServiceInfo> servicesInfo = new java.util.ArrayList<StartServiceInfo>();
+ for(String name : loadOrder)
+ {
+ if(name.length() > 0)
+ {
+ String key = prefix + name;
+ String value = services.get(key);
+ if(value == null)
+ {
+ FailureException ex = new FailureException();
+ ex.reason = "ServiceManager: no service definition for `" + name + "'";
+ throw ex;
+ }
+ servicesInfo.add(new StartServiceInfo(name, value, _argv));
+ services.remove(key);
+ }
+ }
+ for(java.util.Map.Entry<String, String> p : services.entrySet())
+ {
+ String name = p.getKey().substring(prefix.length());
+ String value = p.getValue();
+ servicesInfo.add(new StartServiceInfo(name, value, _argv));
+ }
+
+ //
+ // Check if some services are using the shared communicator in which
+ // case we create the shared communicator now with a property set that
+ // is the union of all the service properties (from services that use
+ // the shared communicator).
+ //
+ if(properties.getPropertiesForPrefix("IceBox.UseSharedCommunicator.").size() > 0)
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = createServiceProperties("SharedCommunicator");
+ for(StartServiceInfo service : servicesInfo)
+ {
+ if(properties.getPropertyAsInt("IceBox.UseSharedCommunicator." + service.name) <= 0)
+ {
+ continue;
+ }
+
+ //
+ // Load the service properties using the shared communicator properties as
+ // the default properties.
+ //
+ Ice.StringSeqHolder serviceArgs = new Ice.StringSeqHolder(service.args);
+ Ice.Properties svcProperties = Ice.Util.createProperties(serviceArgs, initData.properties);
+ service.args = serviceArgs.value;
+
+ //
+ // Remove properties from the shared property set that a service explicitly clears.
+ //
+ java.util.Map<String, String> allProps = initData.properties.getPropertiesForPrefix("");
+ for(String key : allProps.keySet())
+ {
+ if(svcProperties.getProperty(key).length() == 0)
+ {
+ initData.properties.setProperty(key, "");
+ }
+ }
+
+ //
+ // Add the service properties to the shared communicator properties.
+ //
+ for(java.util.Map.Entry<String, String> p : svcProperties.getPropertiesForPrefix("").entrySet())
+ {
+ initData.properties.setProperty(p.getKey(), p.getValue());
+ }
+
+ //
+ // Parse <service>.* command line options (the Ice command line options
+ // were parsed by the call to createProperties above).
+ //
+ service.args = initData.properties.parseCommandLineOptions(service.name, service.args);
+ }
+
+ String facetNamePrefix = "IceBox.SharedCommunicator.";
+ boolean addFacets = configureAdmin(initData.properties, facetNamePrefix);
+
+ _sharedCommunicator = Ice.Util.initialize(initData);
+
+ if(addFacets)
+ {
+ // Add all facets created on shared communicator to the IceBox communicator
+ // but renamed <prefix>.<facet-name>, except for the Process facet which is
+ // never added.
+ for(java.util.Map.Entry<String, Ice.Object> p : _sharedCommunicator.findAllAdminFacets().entrySet())
+ {
+ if(!p.getKey().equals("Process"))
+ {
+ _communicator.addAdminFacet(p.getValue(), facetNamePrefix + p.getKey());
+ }
+ }
+ }
+ }
+
+ for(StartServiceInfo s : servicesInfo)
+ {
+ start(s.name, s.className, s.classDir, s.absolutePath, s.args);
+ }
+
+ //
+ // We may want to notify external scripts that the services
+ // have started. This is done by defining the property:
+ //
+ // IceBox.PrintServicesReady=bundleName
+ //
+ // Where bundleName is whatever you choose to call this set of
+ // services. It will be echoed back as "bundleName ready".
+ //
+ // This must be done after start() has been invoked on the
+ // services.
+ //
+ String bundleName = properties.getProperty("IceBox.PrintServicesReady");
+ if(bundleName.length() > 0)
+ {
+ System.out.println(bundleName + " ready");
+ }
+
+ //
+ // Don't move after the adapter activation. This allows
+ // applications to wait for the service manager to be
+ // reachable before sending a signal to shutdown the
+ // IceBox.
+ //
+ Ice.Application.shutdownOnInterrupt();
+
+ //
+ // Register "this" as a facet to the Admin object and
+ // create Admin object
+ //
+ try
+ {
+ _communicator.addAdminFacet(this, "IceBox.ServiceManager");
+ _communicator.getAdmin();
+ }
+ catch(Ice.ObjectAdapterDeactivatedException ex)
+ {
+ //
+ // Expected if the communicator has been shutdown.
+ //
+ }
+
+ //
+ // Start request dispatching after we've started the services.
+ //
+ if(adapter != null)
+ {
+ try
+ {
+ adapter.activate();
+ }
+ catch(Ice.ObjectAdapterDeactivatedException ex)
+ {
+ //
+ // Expected if the communicator has been shutdown.
+ //
+ }
+ }
+
+ _communicator.waitForShutdown();
+ Ice.Application.defaultInterrupt();
+ }
+ catch(FailureException ex)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ pw.println(ex.reason);
+ ex.printStackTrace(pw);
+ pw.flush();
+ _logger.error(sw.toString());
+ return 1;
+ }
+ catch(Throwable ex)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ _logger.error("ServiceManager: caught exception:\n" + sw.toString());
+ return 1;
+ }
+ finally
+ {
+ //
+ // Invoke stop() on the services.
+ //
+ stopAll();
+ }
+
+ return 0;
+ }
+
+ synchronized private void
+ start(String service, String className, String classDir, boolean absolutePath, String[] args)
+ throws FailureException
+ {
+ //
+ // Load the class.
+ //
+
+ //
+ // Use a class loader if the user specified a JAR file or class directory.
+ //
+ Class<?> c = null;
+ if(classDir != null)
+ {
+ try
+ {
+ if(!absolutePath)
+ {
+ classDir = new java.io.File(System.getProperty("user.dir") + java.io.File.separator +
+ classDir).getCanonicalPath();
+ }
+
+ if(!classDir.endsWith(java.io.File.separator) && !classDir.endsWith(".jar"))
+ {
+ classDir += java.io.File.separator;
+ }
+ classDir = URLEncoder.encode(classDir, "UTF-8");
+
+ //
+ // Reuse an existing class loader if we have already loaded a plug-in with
+ // the same value for classDir, otherwise create a new one.
+ //
+ ClassLoader cl = null;
+
+ if(_classLoaders == null)
+ {
+ _classLoaders = new java.util.HashMap<String, ClassLoader>();
+ }
+ else
+ {
+ cl = _classLoaders.get(classDir);
+ }
+
+ if(cl == null)
+ {
+ final java.net.URL[] url = new java.net.URL[] { new java.net.URL("file:///" + classDir) };
+
+ cl = new java.net.URLClassLoader(url);
+
+ _classLoaders.put(classDir, cl);
+ }
+
+ c = cl.loadClass(className);
+ }
+ catch(java.net.MalformedURLException ex)
+ {
+ throw new FailureException("ServiceManager: invalid entry point format `" + classDir + "'", ex);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new FailureException("ServiceManager: invalid path in plug-in entry point `" + classDir +
+ "'", ex);
+ }
+ catch(java.lang.ClassNotFoundException ex)
+ {
+ // Ignored
+ }
+ }
+ else
+ {
+ c = IceInternal.Util.findClass(className, null);
+ }
+
+ if(c == null)
+ {
+ throw new FailureException("ServiceManager: class " + className + " not found");
+ }
+
+ ServiceInfo info = new ServiceInfo();
+ info.name = service;
+ info.status = StatusStopped;
+ info.args = args;
+
+ //
+ // If Ice.UseSharedCommunicator.<name> is defined, create a
+ // communicator for the service. The communicator inherits
+ // from the shared communicator properties. If it's not
+ // defined, add the service properties to the shared
+ // commnunicator property set.
+ //
+ Ice.Communicator communicator;
+ if(_communicator.getProperties().getPropertyAsInt("IceBox.UseSharedCommunicator." + service) > 0)
+ {
+ assert(_sharedCommunicator != null);
+ communicator = _sharedCommunicator;
+ }
+ else
+ {
+ try
+ {
+ //
+ // Create the service properties. We use the communicator properties as the default
+ // properties if IceBox.InheritProperties is set.
+ //
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = createServiceProperties(service);
+ Ice.StringSeqHolder serviceArgs = new Ice.StringSeqHolder(info.args);
+ if(serviceArgs.value.length > 0)
+ {
+ //
+ // Create the service properties with the given service arguments. This should
+ // read the service config file if it's specified with --Ice.Config.
+ //
+ initData.properties = Ice.Util.createProperties(serviceArgs, initData.properties);
+
+ //
+ // Next, parse the service "<service>.*" command line options (the Ice command
+ // line options were parsed by the createProperties above)
+ //
+ serviceArgs.value = initData.properties.parseCommandLineOptions(service, serviceArgs.value);
+ }
+
+ //
+ // Clone the logger to assign a new prefix. If one of the built-in loggers is configured
+ // don't set any logger.
+ //
+ if(initData.properties.getProperty("Ice.LogFile").length() == 0 &&
+ (initData.properties.getPropertyAsInt("Ice.UseSyslog") <= 0 ||
+ System.getProperty("os.name").startsWith("Windows")))
+ {
+ initData.logger = _logger.cloneWithPrefix(initData.properties.getProperty("Ice.ProgramName"));
+ }
+
+ //
+ // If Admin is enabled on the IceBox communicator, for each service that does not set
+ // Ice.Admin.Enabled, we set Ice.Admin.Enabled=1 to have this service create facets; then
+ // we add these facets to the IceBox Admin object as IceBox.Service.<service>.<facet>.
+ //
+ String serviceFacetNamePrefix = "IceBox.Service." + service + ".";
+ boolean addFacets = configureAdmin(initData.properties, serviceFacetNamePrefix);
+
+ //
+ // Remaining command line options are passed to the communicator. This is
+ // necessary for Ice plug-in properties (e.g.: IceSSL).
+ //
+ info.communicator = Ice.Util.initialize(serviceArgs, initData);
+ info.args = serviceArgs.value;
+ communicator = info.communicator;
+
+ if(addFacets)
+ {
+ // Add all facets created on the service communicator to the IceBox communicator
+ // but renamed IceBox.Service.<service>.<facet-name>, except for the Process facet
+ // which is never added
+ for(java.util.Map.Entry<String, Ice.Object> p : communicator.findAllAdminFacets().entrySet())
+ {
+ if(!p.getKey().equals("Process"))
+ {
+ _communicator.addAdminFacet(p.getValue(), serviceFacetNamePrefix + p.getKey());
+ }
+ }
+ }
+ }
+ catch(Throwable ex)
+ {
+ FailureException e = new FailureException();
+ e.reason = "ServiceManager: exception while starting service " + service;
+ e.initCause(ex);
+ throw e;
+ }
+ }
+
+ try
+ {
+ //
+ // Instantiate the service.
+ //
+ try
+ {
+ //
+ // If the service class provides a constructor that accepts an Ice.Communicator argument,
+ // use that in preference to the default constructor.
+ //
+ java.lang.Object obj = null;
+ try
+ {
+ java.lang.reflect.Constructor<?> con = c.getDeclaredConstructor(Ice.Communicator.class);
+ obj = con.newInstance(_communicator);
+ }
+ catch(IllegalAccessException ex)
+ {
+ throw new FailureException(
+ "ServiceManager: unable to access service constructor " + className + "(Ice.Communicator)", ex);
+ }
+ catch(NoSuchMethodException ex)
+ {
+ // Ignore.
+ }
+ catch(java.lang.reflect.InvocationTargetException ex)
+ {
+ if(ex.getCause() != null)
+ {
+ throw ex.getCause();
+ }
+ else
+ {
+ throw new FailureException("ServiceManager: exception in service constructor for " + className, ex);
+ }
+ }
+
+ if(obj == null)
+ {
+ //
+ // Fall back to the default constructor.
+ //
+ try
+ {
+ obj = c.newInstance();
+ }
+ catch(IllegalAccessException ex)
+ {
+ throw new FailureException(
+ "ServiceManager: unable to access default service constructor in class " + className, ex);
+ }
+ }
+
+ try
+ {
+ info.service = (Service)obj;
+ }
+ catch(ClassCastException ex)
+ {
+ throw new FailureException("ServiceManager: class " + className + " does not implement IceBox.Service");
+ }
+ }
+ catch(InstantiationException ex)
+ {
+ throw new FailureException("ServiceManager: unable to instantiate class " + className, ex);
+ }
+ catch(FailureException ex)
+ {
+ throw ex;
+ }
+ catch(Throwable ex)
+ {
+ throw new FailureException("ServiceManager: exception in service constructor for " + className, ex);
+ }
+
+ try
+ {
+ info.service.start(service, communicator, info.args);
+
+ //
+ // There is no need to notify the observers since the 'start all'
+ // (that indirectly calls this method) occurs before the creation of
+ // the Server Admin object, and before the activation of the main
+ // object adapter (so before any observer can be registered)
+ //
+ }
+ catch(FailureException ex)
+ {
+ throw ex;
+ }
+ catch(Throwable ex)
+ {
+ FailureException e = new FailureException();
+ e.reason = "ServiceManager: exception while starting service " + service;
+ e.initCause(ex);
+ throw e;
+ }
+
+ info.status = StatusStarted;
+ _services.add(info);
+ }
+ catch(RuntimeException ex)
+ {
+ if(info.communicator != null)
+ {
+ destroyServiceCommunicator(service, info.communicator);
+ }
+
+ throw ex;
+ }
+ }
+
+ private synchronized void
+ stopAll()
+ {
+ //
+ // First wait for any active startService/stopService calls to complete.
+ //
+ while(_pendingStatusChanges)
+ {
+ try
+ {
+ wait();
+ }
+ catch(java.lang.InterruptedException ex)
+ {
+ }
+ }
+
+ //
+ // For each service, we call stop on the service and flush its database environment to
+ // the disk. Services are stopped in the reverse order of the order they were started.
+ //
+ java.util.List<String> stoppedServices = new java.util.ArrayList<String>();
+ java.util.ListIterator<ServiceInfo> p = _services.listIterator(_services.size());
+ while(p.hasPrevious())
+ {
+ ServiceInfo info = p.previous();
+ if(info.status == StatusStarted)
+ {
+ try
+ {
+ info.service.stop();
+ info.status = StatusStopped;
+ stoppedServices.add(info.name);
+ }
+ catch(Throwable e)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ _logger.warning("ServiceManager: exception while stopping service " + info.name + ":\n" +
+ sw.toString());
+ }
+ }
+
+ if(info.communicator != null)
+ {
+ destroyServiceCommunicator(info.name, info.communicator);
+ }
+ }
+
+ if(_sharedCommunicator != null)
+ {
+ removeAdminFacets("IceBox.SharedCommunicator.");
+
+ try
+ {
+ _sharedCommunicator.destroy();
+ }
+ catch(java.lang.Exception e)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ _logger.warning("ServiceManager: exception while destroying shared communicator:\n" + sw.toString());
+ }
+ _sharedCommunicator = null;
+ }
+
+ _services.clear();
+ servicesStopped(stoppedServices, _observers);
+ }
+
+ private void
+ servicesStarted(java.util.List<String> services, java.util.Set<ServiceObserverPrx> observers)
+ {
+ if(services.size() > 0)
+ {
+ String[] servicesArray = services.toArray(new String[0]);
+
+ for(final ServiceObserverPrx observer: observers)
+ {
+ observer.begin_servicesStarted(servicesArray, _observerCompletedCB);
+ }
+ }
+ }
+
+ private void
+ servicesStopped(java.util.List<String> services, java.util.Set<ServiceObserverPrx> observers)
+ {
+ if(services.size() > 0)
+ {
+ String[] servicesArray = services.toArray(new String[0]);
+
+ for(final ServiceObserverPrx observer: observers)
+ {
+ observer.begin_servicesStopped(servicesArray, _observerCompletedCB);
+ }
+ }
+ }
+
+ private void
+ observerRemoved(ServiceObserverPrx observer, RuntimeException ex)
+ {
+ if(_traceServiceObserver >= 1)
+ {
+ //
+ // CommunicatorDestroyedException may occur during shutdown. The observer notification has
+ // been sent, but the communicator was destroyed before the reply was received. We do not
+ // log a message for this exception.
+ //
+ if(!(ex instanceof Ice.CommunicatorDestroyedException))
+ {
+ _logger.trace("IceBox.ServiceObserver",
+ "Removed service observer " + _communicator.proxyToString(observer)
+ + "\nafter catching " + ex.toString());
+ }
+ }
+ }
+
+ public final static int StatusStopping = 0;
+ public final static int StatusStopped = 1;
+ public final static int StatusStarting = 2;
+ public final static int StatusStarted = 3;
+
+ static final class ServiceInfo implements Cloneable
+ {
+ @Override
+ public ServiceInfo clone()
+ {
+ ServiceInfo c = null;
+ try
+ {
+ c = (ServiceInfo)super.clone();
+ }
+ catch(CloneNotSupportedException ex)
+ {
+ }
+ return c;
+ }
+
+ public String name;
+ public Service service;
+ public Ice.Communicator communicator = null;
+ public int status;
+ public String[] args;
+ }
+
+ static class StartServiceInfo
+ {
+ StartServiceInfo(String service, String value, String[] serverArgs)
+ {
+ name = service;
+
+ //
+ // We support the following formats:
+ //
+ // <class-name> [args]
+ // <jar-file>:<class-name> [args]
+ // <class-dir>:<class-name> [args]
+ // "<path with spaces>":<class-name> [args]
+ // "<path with spaces>:<class-name>" [args]
+ //
+
+ try
+ {
+ args = IceUtilInternal.Options.split(value);
+ }
+ catch(IceUtilInternal.Options.BadQuote ex)
+ {
+ throw new FailureException("ServiceManager: invalid arguments for service `" + name + "':\n" +
+ ex.getMessage());
+ }
+
+ assert(args.length > 0);
+
+ final String entryPoint = args[0];
+
+ final boolean isWindows = System.getProperty("os.name").startsWith("Windows");
+ absolutePath = false;
+
+ //
+ // Find first ':' that isn't part of the file path.
+ //
+ int pos = entryPoint.indexOf(':');
+ if(isWindows)
+ {
+ final String driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if(pos == 1 && entryPoint.length() > 2 && driveLetters.indexOf(entryPoint.charAt(0)) != -1 &&
+ (entryPoint.charAt(2) == '\\' || entryPoint.charAt(2) == '/'))
+ {
+ absolutePath = true;
+ pos = entryPoint.indexOf(':', pos + 1);
+ }
+ if(!absolutePath)
+ {
+ absolutePath = entryPoint.startsWith("\\\\");
+ }
+ }
+ else
+ {
+ absolutePath = entryPoint.startsWith("/");
+ }
+
+ if((pos == -1 && absolutePath) || (pos != -1 && entryPoint.length() <= pos + 1))
+ {
+ //
+ // Class name is missing.
+ //
+ throw new FailureException("ServiceManager: invalid entry point for service `" + name + "':\n" +
+ entryPoint);
+ }
+
+ //
+ // Extract the JAR file or subdirectory, if any.
+ //
+ classDir = null; // Path name of JAR file or subdirectory.
+
+ if(pos == -1)
+ {
+ className = entryPoint;
+ }
+ else
+ {
+ classDir = entryPoint.substring(0, pos).trim();
+ className = entryPoint.substring(pos + 1).trim();
+ }
+
+ //
+ // Shift the arguments.
+ //
+ String[] tmp = new String[args.length - 1];
+ System.arraycopy(args, 1, tmp, 0, args.length - 1);
+ args = tmp;
+
+ if(serverArgs.length > 0)
+ {
+ java.util.List<String> l = new java.util.ArrayList<String>(java.util.Arrays.asList(args));
+ for(String arg : serverArgs)
+ {
+ if(arg.startsWith("--" + service + "."))
+ {
+ l.add(arg);
+ }
+ }
+ args = l.toArray(args);
+ }
+ }
+
+ String name;
+ String[] args;
+ String className;
+ String classDir;
+ boolean absolutePath;
+ }
+
+ private Ice.Properties
+ createServiceProperties(String service)
+ {
+ Ice.Properties properties;
+ Ice.Properties communicatorProperties = _communicator.getProperties();
+ if(communicatorProperties.getPropertyAsInt("IceBox.InheritProperties") > 0)
+ {
+ properties = communicatorProperties._clone();
+ // Inherit all except Ice.Admin.xxx properties
+ for(String p : properties.getPropertiesForPrefix("Ice.Admin.").keySet())
+ {
+ properties.setProperty(p, "");
+ }
+ }
+ else
+ {
+ properties = Ice.Util.createProperties();
+ }
+
+ String programName = communicatorProperties.getProperty("Ice.ProgramName");
+ if(programName.length() == 0)
+ {
+ properties.setProperty("Ice.ProgramName", service);
+ }
+ else
+ {
+ properties.setProperty("Ice.ProgramName", programName + "-" + service);
+ }
+ return properties;
+ }
+
+ private void
+ destroyServiceCommunicator(String service, Ice.Communicator communicator)
+ {
+ try
+ {
+ communicator.shutdown();
+ communicator.waitForShutdown();
+ }
+ catch(Ice.CommunicatorDestroyedException e)
+ {
+ //
+ // Ignore, the service might have already destroyed
+ // the communicator for its own reasons.
+ //
+ }
+ catch(java.lang.Exception e)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ _logger.warning("ServiceManager: exception in shutting down communicator for service "
+ + service + "\n" + sw.toString());
+ }
+
+ removeAdminFacets("IceBox.Service." + service + ".");
+
+ try
+ {
+ communicator.destroy();
+ }
+ catch(java.lang.Exception e)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ _logger.warning("ServiceManager: exception in destroying communicator for service "
+ + service + "\n" + sw.toString());
+ }
+ }
+
+ private boolean configureAdmin(Ice.Properties properties, String prefix)
+ {
+ if(_adminEnabled && properties.getProperty("Ice.Admin.Enabled").isEmpty())
+ {
+ java.util.List<String> facetNames = new java.util.LinkedList<String>();
+ for(String p : _adminFacetFilter)
+ {
+ if(p.startsWith(prefix))
+ {
+ facetNames.add(p.substring(prefix.length()));
+ }
+ }
+
+ if(_adminFacetFilter.isEmpty() || !facetNames.isEmpty())
+ {
+ properties.setProperty("Ice.Admin.Enabled", "1");
+
+ if(!facetNames.isEmpty())
+ {
+ // TODO: need joinString with escape!
+ properties.setProperty("Ice.Admin.Facets", IceUtilInternal.StringUtil.joinString(facetNames, " "));
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void removeAdminFacets(String prefix)
+ {
+ try
+ {
+ for(String p : _communicator.findAllAdminFacets().keySet())
+ {
+ if(p.startsWith(prefix))
+ {
+ _communicator.removeAdminFacet(p);
+ }
+ }
+ }
+ catch(Ice.CommunicatorDestroyedException ex)
+ {
+ // Ignored
+ }
+ catch(Ice.ObjectAdapterDeactivatedException ex)
+ {
+ // Ignored
+ }
+ }
+
+
+ private Ice.Communicator _communicator;
+ private boolean _adminEnabled = false;
+ private java.util.Set<String> _adminFacetFilter;
+ private Ice.Communicator _sharedCommunicator;
+ private Ice.Logger _logger;
+ private String[] _argv; // Filtered server argument vector
+ private java.util.List<ServiceInfo> _services = new java.util.LinkedList<ServiceInfo>();
+ private boolean _pendingStatusChanges = false;
+ private Ice.Callback _observerCompletedCB;
+ private java.util.HashSet<ServiceObserverPrx> _observers = new java.util.HashSet<ServiceObserverPrx>();
+ private int _traceServiceObserver = 0;
+ private java.util.Map<String, ClassLoader> _classLoaders;
+}
diff --git a/java-compat/src/IceDiscovery/build.gradle b/java-compat/src/IceDiscovery/build.gradle
new file mode 100644
index 00000000000..c64a33f1ccd
--- /dev/null
+++ b/java-compat/src/IceDiscovery/build.gradle
@@ -0,0 +1,27 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+sourceCompatibility = iceSourceCompatibility
+targetCompatibility = iceTargetCompatibility
+
+project.ext.displayName = "IceDiscovery Compat"
+project.ext.description = "Allow Ice applications to discover objects and object adapters"
+
+slice {
+ java {
+ args = "--ice"
+ files = fileTree(dir: "$sliceDir/IceDiscovery", includes:['*.ice'], excludes:["*F.ice"])
+ }
+}
+
+dependencies {
+ compile project(':ice-compat')
+}
+
+apply from: "$rootProject.projectDir/../java/gradle/library.gradle"
diff --git a/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LocatorI.java b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LocatorI.java
new file mode 100644
index 00000000000..7061f168010
--- /dev/null
+++ b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LocatorI.java
@@ -0,0 +1,43 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceDiscovery;
+
+class LocatorI extends Ice._LocatorDisp
+{
+ public LocatorI(LookupI lookup, Ice.LocatorRegistryPrx registry)
+ {
+ _lookup = lookup;
+ _registry = registry;
+ }
+
+ @Override
+ public void
+ findObjectById_async(Ice.AMD_Locator_findObjectById cb, Ice.Identity id, Ice.Current current)
+ {
+ _lookup.findObject(cb, id);
+ }
+
+ @Override
+ public void
+ findAdapterById_async(Ice.AMD_Locator_findAdapterById cb, String adapterId, Ice.Current current)
+ {
+ _lookup.findAdapter(cb, adapterId);
+ }
+
+ @Override
+ public Ice.LocatorRegistryPrx
+ getRegistry(Ice.Current current)
+ {
+ return _registry;
+ }
+
+ private final LookupI _lookup;
+ private final Ice.LocatorRegistryPrx _registry;
+}
diff --git a/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LocatorRegistryI.java b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LocatorRegistryI.java
new file mode 100644
index 00000000000..be8e0e6f220
--- /dev/null
+++ b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LocatorRegistryI.java
@@ -0,0 +1,179 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceDiscovery;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
+
+class LocatorRegistryI extends Ice._LocatorRegistryDisp
+{
+ public LocatorRegistryI(Ice.Communicator com)
+ {
+ _wellKnownProxy = com.stringToProxy("p").ice_locator(null).ice_router(null).ice_collocationOptimized(true);
+ }
+
+ @Override
+ synchronized public void
+ setAdapterDirectProxy_async(Ice.AMD_LocatorRegistry_setAdapterDirectProxy cb,
+ String adapterId,
+ Ice.ObjectPrx proxy,
+ Ice.Current current)
+ {
+ if(proxy != null)
+ {
+ _adapters.put(adapterId, proxy);
+ }
+ else
+ {
+ _adapters.remove(adapterId);
+ }
+ cb.ice_response();
+ }
+
+ @Override
+ synchronized public void
+ setReplicatedAdapterDirectProxy_async(Ice.AMD_LocatorRegistry_setReplicatedAdapterDirectProxy cb,
+ String adapterId,
+ String replicaGroupId,
+ Ice.ObjectPrx proxy,
+ Ice.Current current)
+ {
+ if(proxy != null)
+ {
+ _adapters.put(adapterId, proxy);
+ Set<String> s = _replicaGroups.get(replicaGroupId);
+ if(s == null)
+ {
+ s = new HashSet<String>();
+ _replicaGroups.put(replicaGroupId, s);
+ }
+ s.add(adapterId);
+ }
+ else
+ {
+ _adapters.remove(adapterId);
+ Set<String> s = _replicaGroups.get(replicaGroupId);
+ if(s != null)
+ {
+ s.remove(adapterId);
+ if(s.isEmpty())
+ {
+ _replicaGroups.remove(adapterId);
+ }
+ }
+ }
+ cb.ice_response();
+ }
+
+ @Override
+ public void
+ setServerProcessProxy_async(Ice.AMD_LocatorRegistry_setServerProcessProxy cb,
+ String serverId,
+ Ice.ProcessPrx process,
+ Ice.Current current)
+ {
+ cb.ice_response();
+ }
+
+ synchronized Ice.ObjectPrx
+ findObject(Ice.Identity id)
+ {
+ if(id.name.length() == 0)
+ {
+ return null;
+ }
+
+ Ice.ObjectPrx prx = _wellKnownProxy.ice_identity(id);
+
+ List<String> adapterIds = new ArrayList<String>();
+ for(String a : _replicaGroups.keySet())
+ {
+ try
+ {
+ prx.ice_adapterId(a).ice_ping();
+ adapterIds.add(a);
+ }
+ catch(Ice.LocalException ex)
+ {
+ }
+ }
+ if(adapterIds.isEmpty())
+ {
+ for(String a : _adapters.keySet())
+ {
+ try
+ {
+ prx.ice_adapterId(a).ice_ping();
+ adapterIds.add(a);
+ }
+ catch(Ice.LocalException ex)
+ {
+ }
+ }
+ }
+
+ if(adapterIds.isEmpty())
+ {
+ return null;
+ }
+ java.util.Collections.shuffle(adapterIds);
+ return prx.ice_adapterId(adapterIds.get(0));
+ }
+
+ synchronized Ice.ObjectPrx
+ findAdapter(String adapterId, Ice.Holder<Boolean> isReplicaGroup)
+ {
+ Ice.ObjectPrx proxy = _adapters.get(adapterId);
+ if(proxy != null)
+ {
+ isReplicaGroup.value = false;
+ return proxy;
+ }
+
+ Set<String> s = _replicaGroups.get(adapterId);
+ if(s != null)
+ {
+ List<Ice.Endpoint> endpoints = new ArrayList<Ice.Endpoint>();
+ Ice.ObjectPrx prx = null;
+ for(String a : s)
+ {
+ proxy = _adapters.get(a);
+ if(proxy == null)
+ {
+ continue; // TODO: Inconsistency
+ }
+
+ if(prx == null)
+ {
+ prx = proxy;
+ }
+
+ endpoints.addAll(java.util.Arrays.asList(proxy.ice_getEndpoints()));
+ }
+
+ if(prx != null)
+ {
+ isReplicaGroup.value = true;
+ return prx.ice_endpoints(endpoints.toArray(new Ice.Endpoint[endpoints.size()]));
+ }
+ }
+ isReplicaGroup.value = false;
+ return null;
+ }
+
+ final Ice.ObjectPrx _wellKnownProxy;
+ final Map<String, Ice.ObjectPrx> _adapters = new HashMap<String, Ice.ObjectPrx>();
+ final Map<String, Set<String>> _replicaGroups = new HashMap<String, Set<String>>();
+}
+
diff --git a/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupI.java b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupI.java
new file mode 100644
index 00000000000..003fe63c53b
--- /dev/null
+++ b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupI.java
@@ -0,0 +1,399 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceDiscovery;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+
+class LookupI extends _LookupDisp
+{
+ abstract private class Request<T, AmdCB> implements Runnable
+ {
+ Request(T id, int retryCount)
+ {
+ _id = id;
+ _nRetry = retryCount;
+ }
+
+ T
+ getId()
+ {
+ return _id;
+ }
+
+ boolean
+ addCallback(AmdCB cb)
+ {
+ _callbacks.add(cb);
+ return _callbacks.size() == 1;
+ }
+
+ boolean
+ retry()
+ {
+ return --_nRetry >= 0;
+ }
+
+ void
+ scheduleTimer(long timeout)
+ {
+ _future = _timer.schedule(this, timeout, java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+
+ void
+ cancelTimer()
+ {
+ assert _future != null;
+ _future.cancel(false);
+ _future = null;
+ }
+
+ protected int _nRetry;
+ protected List<AmdCB> _callbacks = new ArrayList<AmdCB>();
+ private T _id;
+ protected java.util.concurrent.Future<?> _future;
+ };
+
+ private class AdapterRequest extends Request<String, Ice.AMD_Locator_findAdapterById>
+ {
+ AdapterRequest(String id, int retryCount)
+ {
+ super(id, retryCount);
+ _start = System.nanoTime();
+ _latency = 0;
+ }
+
+ @Override
+ boolean
+ retry()
+ {
+ return _proxies.size() == 0 && --_nRetry >= 0;
+ }
+
+ boolean
+ response(Ice.ObjectPrx proxy, boolean isReplicaGroup)
+ {
+ if(isReplicaGroup)
+ {
+ _proxies.add(proxy);
+ if(_latency == 0)
+ {
+ _latency = (long)((System.nanoTime() - _start) * _latencyMultiplier / 100000.0);
+ if(_latency == 0)
+ {
+ _latency = 1; // 1ms
+ }
+ cancelTimer();
+ scheduleTimer(_latency);
+ }
+ return false;
+ }
+ finished(proxy);
+ return true;
+ }
+
+ void
+ finished(Ice.ObjectPrx proxy)
+ {
+ if(proxy != null || _proxies.isEmpty())
+ {
+ sendResponse(proxy);
+ return;
+ }
+ else if(_proxies.size() == 1)
+ {
+ sendResponse(_proxies.get(0));
+ return;
+ }
+
+ List<Ice.Endpoint> endpoints = new ArrayList<Ice.Endpoint>();
+ Ice.ObjectPrx result = null;
+ for(Ice.ObjectPrx prx : _proxies)
+ {
+ if(result == null)
+ {
+ result = prx;
+ }
+ endpoints.addAll(java.util.Arrays.asList(prx.ice_getEndpoints()));
+ }
+ sendResponse(result.ice_endpoints(endpoints.toArray(new Ice.Endpoint[endpoints.size()])));
+ }
+
+ @Override
+ public void
+ run()
+ {
+ adapterRequestTimedOut(this);
+ }
+
+ private void
+ sendResponse(Ice.ObjectPrx proxy)
+ {
+ for(Ice.AMD_Locator_findAdapterById cb : _callbacks)
+ {
+ cb.ice_response(proxy);
+ }
+ _callbacks.clear();
+ }
+
+ private List<Ice.ObjectPrx> _proxies = new ArrayList<Ice.ObjectPrx>();
+ private long _start;
+ private long _latency;
+ };
+
+ private class ObjectRequest extends Request<Ice.Identity, Ice.AMD_Locator_findObjectById>
+ {
+ ObjectRequest(Ice.Identity id, int retryCount)
+ {
+ super(id, retryCount);
+ }
+
+ void
+ response(Ice.ObjectPrx proxy)
+ {
+ finished(proxy);
+ }
+
+ void
+ finished(Ice.ObjectPrx proxy)
+ {
+ for(Ice.AMD_Locator_findObjectById cb : _callbacks)
+ {
+ cb.ice_response(proxy);
+ }
+ _callbacks.clear();
+ }
+
+ @Override
+ public void
+ run()
+ {
+ objectRequestTimedOut(this);
+ }
+ };
+
+ public LookupI(LocatorRegistryI registry, LookupPrx lookup, Ice.Properties properties)
+ {
+ _registry = registry;
+ _lookup = lookup;
+ _timeout = properties.getPropertyAsIntWithDefault("IceDiscovery.Timeout", 300);
+ _retryCount = properties.getPropertyAsIntWithDefault("IceDiscovery.RetryCount", 3);
+ _latencyMultiplier = properties.getPropertyAsIntWithDefault("IceDiscovery.LatencyMultiplier", 1);
+ _domainId = properties.getProperty("IceDiscovery.DomainId");
+ _timer = IceInternal.Util.getInstance(lookup.ice_getCommunicator()).timer();
+ }
+
+ void
+ setLookupReply(LookupReplyPrx lookupReply)
+ {
+ _lookupReply = lookupReply;
+ }
+
+ @Override
+ public void
+ findObjectById(String domainId, Ice.Identity id, IceDiscovery.LookupReplyPrx reply, Ice.Current c)
+ {
+ if(!domainId.equals(_domainId))
+ {
+ return; // Ignore.
+ }
+
+ Ice.ObjectPrx proxy = _registry.findObject(id);
+ if(proxy != null)
+ {
+ //
+ // Reply to the mulicast request using the given proxy.
+ //
+ try
+ {
+ reply.begin_foundObjectById(id, proxy);
+ }
+ catch(Ice.LocalException ex)
+ {
+ // Ignore
+ }
+ }
+ }
+
+ @Override
+ public void
+ findAdapterById(String domainId, String adapterId, IceDiscovery.LookupReplyPrx reply, Ice.Current c)
+ {
+ if(!domainId.equals(_domainId))
+ {
+ return; // Ignore.
+ }
+
+ Ice.Holder<Boolean> isReplicaGroup = new Ice.Holder<Boolean>();
+ Ice.ObjectPrx proxy = _registry.findAdapter(adapterId, isReplicaGroup);
+ if(proxy != null)
+ {
+ //
+ // Reply to the multicast request using the given proxy.
+ //
+ try
+ {
+ reply.begin_foundAdapterById(adapterId, proxy, isReplicaGroup.value);
+ }
+ catch(Ice.LocalException ex)
+ {
+ // Ignore
+ }
+ }
+ }
+
+ synchronized void
+ findObject(Ice.AMD_Locator_findObjectById cb, Ice.Identity id)
+ {
+ ObjectRequest request = _objectRequests.get(id);
+ if(request == null)
+ {
+ request = new ObjectRequest(id, _retryCount);
+ _objectRequests.put(id, request);
+ }
+
+ if(request.addCallback(cb))
+ {
+ try
+ {
+ _lookup.begin_findObjectById(_domainId, id, _lookupReply);
+ request.scheduleTimer(_timeout);
+ }
+ catch(Ice.LocalException ex)
+ {
+ request.finished(null);
+ _objectRequests.remove(id);
+ }
+ }
+ }
+
+ synchronized void
+ findAdapter(Ice.AMD_Locator_findAdapterById cb, String adapterId)
+ {
+ AdapterRequest request = _adapterRequests.get(adapterId);
+ if(request == null)
+ {
+ request = new AdapterRequest(adapterId, _retryCount);
+ _adapterRequests.put(adapterId, request);
+ }
+
+ if(request.addCallback(cb))
+ {
+ try
+ {
+ _lookup.begin_findAdapterById(_domainId, adapterId, _lookupReply);
+ request.scheduleTimer(_timeout);
+ }
+ catch(Ice.LocalException ex)
+ {
+ request.finished(null);
+ _adapterRequests.remove(adapterId);
+ }
+ }
+ }
+
+ synchronized void
+ foundObject(Ice.Identity id, Ice.ObjectPrx proxy)
+ {
+ ObjectRequest request = _objectRequests.get(id);
+ if(request == null)
+ {
+ return;
+ }
+
+ request.response(proxy);
+ request.cancelTimer();
+ _objectRequests.remove(id);
+ }
+
+ synchronized void
+ foundAdapter(String adapterId, Ice.ObjectPrx proxy, boolean isReplicaGroup)
+ {
+ AdapterRequest request = _adapterRequests.get(adapterId);
+ if(request == null)
+ {
+ return;
+ }
+
+ if(request.response(proxy, isReplicaGroup))
+ {
+ request.cancelTimer();
+ _adapterRequests.remove(adapterId);
+ }
+ }
+
+ synchronized void
+ objectRequestTimedOut(ObjectRequest request)
+ {
+ ObjectRequest r = _objectRequests.get(request.getId());
+ if(r == null || request != r)
+ {
+ return;
+ }
+
+ if(request.retry())
+ {
+ try
+ {
+ _lookup.begin_findObjectById(_domainId, request.getId(), _lookupReply);
+ request.scheduleTimer(_timeout);
+ return;
+ }
+ catch(Ice.LocalException ex)
+ {
+ }
+ }
+
+ request.finished(null);
+ _objectRequests.remove(request.getId());
+ }
+
+ synchronized void
+ adapterRequestTimedOut(AdapterRequest request)
+ {
+ AdapterRequest r = _adapterRequests.get(request.getId());
+ if(r == null || r != request)
+ {
+ return;
+ }
+
+ if(request.retry())
+ {
+ try
+ {
+ _lookup.begin_findAdapterById(_domainId, request.getId(), _lookupReply);
+ request.scheduleTimer(_timeout);
+ return;
+ }
+ catch(Ice.LocalException ex)
+ {
+ }
+ }
+
+ request.finished(null);
+ _adapterRequests.remove(request.getId());
+ }
+
+ private LocatorRegistryI _registry;
+ private final LookupPrx _lookup;
+ private LookupReplyPrx _lookupReply;
+ private final int _timeout;
+ private final int _retryCount;
+ private final int _latencyMultiplier;
+ private final String _domainId;
+
+ private final java.util.concurrent.ScheduledExecutorService _timer;
+
+ private Map<Ice.Identity, ObjectRequest> _objectRequests = new HashMap<Ice.Identity, ObjectRequest>();
+ private Map<String, AdapterRequest> _adapterRequests = new HashMap<String, AdapterRequest>();
+}
+
diff --git a/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupReplyI.java b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupReplyI.java
new file mode 100644
index 00000000000..c848d425630
--- /dev/null
+++ b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupReplyI.java
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceDiscovery;
+
+class LookupReplyI extends _LookupReplyDisp
+{
+ public LookupReplyI(LookupI lookup)
+ {
+ _lookup = lookup;
+ }
+
+ @Override
+ public void
+ foundObjectById(Ice.Identity id, Ice.ObjectPrx proxy, Ice.Current current)
+ {
+ _lookup.foundObject(id, proxy);
+ }
+
+ @Override
+ public void
+ foundAdapterById(String adapterId, Ice.ObjectPrx proxy, boolean isReplicaGroup, Ice.Current current)
+ {
+ _lookup.foundAdapter(adapterId, proxy, isReplicaGroup);
+ }
+
+ private final LookupI _lookup;
+}
+
diff --git a/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginFactory.java b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginFactory.java
new file mode 100644
index 00000000000..506746369a6
--- /dev/null
+++ b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginFactory.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceDiscovery;
+
+public class PluginFactory implements Ice.PluginFactory
+{
+ @Override
+ public Ice.Plugin
+ create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginI(communicator);
+ }
+}
diff --git a/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginI.java b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginI.java
new file mode 100644
index 00000000000..4f45834c7ea
--- /dev/null
+++ b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginI.java
@@ -0,0 +1,138 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceDiscovery;
+
+public class PluginI implements Ice.Plugin
+{
+ public
+ PluginI(Ice.Communicator communicator)
+ {
+ _communicator = communicator;
+ }
+
+ @Override
+ public void
+ initialize()
+ {
+ Ice.Properties properties = _communicator.getProperties();
+
+ boolean ipv4 = properties.getPropertyAsIntWithDefault("Ice.IPv4", 1) > 0;
+ boolean preferIPv6 = properties.getPropertyAsInt("Ice.PreferIPv6Address") > 0;
+ String address;
+ if(ipv4 && !preferIPv6)
+ {
+ address = properties.getPropertyWithDefault("IceDiscovery.Address", "239.255.0.1");
+ }
+ else
+ {
+ address = properties.getPropertyWithDefault("IceDiscovery.Address", "ff15::1");
+ }
+ int port = properties.getPropertyAsIntWithDefault("IceDiscovery.Port", 4061);
+ String intf = properties.getProperty("IceDiscovery.Interface");
+
+ if(properties.getProperty("IceDiscovery.Multicast.Endpoints").isEmpty())
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("udp -h \"").append(address).append("\" -p ").append(port);
+ if(!intf.isEmpty())
+ {
+ s.append(" --interface \"").append(intf).append("\"");
+ }
+ properties.setProperty("IceDiscovery.Multicast.Endpoints", s.toString());
+ }
+ if(properties.getProperty("IceDiscovery.Reply.Endpoints").isEmpty())
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("udp");
+ if(!intf.isEmpty())
+ {
+ s.append(" -h \"").append(intf).append("\"");
+ }
+ properties.setProperty("IceDiscovery.Reply.Endpoints", s.toString());
+ }
+ if(properties.getProperty("IceDiscovery.Locator.Endpoints").isEmpty())
+ {
+ properties.setProperty("IceDiscovery.Locator.AdapterId", java.util.UUID.randomUUID().toString());
+ }
+
+ _multicastAdapter = _communicator.createObjectAdapter("IceDiscovery.Multicast");
+ _replyAdapter = _communicator.createObjectAdapter("IceDiscovery.Reply");
+ _locatorAdapter = _communicator.createObjectAdapter("IceDiscovery.Locator");
+
+ //
+ // Setup locatory registry.
+ //
+ LocatorRegistryI locatorRegistry = new LocatorRegistryI(_communicator);
+ Ice.LocatorRegistryPrx locatorRegistryPrx = Ice.LocatorRegistryPrxHelper.uncheckedCast(
+ _locatorAdapter.addWithUUID(locatorRegistry));
+
+ String lookupEndpoints = properties.getProperty("IceDiscovery.Lookup");
+ if(lookupEndpoints.isEmpty())
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("udp -h \"").append(address).append("\" -p ").append(port);
+ if(!intf.isEmpty())
+ {
+ s.append(" --interface \"").append(intf).append("\"");
+ }
+ lookupEndpoints = s.toString();
+ }
+
+ Ice.ObjectPrx lookupPrx = _communicator.stringToProxy("IceDiscovery/Lookup -d:" + lookupEndpoints);
+ lookupPrx = lookupPrx.ice_collocationOptimized(false); // No collocation optimization for the multicast proxy!
+ try
+ {
+ lookupPrx.ice_getConnection();
+ }
+ catch(Ice.LocalException ex)
+ {
+ StringBuilder b = new StringBuilder();
+ b.append("IceDiscovery is unable to establish a multicast connection:\n");
+ b.append("proxy = ");
+ b.append(lookupPrx.toString());
+ b.append('\n');
+ b.append(ex.toString());
+ throw new Ice.PluginInitializationException(b.toString());
+ }
+
+ //
+ // Add lookup and lookup reply Ice objects
+ //
+ LookupI lookup = new LookupI(locatorRegistry, LookupPrxHelper.uncheckedCast(lookupPrx), properties);
+ _multicastAdapter.add(lookup, Ice.Util.stringToIdentity("IceDiscovery/Lookup"));
+
+ Ice.ObjectPrx lookupReply = _replyAdapter.addWithUUID(new LookupReplyI(lookup)).ice_datagram();
+ lookup.setLookupReply(LookupReplyPrxHelper.uncheckedCast(lookupReply));
+
+ //
+ // Setup locator on the communicator.
+ //
+ Ice.ObjectPrx locator = _locatorAdapter.addWithUUID(new LocatorI(lookup, locatorRegistryPrx));
+ _communicator.setDefaultLocator(Ice.LocatorPrxHelper.uncheckedCast(locator));
+
+ _multicastAdapter.activate();
+ _replyAdapter.activate();
+ _locatorAdapter.activate();
+ }
+
+ @Override
+ public void
+ destroy()
+ {
+ _multicastAdapter.destroy();
+ _replyAdapter.destroy();
+ _locatorAdapter.destroy();
+ }
+
+ private Ice.Communicator _communicator;
+ private Ice.ObjectAdapter _multicastAdapter;
+ private Ice.ObjectAdapter _replyAdapter;
+ private Ice.ObjectAdapter _locatorAdapter;
+}
diff --git a/java-compat/src/IceGrid/build.gradle b/java-compat/src/IceGrid/build.gradle
new file mode 100644
index 00000000000..d2bd4fc5f70
--- /dev/null
+++ b/java-compat/src/IceGrid/build.gradle
@@ -0,0 +1,30 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+sourceCompatibility = iceSourceCompatibility
+targetCompatibility = iceTargetCompatibility
+
+project.ext.displayName = "IceGrid Compat"
+project.ext.description = "Locate, deploy, and manage Ice servers"
+
+slice {
+ java {
+ set1 {
+ args = "--ice --tie --checksum IceGrid.SliceChecksums"
+ files = fileTree(dir: "$sliceDir/IceGrid", includes:['*.ice'], excludes:["*F.ice"])
+ }
+ }
+}
+
+dependencies {
+ compile project(':ice-compat')
+ compile project(':glacier2-compat')
+}
+
+apply from: "$rootProject.projectDir/../java/gradle/library.gradle"
diff --git a/java-compat/src/IceLocatorDiscovery/build.gradle b/java-compat/src/IceLocatorDiscovery/build.gradle
new file mode 100644
index 00000000000..be398fe5e31
--- /dev/null
+++ b/java-compat/src/IceLocatorDiscovery/build.gradle
@@ -0,0 +1,27 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+sourceCompatibility = iceSourceCompatibility
+targetCompatibility = iceTargetCompatibility
+
+project.ext.displayName = "IceLocatorDiscovery Compat"
+project.ext.description = "Ice plug-in that enables the discovery of IceGrid and custom locators via UDP multicast"
+
+slice {
+ java {
+ args = "--ice"
+ files = fileTree(dir: "$sliceDir/IceLocatorDiscovery", includes:['*.ice'], excludes:["*F.ice"])
+ }
+}
+
+dependencies {
+ compile project(':ice-compat')
+}
+
+apply from: "$rootProject.projectDir/../java/gradle/library.gradle"
diff --git a/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginFactory.java b/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginFactory.java
new file mode 100644
index 00000000000..89b2cbba771
--- /dev/null
+++ b/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginFactory.java
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceLocatorDiscovery;
+
+public class PluginFactory implements Ice.PluginFactory
+{
+ @Override
+ public Ice.Plugin
+ create(Ice.Communicator communicator, String name, String[] args)
+ {
+ return new PluginI(communicator);
+ }
+}
diff --git a/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginI.java b/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginI.java
new file mode 100644
index 00000000000..b2fb41d7ced
--- /dev/null
+++ b/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginI.java
@@ -0,0 +1,456 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceLocatorDiscovery;
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+class PluginI implements Ice.Plugin
+{
+ private static class Request
+ {
+ Request(LocatorI locator,
+ String operation,
+ Ice.OperationMode mode,
+ byte[] inParams,
+ java.util.Map<String, String> context,
+ Ice.AMD_Object_ice_invoke amdCB)
+ {
+ _locator = locator;
+ _operation = operation;
+ _mode = mode;
+ _inParams = inParams;
+ _context = context;
+ _amdCB = amdCB;
+ }
+
+ void
+ invoke(Ice.LocatorPrx l)
+ {
+ _locatorPrx = l;
+ try
+ {
+ l.begin_ice_invoke(_operation, _mode, _inParams, _context,
+ new Ice.Callback_Object_ice_invoke()
+ {
+ @Override
+ public void
+ response(boolean ok, byte[] outParams)
+ {
+ _amdCB.ice_response(ok, outParams);
+ }
+
+ @Override
+ public void
+ exception(Ice.LocalException ex)
+ {
+ Request.this.exception(ex);
+ }
+ });
+ }
+ catch(Ice.LocalException ex)
+ {
+ exception(ex);
+ }
+ }
+
+ private void
+ exception(Ice.LocalException ex)
+ {
+ try
+ {
+ throw ex;
+ }
+ catch(Ice.RequestFailedException exc)
+ {
+ _amdCB.ice_exception(ex);
+ }
+ catch(Ice.UnknownException exc)
+ {
+ _amdCB.ice_exception(ex);
+ }
+ catch(Ice.NoEndpointException exc)
+ {
+ _amdCB.ice_exception(new Ice.ObjectNotExistException());
+ }
+ catch(Ice.ObjectAdapterDeactivatedException exc)
+ {
+ _amdCB.ice_exception(new Ice.ObjectNotExistException());
+ }
+ catch(Ice.CommunicatorDestroyedException exc)
+ {
+ _amdCB.ice_exception(new Ice.ObjectNotExistException());
+ }
+ catch(Ice.LocalException exc)
+ {
+ _locator.invoke(_locatorPrx, Request.this); // Retry with new locator proxy
+ }
+ }
+
+ private final LocatorI _locator;
+ private final String _operation;
+ private final Ice.OperationMode _mode;
+ private final java.util.Map<String, String> _context;
+ private final byte[] _inParams;
+ private final Ice.AMD_Object_ice_invoke _amdCB;
+
+ private Ice.LocatorPrx _locatorPrx;
+ };
+
+ static private class VoidLocatorI extends Ice._LocatorDisp
+ {
+ @Override
+ public void
+ findObjectById_async(Ice.AMD_Locator_findObjectById amdCB, Ice.Identity id, Ice.Current current)
+ {
+ amdCB.ice_response(null);
+ }
+
+ @Override
+ public void
+ findAdapterById_async(Ice.AMD_Locator_findAdapterById amdCB, String id, Ice.Current current)
+ {
+ amdCB.ice_response(null);
+ }
+
+ @Override
+ public Ice.LocatorRegistryPrx
+ getRegistry(Ice.Current current)
+ {
+ return null;
+ }
+ };
+
+ private static class LocatorI extends Ice.BlobjectAsync
+ {
+ LocatorI(LookupPrx lookup, Ice.Properties properties, String instanceName, Ice.LocatorPrx voidLocator)
+ {
+ _lookup = lookup;
+ _timeout = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.Timeout", 300);
+ _retryCount = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.RetryCount", 3);
+ _retryDelay = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.RetryDelay", 2000);
+ _timer = IceInternal.Util.getInstance(lookup.ice_getCommunicator()).timer();
+ _instanceName = instanceName;
+ _warned = false;
+ _locator = lookup.ice_getCommunicator().getDefaultLocator();
+ _voidLocator = voidLocator;
+ _pendingRetryCount = 0;
+ }
+
+ public void
+ setLookupReply(LookupReplyPrx lookupReply)
+ {
+ _lookupReply = lookupReply;
+ }
+
+ @Override
+ public synchronized void
+ ice_invoke_async(Ice.AMD_Object_ice_invoke amdCB, byte[] inParams, Ice.Current current)
+ {
+ invoke(null, new Request(this, current.operation, current.mode, inParams, current.ctx, amdCB));
+ }
+
+ public synchronized void
+ foundLocator(Ice.LocatorPrx locator)
+ {
+ if(locator == null ||
+ (!_instanceName.isEmpty() && !locator.ice_getIdentity().category.equals(_instanceName)))
+ {
+ return;
+ }
+
+ //
+ // If we already have a locator assigned, ensure the given locator
+ // has the same identity, otherwise ignore it.
+ //
+ if(_locator != null && !locator.ice_getIdentity().category.equals(_locator.ice_getIdentity().category))
+ {
+ if(!_warned)
+ {
+ _warned = true; // Only warn once
+
+ locator.ice_getCommunicator().getLogger().warning(
+ "received Ice locator with different instance name:\n" +
+ "using = `" + _locator.ice_getIdentity().category + "'\n" +
+ "received = `" + locator.ice_getIdentity().category + "'\n" +
+ "This is typically the case if multiple Ice locators with different " +
+ "instance names are deployed and the property `IceLocatorDiscovery.InstanceName'" +
+ "is not set.");
+ }
+ return;
+ }
+
+ if(_pendingRetryCount > 0) // No need to retry, we found a locator
+ {
+ _future.cancel(false);
+ _future = null;
+
+ _pendingRetryCount = 0;
+ }
+
+ if(_locator != null)
+ {
+ //
+ // We found another locator replica, append its endpoints to the
+ // current locator proxy endpoints.
+ //
+ List<Ice.Endpoint> newEndpoints = new ArrayList<Ice.Endpoint>(
+ Arrays.asList(_locator.ice_getEndpoints()));
+ for(Ice.Endpoint p : locator.ice_getEndpoints())
+ {
+ //
+ // Only add endpoints if not already in the locator proxy endpoints
+ //
+ boolean found = false;
+ for(Ice.Endpoint q : newEndpoints)
+ {
+ if(p.equals(q))
+ {
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ newEndpoints.add(p);
+ }
+
+ }
+ _locator = (Ice.LocatorPrx)_locator.ice_endpoints(
+ newEndpoints.toArray(new Ice.Endpoint[newEndpoints.size()]));
+ }
+ else
+ {
+ _locator = locator;
+ if(_instanceName.isEmpty())
+ {
+ _instanceName = _locator.ice_getIdentity().category; // Stick to the first locator
+ }
+ }
+
+ //
+ // Send pending requests if any.
+ //
+ for(Request req : _pendingRequests)
+ {
+ req.invoke(_locator);
+ }
+ _pendingRequests.clear();
+ }
+
+
+ public synchronized void
+ invoke(Ice.LocatorPrx locator, Request request)
+ {
+ if(_locator != null && _locator != locator)
+ {
+ request.invoke(_locator);
+ }
+ else if(IceInternal.Time.currentMonotonicTimeMillis() < _nextRetry)
+ {
+ request.invoke(_voidLocator); // Don't retry to find a locator before the retry delay expires
+ }
+ else
+ {
+ _locator = null;
+
+ _pendingRequests.add(request);
+
+ if(_pendingRetryCount == 0) // No request in progress
+ {
+ _pendingRetryCount = _retryCount;
+ try
+ {
+ _lookup.begin_findLocator(_instanceName, _lookupReply); // Send multicast request.
+ _future = _timer.schedule(_retryTask, _timeout, java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+ catch(Ice.LocalException ex)
+ {
+ for(Request req : _pendingRequests)
+ {
+ req.invoke(_voidLocator);
+ }
+ _pendingRequests.clear();
+ _pendingRetryCount = 0;
+ }
+ }
+ }
+ }
+
+ private Runnable _retryTask = new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ synchronized(LocatorI.this)
+ {
+ if(--_pendingRetryCount > 0)
+ {
+ try
+ {
+ _lookup.begin_findLocator(_instanceName, _lookupReply); // Send multicast request.
+ _future = _timer.schedule(_retryTask, _timeout, java.util.concurrent.TimeUnit.MILLISECONDS);
+ return;
+ }
+ catch(Ice.LocalException ex)
+ {
+ }
+ _pendingRetryCount = 0;
+ }
+
+ for(Request req : _pendingRequests)
+ {
+ req.invoke(_voidLocator);
+ }
+ _pendingRequests.clear();
+ _nextRetry = IceInternal.Time.currentMonotonicTimeMillis() + _retryDelay;
+ }
+
+ }
+ };
+
+ private final LookupPrx _lookup;
+ private final int _timeout;
+ private java.util.concurrent.Future<?> _future;
+ private final java.util.concurrent.ScheduledExecutorService _timer;
+ private final int _retryCount;
+ private final int _retryDelay;
+
+ private String _instanceName;
+ private boolean _warned;
+ private LookupReplyPrx _lookupReply;
+ private Ice.LocatorPrx _locator;
+ private Ice.LocatorPrx _voidLocator;
+
+ private int _pendingRetryCount;
+ private List<Request> _pendingRequests = new ArrayList<Request>();
+ private long _nextRetry;
+ };
+
+ private class LookupReplyI extends _LookupReplyDisp
+ {
+ LookupReplyI(LocatorI locator)
+ {
+ _locator = locator;
+ }
+
+ @Override
+ public void
+ foundLocator(Ice.LocatorPrx locator, Ice.Current curr)
+ {
+ _locator.foundLocator(locator);
+ }
+
+ private final LocatorI _locator;
+ };
+
+ public
+ PluginI(Ice.Communicator communicator)
+ {
+ _communicator = communicator;
+ }
+
+ @Override
+ public void
+ initialize()
+ {
+ Ice.Properties properties = _communicator.getProperties();
+
+ boolean ipv4 = properties.getPropertyAsIntWithDefault("Ice.IPv4", 1) > 0;
+ boolean preferIPv6 = properties.getPropertyAsInt("Ice.PreferIPv6Address") > 0;
+ String address;
+ if(ipv4 && !preferIPv6)
+ {
+ address = properties.getPropertyWithDefault("IceLocatorDiscovery.Address", "239.255.0.1");
+ }
+ else
+ {
+ address = properties.getPropertyWithDefault("IceLocatorDiscovery.Address", "ff15::1");
+ }
+ int port = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.Port", 4061);
+ String intf = properties.getProperty("IceLocatorDiscovery.Interface");
+
+ if(properties.getProperty("IceLocatorDiscovery.Reply.Endpoints").isEmpty())
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("udp");
+ if(!intf.isEmpty())
+ {
+ s.append(" -h \"").append(intf).append("\"");
+ }
+ properties.setProperty("IceLocatorDiscovery.Reply.Endpoints", s.toString());
+ }
+ if(properties.getProperty("IceLocatorDiscovery.Locator.Endpoints").isEmpty())
+ {
+ properties.setProperty("IceLocatorDiscovery.Locator.AdapterId", java.util.UUID.randomUUID().toString());
+ }
+
+ _replyAdapter = _communicator.createObjectAdapter("IceLocatorDiscovery.Reply");
+ _locatorAdapter = _communicator.createObjectAdapter("IceLocatorDiscovery.Locator");
+
+ // We don't want those adapters to be registered with the locator so clear their locator.
+ _replyAdapter.setLocator(null);
+ _locatorAdapter.setLocator(null);
+
+ String lookupEndpoints = properties.getProperty("IceLocatorDiscovery.Lookup");
+ if(lookupEndpoints.isEmpty())
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("udp -h \"").append(address).append("\" -p ").append(port);
+ if(!intf.isEmpty())
+ {
+ s.append(" --interface \"").append(intf).append("\"");
+ }
+ lookupEndpoints = s.toString();
+ }
+
+ Ice.ObjectPrx lookupPrx = _communicator.stringToProxy("IceLocatorDiscovery/Lookup -d:" + lookupEndpoints);
+ lookupPrx = lookupPrx.ice_collocationOptimized(false); // No collocation optimization for the multicast proxy!
+ try
+ {
+ lookupPrx.ice_getConnection(); // Ensure we can establish a connection to the multicast proxy
+ }
+ catch(Ice.LocalException ex)
+ {
+ StringBuilder s = new StringBuilder();
+ s.append("IceLocatorDiscovery is unable to establish a multicast connection:\n");
+ s.append("proxy = ").append(lookupPrx.toString()).append("\n").append(ex);
+ throw new Ice.PluginInitializationException(s.toString());
+ }
+
+ Ice.LocatorPrx voidLoc = Ice.LocatorPrxHelper.uncheckedCast(_locatorAdapter.addWithUUID(new VoidLocatorI()));
+
+ String instanceName = properties.getProperty("IceLocatorDiscovery.InstanceName");
+ Ice.Identity id = new Ice.Identity();
+ id.name = "Locator";
+ id.category = !instanceName.isEmpty() ? instanceName : java.util.UUID.randomUUID().toString();
+ LocatorI locator = new LocatorI(LookupPrxHelper.uncheckedCast(lookupPrx), properties, instanceName, voidLoc);
+ _communicator.setDefaultLocator(Ice.LocatorPrxHelper.uncheckedCast(_locatorAdapter.addWithUUID(locator)));
+
+ Ice.ObjectPrx lookupReply = _replyAdapter.addWithUUID(new LookupReplyI(locator)).ice_datagram();
+ locator.setLookupReply(LookupReplyPrxHelper.uncheckedCast(lookupReply));
+
+ _replyAdapter.activate();
+ _locatorAdapter.activate();
+ }
+
+ @Override
+ public void
+ destroy()
+ {
+ _replyAdapter.destroy();
+ _locatorAdapter.destroy();
+ }
+
+ private Ice.Communicator _communicator;
+ private Ice.ObjectAdapter _locatorAdapter;
+ private Ice.ObjectAdapter _replyAdapter;
+}
diff --git a/java-compat/src/IcePatch2/build.gradle b/java-compat/src/IcePatch2/build.gradle
new file mode 100644
index 00000000000..31ede53de5a
--- /dev/null
+++ b/java-compat/src/IcePatch2/build.gradle
@@ -0,0 +1,29 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+sourceCompatibility = iceSourceCompatibility
+targetCompatibility = iceTargetCompatibility
+
+project.ext.displayName = "IcePatch2 Compat"
+project.ext.description = "File distribution and patching for Ice"
+
+slice {
+ java {
+ set1 {
+ args = "--ice --tie --checksum IcePatch2.SliceChecksums"
+ files = fileTree(dir: "$sliceDir/IcePatch2", includes:['*.ice'], excludes:["*F.ice"])
+ }
+ }
+}
+
+dependencies {
+ compile project(':ice-compat')
+}
+
+apply from: "$rootProject.projectDir/../java/gradle/library.gradle"
diff --git a/java-compat/src/IceStorm/build.gradle b/java-compat/src/IceStorm/build.gradle
new file mode 100644
index 00000000000..9ce6d131b0f
--- /dev/null
+++ b/java-compat/src/IceStorm/build.gradle
@@ -0,0 +1,29 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+sourceCompatibility = iceSourceCompatibility
+targetCompatibility = iceTargetCompatibility
+
+project.ext.displayName = "IceStorm Compat"
+project.ext.description = "Publish-subscribe event distribution service"
+
+slice {
+ java {
+ set1 {
+ args = "--ice --tie --checksum IceStorm.SliceChecksums"
+ files = fileTree(dir: "$sliceDir/IceStorm", includes:['*.ice'], excludes:["*F.ice"])
+ }
+ }
+}
+
+dependencies {
+ compile project(':ice-compat')
+}
+
+apply from: "$rootProject.projectDir/../java/gradle/library.gradle"