1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 package IceInternal;
6 
7 public class RoutableReference extends Reference
8 {
9     @Override
10     public final EndpointI[]
getEndpoints()11     getEndpoints()
12     {
13         return _endpoints;
14     }
15 
16     @Override
17     public final String
getAdapterId()18     getAdapterId()
19     {
20         return _adapterId;
21     }
22 
23     @Override
24     public final LocatorInfo
getLocatorInfo()25     getLocatorInfo()
26     {
27         return _locatorInfo;
28     }
29 
30     @Override
31     public final RouterInfo
getRouterInfo()32     getRouterInfo()
33     {
34         return _routerInfo;
35     }
36 
37     @Override
38     public final boolean
getCollocationOptimized()39     getCollocationOptimized()
40     {
41         return _collocationOptimized;
42     }
43 
44     @Override
45     public final boolean
getCacheConnection()46     getCacheConnection()
47     {
48         return _cacheConnection;
49     }
50 
51     @Override
52     public final boolean
getPreferSecure()53     getPreferSecure()
54     {
55         return _preferSecure;
56     }
57 
58     @Override
59     public final Ice.EndpointSelectionType
getEndpointSelection()60     getEndpointSelection()
61     {
62         return _endpointSelection;
63     }
64 
65     @Override
66     public final int
getLocatorCacheTimeout()67     getLocatorCacheTimeout()
68     {
69         return _locatorCacheTimeout;
70     }
71 
72     @Override
73     public final String
getConnectionId()74     getConnectionId()
75     {
76         return _connectionId;
77     }
78 
79     @Override
80     public Ice.IntOptional
getTimeout()81     getTimeout()
82     {
83         return _overrideTimeout ? Ice.Optional.O(_timeout) : new Ice.IntOptional();
84     }
85 
86     @Override
87     public Reference
changeEncoding(Ice.EncodingVersion newEncoding)88     changeEncoding(Ice.EncodingVersion newEncoding)
89     {
90         RoutableReference r = (RoutableReference)super.changeEncoding(newEncoding);
91         if(r != this)
92         {
93             LocatorInfo locInfo = r._locatorInfo;
94             if(locInfo != null && !locInfo.getLocator().ice_getEncodingVersion().equals(newEncoding))
95             {
96                 r._locatorInfo = getInstance().locatorManager().get(
97                     (Ice.LocatorPrx)locInfo.getLocator().ice_encodingVersion(newEncoding));
98             }
99         }
100         return r;
101     }
102 
103     @Override
104     public Reference
changeCompress(boolean newCompress)105     changeCompress(boolean newCompress)
106     {
107         RoutableReference r = (RoutableReference)super.changeCompress(newCompress);
108         if(r != this && _endpoints.length > 0) // Also override the compress flag on the endpoints if it was updated.
109         {
110             EndpointI[] newEndpoints = new EndpointI[_endpoints.length];
111             for(int i = 0; i < _endpoints.length; i++)
112             {
113                 newEndpoints[i] = _endpoints[i].compress(newCompress);
114             }
115             r._endpoints = newEndpoints;
116         }
117         return r;
118     }
119 
120     @Override
121     public Reference
changeEndpoints(EndpointI[] newEndpoints)122     changeEndpoints(EndpointI[] newEndpoints)
123     {
124         if(java.util.Arrays.equals(newEndpoints, _endpoints))
125         {
126             return this;
127         }
128         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
129         r._endpoints = newEndpoints;
130         r._adapterId = "";
131         r.applyOverrides(r._endpoints);
132         return r;
133     }
134 
135     @Override
136     public Reference
changeAdapterId(String newAdapterId)137     changeAdapterId(String newAdapterId)
138     {
139         if(_adapterId.equals(newAdapterId))
140         {
141             return this;
142         }
143         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
144         r._adapterId = newAdapterId;
145         r._endpoints = _emptyEndpoints;
146         return r;
147     }
148 
149     @Override
150     public Reference
changeLocator(Ice.LocatorPrx newLocator)151     changeLocator(Ice.LocatorPrx newLocator)
152     {
153         LocatorInfo newLocatorInfo = getInstance().locatorManager().get(newLocator);
154         if(newLocatorInfo != null && _locatorInfo != null && newLocatorInfo.equals(_locatorInfo))
155         {
156             return this;
157         }
158         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
159         r._locatorInfo = newLocatorInfo;
160         return r;
161     }
162 
163     @Override
164     public Reference
changeRouter(Ice.RouterPrx newRouter)165     changeRouter(Ice.RouterPrx newRouter)
166     {
167         RouterInfo newRouterInfo = getInstance().routerManager().get(newRouter);
168         if(newRouterInfo != null && _routerInfo != null && newRouterInfo.equals(_routerInfo))
169         {
170             return this;
171         }
172         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
173         r._routerInfo = newRouterInfo;
174         return r;
175     }
176 
177     @Override
178     public Reference
changeCollocationOptimized(boolean newCollocationOptimized)179     changeCollocationOptimized(boolean newCollocationOptimized)
180     {
181         if(newCollocationOptimized == _collocationOptimized)
182         {
183             return this;
184         }
185         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
186         r._collocationOptimized = newCollocationOptimized;
187         return r;
188     }
189 
190     @Override
191     public final Reference
changeCacheConnection(boolean newCache)192     changeCacheConnection(boolean newCache)
193     {
194         if(newCache == _cacheConnection)
195         {
196             return this;
197         }
198         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
199         r._cacheConnection = newCache;
200         return r;
201     }
202 
203     @Override
204     public Reference
changePreferSecure(boolean newPreferSecure)205     changePreferSecure(boolean newPreferSecure)
206     {
207         if(newPreferSecure == _preferSecure)
208         {
209             return this;
210         }
211         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
212         r._preferSecure = newPreferSecure;
213         return r;
214     }
215 
216     @Override
217     public final Reference
changeEndpointSelection(Ice.EndpointSelectionType newType)218     changeEndpointSelection(Ice.EndpointSelectionType newType)
219     {
220         if(newType == _endpointSelection)
221         {
222             return this;
223         }
224         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
225         r._endpointSelection = newType;
226         return r;
227     }
228 
229     @Override
230     public Reference
changeLocatorCacheTimeout(int newTimeout)231     changeLocatorCacheTimeout(int newTimeout)
232     {
233         if(_locatorCacheTimeout == newTimeout)
234         {
235             return this;
236         }
237         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
238         r._locatorCacheTimeout = newTimeout;
239         return r;
240     }
241 
242     @Override
243     public Reference
changeTimeout(int newTimeout)244     changeTimeout(int newTimeout)
245     {
246         if(_overrideTimeout && _timeout == newTimeout)
247         {
248             return this;
249         }
250         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
251         r._timeout = newTimeout;
252         r._overrideTimeout = true;
253         if(_endpoints.length > 0)
254         {
255             EndpointI[] newEndpoints = new EndpointI[_endpoints.length];
256             for(int i = 0; i < _endpoints.length; i++)
257             {
258                 newEndpoints[i] = _endpoints[i].timeout(newTimeout);
259             }
260             r._endpoints = newEndpoints;
261         }
262         return r;
263     }
264 
265     @Override
266     public Reference
changeConnectionId(String id)267     changeConnectionId(String id)
268     {
269         if(_connectionId.equals(id))
270         {
271             return this;
272         }
273         RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
274         r._connectionId = id;
275         if(_endpoints.length > 0)
276         {
277             EndpointI[] newEndpoints = new EndpointI[_endpoints.length];
278             for(int i = 0; i < _endpoints.length; i++)
279             {
280                 newEndpoints[i] = _endpoints[i].connectionId(id);
281             }
282             r._endpoints = newEndpoints;
283         }
284         return r;
285     }
286 
287     @Override
288     public Reference
changeConnection(Ice.ConnectionI connection)289     changeConnection(Ice.ConnectionI connection)
290     {
291         return new FixedReference(getInstance(),
292                                   getCommunicator(),
293                                   getIdentity(),
294                                   getFacet(),
295                                   getMode(),
296                                   getSecure(),
297                                   getProtocol(),
298                                   getEncoding(),
299                                   connection,
300                                   getInvocationTimeout(),
301                                   getContext(),
302                                   getCompress());
303     }
304 
305     @Override
306     public boolean
isIndirect()307     isIndirect()
308     {
309         return _endpoints.length == 0;
310     }
311 
312     @Override
313     public boolean
isWellKnown()314     isWellKnown()
315     {
316         return _endpoints.length == 0 && _adapterId.length() == 0;
317     }
318 
319     @Override
320     public void
streamWrite(Ice.OutputStream s)321     streamWrite(Ice.OutputStream s)
322         throws Ice.MarshalException
323     {
324         super.streamWrite(s);
325 
326         s.writeSize(_endpoints.length);
327         if(_endpoints.length > 0)
328         {
329             assert(_adapterId.length() == 0);
330             for(EndpointI endpoint : _endpoints)
331             {
332                 s.writeShort(endpoint.type());
333                 endpoint.streamWrite(s);
334             }
335         }
336         else
337         {
338             s.writeString(_adapterId); // Adapter id.
339         }
340     }
341 
342     @Override
343     public String
toString()344     toString()
345     {
346         //
347         // WARNING: Certain features, such as proxy validation in Glacier2,
348         // depend on the format of proxy strings. Changes to toString() and
349         // methods called to generate parts of the reference string could break
350         // these features. Please review for all features that depend on the
351         // format of proxyToString() before changing this and related code.
352         //
353         StringBuilder s = new StringBuilder(128);
354         s.append(super.toString());
355         if(_endpoints.length > 0)
356         {
357             for(EndpointI endpoint : _endpoints)
358             {
359                 String endp = endpoint.toString();
360                 if(endp != null && endp.length() > 0)
361                 {
362                     s.append(':');
363                     s.append(endp);
364                 }
365             }
366         }
367         else if(_adapterId.length() > 0)
368         {
369             s.append(" @ ");
370 
371             //
372             // If the encoded adapter id string contains characters which
373             // the reference parser uses as separators, then we enclose
374             // the adapter id string in quotes.
375             //
376             String a = IceUtilInternal.StringUtil.escapeString(_adapterId, null, getInstance().toStringMode());
377             if(IceUtilInternal.StringUtil.findFirstOf(a, " :@") != -1)
378             {
379                 s.append('"');
380                 s.append(a);
381                 s.append('"');
382             }
383             else
384             {
385                 s.append(a);
386             }
387         }
388         return s.toString();
389     }
390 
391     @Override
toProperty(String prefix)392     public java.util.Map<String, String> toProperty(String prefix)
393     {
394         java.util.Map<String, String> properties = new java.util.HashMap<String, String>();
395 
396         properties.put(prefix, toString());
397         properties.put(prefix + ".CollocationOptimized", _collocationOptimized ? "1" : "0");
398         properties.put(prefix + ".ConnectionCached", _cacheConnection ? "1" : "0");
399         properties.put(prefix + ".PreferSecure", _preferSecure ? "1" : "0");
400         properties.put(prefix + ".EndpointSelection",
401                        _endpointSelection == Ice.EndpointSelectionType.Random ? "Random" : "Ordered");
402 
403         {
404             StringBuffer s = new StringBuffer();
405             s.append(getInvocationTimeout());
406             properties.put(prefix + ".InvocationTimeout", s.toString());
407         }
408         {
409             StringBuffer s = new StringBuffer();
410             s.append(_locatorCacheTimeout);
411             properties.put(prefix + ".LocatorCacheTimeout", s.toString());
412         }
413 
414         if(_routerInfo != null)
415         {
416             Ice.ObjectPrxHelperBase h = (Ice.ObjectPrxHelperBase)_routerInfo.getRouter();
417             java.util.Map<String, String> routerProperties = h._getReference().toProperty(prefix + ".Router");
418             for(java.util.Map.Entry<String, String> p : routerProperties.entrySet())
419             {
420                 properties.put(p.getKey(), p.getValue());
421             }
422         }
423 
424         if(_locatorInfo != null)
425         {
426             Ice.ObjectPrxHelperBase h = (Ice.ObjectPrxHelperBase)_locatorInfo.getLocator();
427             java.util.Map<String, String> locatorProperties = h._getReference().toProperty(prefix + ".Locator");
428             for(java.util.Map.Entry<String, String> p : locatorProperties.entrySet())
429             {
430                 properties.put(p.getKey(), p.getValue());
431             }
432         }
433 
434         return properties;
435     }
436 
437     @Override
438     public synchronized int
hashCode()439     hashCode()
440     {
441         if(!_hashInitialized)
442         {
443             super.hashCode(); // Initializes _hashValue.
444             _hashValue = IceInternal.HashUtil.hashAdd(_hashValue, _adapterId);
445         }
446         return _hashValue;
447     }
448 
449     @Override
450     public boolean
equals(java.lang.Object obj)451     equals(java.lang.Object obj)
452     {
453         if(this == obj)
454         {
455             return true;
456         }
457         if(!(obj instanceof RoutableReference))
458         {
459             return false;
460         }
461 
462         if(!super.equals(obj))
463         {
464             return false;
465         }
466         RoutableReference rhs = (RoutableReference)obj; // Guaranteed to succeed.
467         if(_locatorInfo == null ? rhs._locatorInfo != null : !_locatorInfo.equals(rhs._locatorInfo))
468         {
469             return false;
470         }
471         if(_routerInfo == null ? rhs._routerInfo != null : !_routerInfo.equals(rhs._routerInfo))
472         {
473             return false;
474         }
475         if(_collocationOptimized != rhs._collocationOptimized)
476         {
477             return false;
478         }
479         if(_cacheConnection != rhs._cacheConnection)
480         {
481             return false;
482         }
483         if(_preferSecure != rhs._preferSecure)
484         {
485             return false;
486         }
487         if(_endpointSelection != rhs._endpointSelection)
488         {
489             return false;
490         }
491         if(_locatorCacheTimeout != rhs._locatorCacheTimeout)
492         {
493             return false;
494         }
495         if(!_connectionId.equals(rhs._connectionId))
496         {
497            return false;
498         }
499         if(_overrideTimeout != rhs._overrideTimeout)
500         {
501            return false;
502         }
503         if(_overrideTimeout && _timeout != rhs._timeout)
504         {
505             return false;
506         }
507         if(!java.util.Arrays.equals(_endpoints, rhs._endpoints))
508         {
509             return false;
510         }
511         if(!_adapterId.equals(rhs._adapterId))
512         {
513            return false;
514         }
515         return true;
516     }
517 
518     @Override
519     public RequestHandler
getRequestHandler(Ice.ObjectPrxHelperBase proxy)520     getRequestHandler(Ice.ObjectPrxHelperBase proxy)
521     {
522         return getInstance().requestHandlerFactory().getRequestHandler(this, proxy);
523     }
524 
525     @Override
526     public BatchRequestQueue
getBatchRequestQueue()527     getBatchRequestQueue()
528     {
529         return new BatchRequestQueue(getInstance(), getMode() == Reference.ModeBatchDatagram);
530     }
531 
532     public void
getConnection(final GetConnectionCallback callback)533     getConnection(final GetConnectionCallback callback)
534     {
535         if(_routerInfo != null)
536         {
537             //
538             // If we route, we send everything to the router's client
539             // proxy endpoints.
540             //
541             _routerInfo.getClientEndpoints(new RouterInfo.GetClientEndpointsCallback()
542                 {
543                     @Override
544                     public void
545                     setEndpoints(EndpointI[] endpts)
546                     {
547                         if(endpts.length > 0)
548                         {
549                             applyOverrides(endpts);
550                             createConnection(endpts, callback);
551                         }
552                         else
553                         {
554                             getConnectionNoRouterInfo(callback);
555                         }
556                     }
557 
558                     @Override
559                     public void
560                     setException(Ice.LocalException ex)
561                     {
562                         callback.setException(ex);
563                     }
564                 });
565         }
566         else
567         {
568             getConnectionNoRouterInfo(callback);
569         }
570     }
571 
572     public void
getConnectionNoRouterInfo(final GetConnectionCallback callback)573     getConnectionNoRouterInfo(final GetConnectionCallback callback)
574     {
575         if(_endpoints.length > 0)
576         {
577             createConnection(_endpoints, callback);
578             return;
579         }
580 
581         final RoutableReference self = this;
582         if(_locatorInfo != null)
583         {
584             _locatorInfo.getEndpoints(this, _locatorCacheTimeout, new LocatorInfo.GetEndpointsCallback()
585             {
586                 @Override
587                 public void
588                 setEndpoints(EndpointI[] endpoints, final boolean cached)
589                 {
590                     if(endpoints.length == 0)
591                     {
592                         callback.setException(new Ice.NoEndpointException(self.toString()));
593                         return;
594                     }
595 
596                     applyOverrides(endpoints);
597                     createConnection(endpoints, new GetConnectionCallback()
598                     {
599                         @Override
600                         public void
601                         setConnection(Ice.ConnectionI connection, boolean compress)
602                         {
603                             callback.setConnection(connection, compress);
604                         }
605 
606                         @Override
607                         public void
608                         setException(Ice.LocalException exc)
609                         {
610                             try
611                             {
612                                 throw exc;
613                             }
614                             catch(Ice.NoEndpointException ex)
615                             {
616                                 callback.setException(ex); // No need to retry if there's no endpoints.
617                             }
618                             catch(Ice.LocalException ex)
619                             {
620                                 assert(_locatorInfo != null);
621                                 _locatorInfo.clearCache(self);
622                                 if(cached)
623                                 {
624                                     TraceLevels traceLvls = getInstance().traceLevels();
625                                     if(traceLvls.retry >= 2)
626                                     {
627                                         String s = "connection to cached endpoints failed\n" +
628                                             "removing endpoints from cache and trying again\n" + ex;
629                                         getInstance().initializationData().logger.trace(traceLvls.retryCat, s);
630                                     }
631                                     getConnectionNoRouterInfo(callback); // Retry.
632                                     return;
633                                 }
634                                 callback.setException(ex);
635                             }
636                         }
637                         });
638                 }
639 
640                 @Override
641                 public void
642                 setException(Ice.LocalException ex)
643                 {
644                     callback.setException(ex);
645                 }
646             });
647         }
648         else
649         {
650             callback.setException(new Ice.NoEndpointException(toString()));
651         }
652     }
653 
654     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)655     RoutableReference(Instance instance,
656                       Ice.Communicator communicator,
657                       Ice.Identity identity,
658                       String facet,
659                       int mode,
660                       boolean secure,
661                       Ice.ProtocolVersion protocol,
662                       Ice.EncodingVersion encoding,
663                       EndpointI[] endpoints,
664                       String adapterId,
665                       LocatorInfo locatorInfo,
666                       RouterInfo routerInfo,
667                       boolean collocationOptimized,
668                       boolean cacheConnection,
669                       boolean prefereSecure,
670                       Ice.EndpointSelectionType endpointSelection,
671                       int locatorCacheTimeout,
672                       int invocationTimeout,
673                       java.util.Map<String, String> context)
674     {
675         super(instance, communicator, identity, facet, mode, secure, protocol, encoding, invocationTimeout, context);
676         _endpoints = endpoints;
677         _adapterId = adapterId;
678         _locatorInfo = locatorInfo;
679         _routerInfo = routerInfo;
680         _collocationOptimized = collocationOptimized;
681         _cacheConnection = cacheConnection;
682         _preferSecure = prefereSecure;
683         _endpointSelection = endpointSelection;
684         _locatorCacheTimeout = locatorCacheTimeout;
685         _overrideTimeout = false;
686         _timeout = -1;
687 
688         if(_endpoints == null)
689         {
690             _endpoints = _emptyEndpoints;
691         }
692         if(_adapterId == null)
693         {
694             _adapterId = "";
695         }
696         assert(_adapterId.length() == 0 || _endpoints.length == 0);
697     }
698 
699     protected void
applyOverrides(EndpointI[] endpts)700     applyOverrides(EndpointI[] endpts)
701     {
702         //
703         // Apply the endpoint overrides to each endpoint.
704         //
705         for(int i = 0; i < endpts.length; ++i)
706         {
707             endpts[i] = endpts[i].connectionId(_connectionId);
708             if(_overrideCompress)
709             {
710                 endpts[i] = endpts[i].compress(_compress);
711             }
712             if(_overrideTimeout)
713             {
714                 endpts[i] = endpts[i].timeout(_timeout);
715             }
716         }
717     }
718 
719     private EndpointI[]
filterEndpoints(EndpointI[] allEndpoints)720     filterEndpoints(EndpointI[] allEndpoints)
721     {
722         java.util.List<EndpointI> endpoints = new java.util.ArrayList<EndpointI>();
723 
724         //
725         // Filter out opaque endpoints.
726         //
727         for(EndpointI endpoint : allEndpoints)
728         {
729             if(!(endpoint instanceof IceInternal.OpaqueEndpointI))
730             {
731                 endpoints.add(endpoint);
732             }
733         }
734 
735         //
736         // Filter out endpoints according to the mode of the reference.
737         //
738         switch(getMode())
739         {
740             case Reference.ModeTwoway:
741             case Reference.ModeOneway:
742             case Reference.ModeBatchOneway:
743             {
744                 //
745                 // Filter out datagram endpoints.
746                 //
747                 java.util.Iterator<EndpointI> i = endpoints.iterator();
748                 while(i.hasNext())
749                 {
750                     EndpointI endpoint = i.next();
751                     if(endpoint.datagram())
752                     {
753                         i.remove();
754                     }
755                 }
756                 break;
757             }
758 
759             case Reference.ModeDatagram:
760             case Reference.ModeBatchDatagram:
761             {
762                 //
763                 // Filter out non-datagram endpoints.
764                 //
765                 java.util.Iterator<EndpointI> i = endpoints.iterator();
766                 while(i.hasNext())
767                 {
768                     EndpointI endpoint = i.next();
769                     if(!endpoint.datagram())
770                     {
771                         i.remove();
772                     }
773                 }
774                 break;
775             }
776         }
777 
778         //
779         // Sort the endpoints according to the endpoint selection type.
780         //
781         switch(getEndpointSelection())
782         {
783             case Random:
784             {
785                 java.util.Collections.shuffle(endpoints);
786                 break;
787             }
788             case Ordered:
789             {
790                 // Nothing to do.
791                 break;
792             }
793             default:
794             {
795                 assert(false);
796                 break;
797             }
798         }
799 
800         //
801         // If a secure connection is requested or secure overrides is
802         // set, remove all non-secure endpoints. Otherwise if preferSecure is set
803         // make secure endpoints prefered. By default make non-secure
804         // endpoints preferred over secure endpoints.
805         //
806         DefaultsAndOverrides overrides = getInstance().defaultsAndOverrides();
807         if(overrides.overrideSecure ? overrides.overrideSecureValue : getSecure())
808         {
809             java.util.Iterator<EndpointI> i = endpoints.iterator();
810             while(i.hasNext())
811             {
812                 EndpointI endpoint = i.next();
813                 if(!endpoint.secure())
814                 {
815                     i.remove();
816                 }
817             }
818         }
819         else if(getPreferSecure())
820         {
821             java.util.Collections.sort(endpoints, _preferSecureEndpointComparator);
822         }
823         else
824         {
825             java.util.Collections.sort(endpoints, _preferNonSecureEndpointComparator);
826         }
827 
828         return endpoints.toArray(new EndpointI[endpoints.size()]);
829     }
830 
831     protected void
createConnection(EndpointI[] allEndpoints, final GetConnectionCallback callback)832     createConnection(EndpointI[] allEndpoints, final GetConnectionCallback callback)
833     {
834         final EndpointI[] endpoints = filterEndpoints(allEndpoints);
835         if(endpoints.length == 0)
836         {
837             callback.setException(new Ice.NoEndpointException(toString()));
838             return;
839         }
840 
841         //
842         // Finally, create the connection.
843         //
844         final OutgoingConnectionFactory factory = getInstance().outgoingConnectionFactory();
845         if(getCacheConnection() || endpoints.length == 1)
846         {
847             //
848             // Get an existing connection or create one if there's no
849             // existing connection to one of the given endpoints.
850             //
851             factory.create(endpoints, false, getEndpointSelection(),
852                            new OutgoingConnectionFactory.CreateConnectionCallback()
853                            {
854                                @Override
855                             public void
856                                setConnection(Ice.ConnectionI connection, boolean compress)
857                                {
858                                    //
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.
862                                    //
863                                    if(_routerInfo != null && _routerInfo.getAdapter() != null)
864                                    {
865                                        connection.setAdapter(_routerInfo.getAdapter());
866                                    }
867                                    callback.setConnection(connection, compress);
868                                }
869 
870                                @Override
871                             public void
872                                setException(Ice.LocalException ex)
873                                {
874                                    callback.setException(ex);
875                                }
876                            });
877         }
878         else
879         {
880             //
881             // Go through the list of endpoints and try to create the
882             // connection until it succeeds. This is different from just
883             // calling create() with the given endpoints since this might
884             // create a new connection even if there's an existing
885             // connection for one of the endpoints.
886             //
887 
888             factory.create(new EndpointI[]{ endpoints[0] }, true, getEndpointSelection(),
889                            new OutgoingConnectionFactory.CreateConnectionCallback()
890                            {
891                                @Override
892                                public void
893                                setConnection(Ice.ConnectionI connection, boolean compress)
894                                {
895                                    //
896                                    // If we have a router, set the object adapter for this router
897                                    // (if any) to the new connection, so that callbacks from the
898                                    // router can be received over this new connection.
899                                    //
900                                    if(_routerInfo != null && _routerInfo.getAdapter() != null)
901                                    {
902                                        connection.setAdapter(_routerInfo.getAdapter());
903                                    }
904                                    callback.setConnection(connection, compress);
905                                }
906 
907                                @Override
908                                public void
909                                setException(final Ice.LocalException ex)
910                                {
911                                    if(_exception == null)
912                                    {
913                                        _exception = ex;
914                                    }
915 
916                                    if(++_i == endpoints.length)
917                                    {
918                                        callback.setException(_exception);
919                                        return;
920                                    }
921 
922                                    final boolean more = _i != endpoints.length - 1;
923                                    final EndpointI[] endpoint = new EndpointI[]{ endpoints[_i] };
924                                    factory.create(endpoint, more, getEndpointSelection(), this);
925                                }
926 
927                                private int _i = 0;
928                                private Ice.LocalException _exception = null;
929                            });
930         }
931     }
932 
933     static class EndpointComparator implements java.util.Comparator<EndpointI>
934     {
EndpointComparator(boolean preferSecure)935         EndpointComparator(boolean preferSecure)
936         {
937             _preferSecure = preferSecure;
938         }
939 
940         @Override
941         public int
compare(EndpointI le, EndpointI re)942         compare(EndpointI le, EndpointI re)
943         {
944             boolean ls = le.secure();
945             boolean rs = re.secure();
946             if((ls && rs) || (!ls && !rs))
947             {
948                 return 0;
949             }
950             else if(!ls && rs)
951             {
952                 if(_preferSecure)
953                 {
954                     return 1;
955                 }
956                 else
957                 {
958                     return -1;
959                 }
960             }
961             else
962             {
963                 if(_preferSecure)
964                 {
965                     return -1;
966                 }
967                 else
968                 {
969                     return 1;
970                 }
971             }
972         }
973 
974         private boolean _preferSecure;
975     }
976 
977     private static EndpointComparator _preferNonSecureEndpointComparator = new EndpointComparator(false);
978     private static EndpointComparator _preferSecureEndpointComparator = new EndpointComparator(true);
979     private static EndpointI[] _emptyEndpoints = new EndpointI[0];
980 
981     private EndpointI[] _endpoints;
982     private String _adapterId;
983     private LocatorInfo _locatorInfo; // Null if no router is used.
984     private RouterInfo _routerInfo; // Null if no router is used.
985     private boolean _collocationOptimized;
986     private boolean _cacheConnection;
987     private boolean _preferSecure;
988     private Ice.EndpointSelectionType _endpointSelection;
989     private int _locatorCacheTimeout;
990 
991     private boolean _overrideTimeout;
992     private int _timeout; // Only used if _overrideTimeout == true
993     private String _connectionId = "";
994 }
995