1 // **********************************************************************
3 // Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
5 // This copy of Ice is licensed to you under the terms described in the
6 // ICE_LICENSE file included in this distribution.
8 // **********************************************************************
12 public class RoutableReference
extends Reference
14 public final EndpointI
[]
26 public final LocatorInfo
32 public final RouterInfo
39 getCollocationOptimized()
41 return _collocationOptimized
;
47 return _cacheConnection
;
56 public final Ice
.EndpointSelectionType
57 getEndpointSelection()
59 return _endpointSelection
;
63 getLocatorCacheTimeout()
65 return _locatorCacheTimeout
;
75 changeCompress(boolean newCompress
)
77 RoutableReference r
= (RoutableReference
)super.changeCompress(newCompress
);
78 if(r
!= this && _endpoints
.length
> 0) // Also override the compress flag on the endpoints if it was updated.
80 EndpointI
[] newEndpoints
= new EndpointI
[_endpoints
.length
];
81 for(int i
= 0; i
< _endpoints
.length
; i
++)
83 newEndpoints
[i
] = _endpoints
[i
].compress(newCompress
);
85 r
._endpoints
= newEndpoints
;
91 changeEndpoints(EndpointI
[] newEndpoints
)
93 if(java
.util
.Arrays
.equals(newEndpoints
, _endpoints
))
97 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
98 r
._endpoints
= newEndpoints
;
100 r
.applyOverrides(r
._endpoints
);
105 changeAdapterId(String newAdapterId
)
107 if(_adapterId
.equals(newAdapterId
))
111 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
112 r
._adapterId
= newAdapterId
;
113 r
._endpoints
= _emptyEndpoints
;
118 changeLocator(Ice
.LocatorPrx newLocator
)
120 LocatorInfo newLocatorInfo
= getInstance().locatorManager().get(newLocator
);
121 if(newLocatorInfo
!= null && _locatorInfo
!= null && newLocatorInfo
.equals(_locatorInfo
))
125 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
126 r
._locatorInfo
= newLocatorInfo
;
131 changeRouter(Ice
.RouterPrx newRouter
)
133 RouterInfo newRouterInfo
= getInstance().routerManager().get(newRouter
);
134 if(newRouterInfo
!= null && _routerInfo
!= null && newRouterInfo
.equals(_routerInfo
))
138 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
139 r
._routerInfo
= newRouterInfo
;
144 changeCollocationOptimized(boolean newCollocationOptimized
)
146 if(newCollocationOptimized
== _collocationOptimized
)
150 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
151 r
._collocationOptimized
= newCollocationOptimized
;
155 public final Reference
156 changeCacheConnection(boolean newCache
)
158 if(newCache
== _cacheConnection
)
162 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
163 r
._cacheConnection
= newCache
;
168 changePreferSecure(boolean newPreferSecure
)
170 if(newPreferSecure
== _preferSecure
)
174 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
175 r
._preferSecure
= newPreferSecure
;
179 public final Reference
180 changeEndpointSelection(Ice
.EndpointSelectionType newType
)
182 if(newType
== _endpointSelection
)
186 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
187 r
._endpointSelection
= newType
;
192 changeLocatorCacheTimeout(int newTimeout
)
194 if(_locatorCacheTimeout
== newTimeout
)
198 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
199 r
._locatorCacheTimeout
= newTimeout
;
204 changeTimeout(int newTimeout
)
206 if(_overrideTimeout
&& _timeout
== newTimeout
)
210 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
211 r
._timeout
= newTimeout
;
212 r
._overrideTimeout
= true;
213 if(_endpoints
.length
> 0)
215 EndpointI
[] newEndpoints
= new EndpointI
[_endpoints
.length
];
216 for(int i
= 0; i
< _endpoints
.length
; i
++)
218 newEndpoints
[i
] = _endpoints
[i
].timeout(newTimeout
);
220 r
._endpoints
= newEndpoints
;
226 changeConnectionId(String id
)
228 if(_connectionId
.equals(id
))
232 RoutableReference r
= (RoutableReference
)getInstance().referenceFactory().copy(this);
233 r
._connectionId
= id
;
234 if(_endpoints
.length
> 0)
236 EndpointI
[] newEndpoints
= new EndpointI
[_endpoints
.length
];
237 for(int i
= 0; i
< _endpoints
.length
; i
++)
239 newEndpoints
[i
] = _endpoints
[i
].connectionId(id
);
241 r
._endpoints
= newEndpoints
;
249 return _endpoints
.length
== 0;
255 return _endpoints
.length
== 0 && _adapterId
.length() == 0;
259 streamWrite(BasicStream s
)
260 throws Ice
.MarshalException
262 super.streamWrite(s
);
264 s
.writeSize(_endpoints
.length
);
265 if(_endpoints
.length
> 0)
267 assert(_adapterId
.length() == 0);
268 for(EndpointI endpoint
: _endpoints
)
270 endpoint
.streamWrite(s
);
275 s
.writeString(_adapterId
); // Adapter id.
283 // WARNING: Certain features, such as proxy validation in Glacier2,
284 // depend on the format of proxy strings. Changes to toString() and
285 // methods called to generate parts of the reference string could break
286 // these features. Please review for all features that depend on the
287 // format of proxyToString() before changing this and related code.
289 StringBuilder s
= new StringBuilder(128);
290 s
.append(super.toString());
291 if(_endpoints
.length
> 0)
293 for(EndpointI endpoint
: _endpoints
)
295 String endp
= endpoint
.toString();
296 if(endp
!= null && endp
.length() > 0)
303 else if(_adapterId
.length() > 0)
308 // If the encoded adapter id string contains characters which
309 // the reference parser uses as separators, then we enclose
310 // the adapter id string in quotes.
312 String a
= IceUtilInternal
.StringUtil
.escapeString(_adapterId
, null);
313 if(IceUtilInternal
.StringUtil
.findFirstOf(a
, " :@") != -1)
327 public java
.util
.Map
<String
, String
> toProperty(String prefix
)
329 java
.util
.Map
<String
, String
> properties
= new java
.util
.HashMap
<String
, String
>();
331 properties
.put(prefix
, toString());
332 properties
.put(prefix
+ ".CollocationOptimized", _collocationOptimized ?
"1" : "0");
333 properties
.put(prefix
+ ".ConnectionCached", _cacheConnection ?
"1" : "0");
334 properties
.put(prefix
+ ".PreferSecure", _preferSecure ?
"1" : "0");
335 properties
.put(prefix
+ ".EndpointSelection",
336 _endpointSelection
== Ice
.EndpointSelectionType
.Random ?
"Random" : "Ordered");
338 StringBuffer s
= new StringBuffer();
339 s
.append(_locatorCacheTimeout
);
340 properties
.put(prefix
+ ".LocatorCacheTimeout", s
.toString());
342 if(_routerInfo
!= null)
344 Ice
.ObjectPrxHelperBase h
= (Ice
.ObjectPrxHelperBase
)_routerInfo
.getRouter();
345 java
.util
.Map
<String
, String
> routerProperties
= h
.__reference().toProperty(prefix
+ ".Router");
346 for(java
.util
.Map
.Entry
<String
, String
> p
: routerProperties
.entrySet())
348 properties
.put(p
.getKey(), p
.getValue());
352 if(_locatorInfo
!= null)
354 Ice
.ObjectPrxHelperBase h
= (Ice
.ObjectPrxHelperBase
)_locatorInfo
.getLocator();
355 java
.util
.Map
<String
, String
> locatorProperties
= h
.__reference().toProperty(prefix
+ ".Locator");
356 for(java
.util
.Map
.Entry
<String
, String
> p
: locatorProperties
.entrySet())
358 properties
.put(p
.getKey(), p
.getValue());
365 public synchronized int
368 if(!_hashInitialized
)
370 super.hashCode(); // Initializes _hashValue.
372 // Add hash of adapter ID to base hash.
373 _hashValue
= 5 * _hashValue
+ _adapterId
.hashCode();
379 equals(java
.lang
.Object obj
)
385 if(!(obj
instanceof RoutableReference
))
390 if(!super.equals(obj
))
394 RoutableReference rhs
= (RoutableReference
)obj
; // Guaranteed to succeed.
395 if(_locatorInfo
== null ? rhs
._locatorInfo
!= null : !_locatorInfo
.equals(rhs
._locatorInfo
))
399 if(_routerInfo
== null ? rhs
._routerInfo
!= null : !_routerInfo
.equals(rhs
._routerInfo
))
403 if(_collocationOptimized
!= rhs
._collocationOptimized
)
407 if(_cacheConnection
!= rhs
._cacheConnection
)
411 if(_preferSecure
!= rhs
._preferSecure
)
415 if(_endpointSelection
!= rhs
._endpointSelection
)
419 if(_locatorCacheTimeout
!= rhs
._locatorCacheTimeout
)
423 if(!_connectionId
.equals(rhs
._connectionId
))
427 if(_overrideTimeout
!= rhs
._overrideTimeout
)
431 if(_overrideTimeout
&& _timeout
!= rhs
._timeout
)
435 if(!java
.util
.Arrays
.equals(_endpoints
, rhs
._endpoints
))
439 if(!_adapterId
.equals(rhs
._adapterId
))
446 public Ice
.ConnectionI
447 getConnection(Ice
.BooleanHolder comp
)
449 if(_routerInfo
!= null)
452 // If we route, we send everything to the router's client
455 EndpointI
[] endpts
= _routerInfo
.getClientEndpoints();
456 if(endpts
.length
> 0)
458 applyOverrides(endpts
);
459 return createConnection(endpts
, comp
);
463 if(_endpoints
.length
> 0)
465 return createConnection(_endpoints
, comp
);
470 Ice
.BooleanHolder cached
= new Ice
.BooleanHolder(false);
471 EndpointI
[] endpts
= null;
472 if(_locatorInfo
!= null)
474 endpts
= _locatorInfo
.getEndpoints(this, _locatorCacheTimeout
, cached
);
475 applyOverrides(endpts
);
478 if(endpts
== null || endpts
.length
== 0)
480 throw new Ice
.NoEndpointException(toString());
485 return createConnection(endpts
, comp
);
487 catch(Ice
.NoEndpointException ex
)
489 throw ex
; // No need to retry if there's no endpoints.
491 catch(Ice
.LocalException ex
)
493 assert(_locatorInfo
!= null);
494 _locatorInfo
.clearCache(this);
497 TraceLevels traceLevels
= getInstance().traceLevels();
498 if(traceLevels
.retry
>= 2)
500 String s
= "connection to cached endpoints failed\n" +
501 "removing endpoints from cache and trying one more time\n" + ex
;
502 getInstance().initializationData().logger
.trace(traceLevels
.retryCat
, s
);
504 continue; // Try again if the endpoints were cached.
512 getConnection(final GetConnectionCallback callback
)
514 if(_routerInfo
!= null)
517 // If we route, we send everything to the router's client
520 _routerInfo
.getClientEndpoints(new RouterInfo
.GetClientEndpointsCallback()
523 setEndpoints(EndpointI
[] endpts
)
525 if(endpts
.length
> 0)
527 applyOverrides(endpts
);
528 createConnection(endpts
, callback
);
532 getConnectionNoRouterInfo(callback
);
537 setException(Ice
.LocalException ex
)
539 callback
.setException(ex
);
545 getConnectionNoRouterInfo(callback
);
550 getConnectionNoRouterInfo(final GetConnectionCallback callback
)
552 if(_endpoints
.length
> 0)
554 createConnection(_endpoints
, callback
);
558 final RoutableReference self
= this;
559 if(_locatorInfo
!= null)
561 _locatorInfo
.getEndpoints(this, _locatorCacheTimeout
, new LocatorInfo
.GetEndpointsCallback()
564 setEndpoints(EndpointI
[] endpoints
, final boolean cached
)
566 if(endpoints
.length
== 0)
568 callback
.setException(new Ice
.NoEndpointException(self
.toString()));
572 applyOverrides(endpoints
);
573 createConnection(endpoints
, new GetConnectionCallback()
576 setConnection(Ice
.ConnectionI connection
, boolean compress
)
578 callback
.setConnection(connection
, compress
);
582 setException(Ice
.LocalException exc
)
588 catch(Ice
.NoEndpointException ex
)
590 callback
.setException(ex
); // No need to retry if there's no endpoints.
592 catch(Ice
.LocalException ex
)
594 assert(_locatorInfo
!= null);
595 _locatorInfo
.clearCache(self
);
598 TraceLevels traceLvls
= getInstance().traceLevels();
599 if(traceLvls
.retry
>= 2)
601 String s
= "connection to cached endpoints failed\n" +
602 "removing endpoints from cache and trying one more time\n" + ex
;
603 getInstance().initializationData().logger
.trace(traceLvls
.retryCat
, s
);
605 getConnectionNoRouterInfo(callback
); // Retry.
608 callback
.setException(ex
);
615 setException(Ice
.LocalException ex
)
617 callback
.setException(ex
);
623 callback
.setException(new Ice
.NoEndpointException(toString()));
628 RoutableReference(Instance instance
,
629 Ice
.Communicator communicator
,
630 Ice
.Identity identity
,
634 EndpointI
[] endpoints
,
636 LocatorInfo locatorInfo
,
637 RouterInfo routerInfo
,
638 boolean collocationOptimized
,
639 boolean cacheConnection
,
640 boolean prefereSecure
,
641 Ice
.EndpointSelectionType endpointSelection
,
642 int locatorCacheTimeout
)
644 super(instance
, communicator
, identity
, facet
, mode
, secure
);
645 _endpoints
= endpoints
;
646 _adapterId
= adapterId
;
647 _locatorInfo
= locatorInfo
;
648 _routerInfo
= routerInfo
;
649 _collocationOptimized
= collocationOptimized
;
650 _cacheConnection
= cacheConnection
;
651 _preferSecure
= prefereSecure
;
652 _endpointSelection
= endpointSelection
;
653 _locatorCacheTimeout
= locatorCacheTimeout
;
654 _overrideTimeout
= false;
657 if(_endpoints
== null)
659 _endpoints
= _emptyEndpoints
;
661 if(_adapterId
== null)
665 assert(_adapterId
.length() == 0 || _endpoints
.length
== 0);
669 applyOverrides(EndpointI
[] endpts
)
672 // Apply the endpoint overrides to each endpoint.
674 for(int i
= 0; i
< endpts
.length
; ++i
)
676 endpts
[i
] = endpts
[i
].connectionId(_connectionId
);
677 if(_overrideCompress
)
679 endpts
[i
] = endpts
[i
].compress(_compress
);
683 endpts
[i
] = endpts
[i
].timeout(_timeout
);
689 filterEndpoints(EndpointI
[] allEndpoints
)
691 java
.util
.List
<EndpointI
> endpoints
= new java
.util
.ArrayList
<EndpointI
>();
694 // Filter out opaque endpoints.
696 for(EndpointI endpoint
: allEndpoints
)
698 if(!(endpoint
instanceof IceInternal
.OpaqueEndpointI
))
700 endpoints
.add(endpoint
);
705 // Filter out endpoints according to the mode of the reference.
709 case Reference
.ModeTwoway
:
710 case Reference
.ModeOneway
:
711 case Reference
.ModeBatchOneway
:
714 // Filter out datagram endpoints.
716 java
.util
.Iterator
<EndpointI
> i
= endpoints
.iterator();
719 EndpointI endpoint
= i
.next();
720 if(endpoint
.datagram())
728 case Reference
.ModeDatagram
:
729 case Reference
.ModeBatchDatagram
:
732 // Filter out non-datagram endpoints.
734 java
.util
.Iterator
<EndpointI
> i
= endpoints
.iterator();
737 EndpointI endpoint
= i
.next();
738 if(!endpoint
.datagram())
748 // Sort the endpoints according to the endpoint selection type.
750 switch(getEndpointSelection())
754 java
.util
.Collections
.shuffle(endpoints
);
770 // If a secure connection is requested or secure overrides is
771 // set, remove all non-secure endpoints. Otherwise if preferSecure is set
772 // make secure endpoints prefered. By default make non-secure
773 // endpoints preferred over secure endpoints.
775 DefaultsAndOverrides overrides
= getInstance().defaultsAndOverrides();
776 if(overrides
.overrideSecure ? overrides
.overrideSecureValue
: getSecure())
778 java
.util
.Iterator
<EndpointI
> i
= endpoints
.iterator();
781 EndpointI endpoint
= i
.next();
782 if(!endpoint
.secure())
788 else if(getPreferSecure())
790 java
.util
.Collections
.sort(endpoints
, _preferSecureEndpointComparator
);
794 java
.util
.Collections
.sort(endpoints
, _preferNonSecureEndpointComparator
);
797 return (EndpointI
[])endpoints
.toArray(new EndpointI
[endpoints
.size()]);
800 protected Ice
.ConnectionI
801 createConnection(EndpointI
[] allEndpoints
, Ice
.BooleanHolder compress
)
803 EndpointI
[] endpoints
= filterEndpoints(allEndpoints
);
804 if(endpoints
.length
== 0)
806 throw new Ice
.NoEndpointException(toString());
810 // Finally, create the connection.
812 OutgoingConnectionFactory factory
= getInstance().outgoingConnectionFactory();
813 Ice
.ConnectionI connection
= null;
814 if(getCacheConnection() || endpoints
.length
== 1)
817 // Get an existing connection or create one if there's no
818 // existing connection to one of the given endpoints.
820 connection
= factory
.create(endpoints
, false, getEndpointSelection(), compress
);
825 // Go through the list of endpoints and try to create the
826 // connection until it succeeds. This is different from just
827 // calling create() with the given endpoints since this might
828 // create a new connection even if there's an existing
829 // connection for one of the endpoints.
832 Ice
.LocalException exception
= null;
833 EndpointI
[] endpoint
= new EndpointI
[1];
834 for(int i
= 0; i
< endpoints
.length
; ++i
)
838 endpoint
[0] = endpoints
[i
];
839 final boolean more
= i
!= endpoints
.length
- 1;
840 connection
= factory
.create(endpoint
, more
, getEndpointSelection(), compress
);
843 catch(Ice
.LocalException ex
)
849 if(connection
== null)
851 assert(exception
!= null);
856 assert(connection
!= null);
859 // If we have a router, set the object adapter for this router
860 // (if any) to the new connection, so that callbacks from the
861 // router can be received over this new connection.
863 if(_routerInfo
!= null && _routerInfo
.getAdapter() != null)
865 connection
.setAdapter(_routerInfo
.getAdapter());
872 createConnection(EndpointI
[] allEndpoints
, final GetConnectionCallback callback
)
874 final EndpointI
[] endpoints
= filterEndpoints(allEndpoints
);
875 if(endpoints
.length
== 0)
877 callback
.setException(new Ice
.NoEndpointException(toString()));
882 // Finally, create the connection.
884 final OutgoingConnectionFactory factory
= getInstance().outgoingConnectionFactory();
885 if(getCacheConnection() || endpoints
.length
== 1)
888 // Get an existing connection or create one if there's no
889 // existing connection to one of the given endpoints.
891 factory
.create(endpoints
, false, getEndpointSelection(),
892 new OutgoingConnectionFactory
.CreateConnectionCallback()
895 setConnection(Ice
.ConnectionI connection
, boolean compress
)
898 // If we have a router, set the object adapter for this router
899 // (if any) to the new connection, so that callbacks from the
900 // router can be received over this new connection.
902 if(_routerInfo
!= null && _routerInfo
.getAdapter() != null)
904 connection
.setAdapter(_routerInfo
.getAdapter());
906 callback
.setConnection(connection
, compress
);
910 setException(Ice
.LocalException ex
)
912 callback
.setException(ex
);
919 // Go through the list of endpoints and try to create the
920 // connection until it succeeds. This is different from just
921 // calling create() with the given endpoints since this might
922 // create a new connection even if there's an existing
923 // connection for one of the endpoints.
926 factory
.create(new EndpointI
[]{ endpoints
[0] }, true, getEndpointSelection(),
927 new OutgoingConnectionFactory
.CreateConnectionCallback()
930 setConnection(Ice
.ConnectionI connection
, boolean compress
)
933 // If we have a router, set the object adapter for this router
934 // (if any) to the new connection, so that callbacks from the
935 // router can be received over this new connection.
937 if(_routerInfo
!= null && _routerInfo
.getAdapter() != null)
939 connection
.setAdapter(_routerInfo
.getAdapter());
941 callback
.setConnection(connection
, compress
);
945 setException(final Ice
.LocalException ex
)
947 if(_exception
== null)
952 if(++_i
== endpoints
.length
)
954 callback
.setException(_exception
);
958 final boolean more
= _i
!= endpoints
.length
- 1;
959 final EndpointI
[] endpoint
= new EndpointI
[]{ endpoints
[_i
] };
960 factory
.create(endpoint
, more
, getEndpointSelection(), this);
964 private Ice
.LocalException _exception
= null;
969 static class EndpointComparator
implements java
.util
.Comparator
<EndpointI
>
971 EndpointComparator(boolean preferSecure
)
973 _preferSecure
= preferSecure
;
977 compare(EndpointI le
, EndpointI re
)
979 boolean ls
= le
.secure();
980 boolean rs
= re
.secure();
981 if((ls
&& rs
) || (!ls
&& !rs
))
1009 private boolean _preferSecure
;
1012 private static EndpointComparator _preferNonSecureEndpointComparator
= new EndpointComparator(false);
1013 private static EndpointComparator _preferSecureEndpointComparator
= new EndpointComparator(true);
1014 private static EndpointI
[] _emptyEndpoints
= new EndpointI
[0];
1016 private EndpointI
[] _endpoints
;
1017 private String _adapterId
;
1018 private LocatorInfo _locatorInfo
; // Null if no router is used.
1019 private RouterInfo _routerInfo
; // Null if no router is used.
1020 private boolean _collocationOptimized
;
1021 private boolean _cacheConnection
;
1022 private boolean _preferSecure
;
1023 private Ice
.EndpointSelectionType _endpointSelection
;
1024 private int _locatorCacheTimeout
;
1026 private boolean _overrideTimeout
;
1027 private int _timeout
; // Only used if _overrideTimeout == true
1028 private String _connectionId
= "";