1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <Ice/Communicator.h>
6 #include <Ice/ReferenceFactory.h>
7 #include <Ice/ProxyFactory.h>
8 #include <Ice/LocalException.h>
9 #include <Ice/Instance.h>
10 #include <Ice/EndpointI.h>
11 #include <Ice/ConnectionI.h>
12 #include <Ice/EndpointFactoryManager.h>
13 #include <Ice/RouterInfo.h>
14 #include <Ice/Router.h>
15 #include <Ice/LocatorInfo.h>
16 #include <Ice/Locator.h>
17 #include <Ice/LoggerUtil.h>
18 #include <Ice/InputStream.h>
19 #include <Ice/Properties.h>
20 #include <Ice/DefaultsAndOverrides.h>
21 #include <Ice/PropertyNames.h>
22 #include <Ice/StringUtil.h>
23 
24 using namespace std;
25 using namespace Ice;
26 using namespace IceInternal;
27 
upCast(::IceInternal::ReferenceFactory * p)28 IceUtil::Shared* IceInternal::upCast(::IceInternal::ReferenceFactory* p) { return p; }
29 
30 ReferencePtr
copy(const Reference * r) const31 IceInternal::ReferenceFactory::copy(const Reference* r) const
32 {
33     const Ice::Identity& ident = r->getIdentity();
34     if(ident.name.empty() && ident.category.empty())
35     {
36         return 0;
37     }
38 
39     return r->clone();
40 }
41 
42 ReferencePtr
create(const Identity & ident,const string & facet,const ReferencePtr & tmpl,const vector<EndpointIPtr> & endpoints)43 IceInternal::ReferenceFactory::create(const Identity& ident,
44                                       const string& facet,
45                                       const ReferencePtr& tmpl,
46                                       const vector<EndpointIPtr>& endpoints)
47 {
48     if(ident.name.empty() && ident.category.empty())
49     {
50         return 0;
51     }
52 
53     return create(ident, facet, tmpl->getMode(), tmpl->getSecure(), tmpl->getProtocol(), tmpl->getEncoding(),
54                   endpoints, "", "");
55 }
56 
57 ReferencePtr
create(const Identity & ident,const string & facet,const ReferencePtr & tmpl,const string & adapterId)58 IceInternal::ReferenceFactory::create(const Identity& ident,
59                                       const string& facet,
60                                       const ReferencePtr& tmpl,
61                                       const string& adapterId)
62 {
63     if(ident.name.empty() && ident.category.empty())
64     {
65         return 0;
66     }
67 
68     return create(ident, facet, tmpl->getMode(), tmpl->getSecure(), tmpl->getProtocol(), tmpl->getEncoding(),
69                   vector<EndpointIPtr>(), adapterId, "");
70 }
71 
72 ReferencePtr
create(const Identity & ident,const Ice::ConnectionIPtr & connection)73 IceInternal::ReferenceFactory::create(const Identity& ident, const Ice::ConnectionIPtr& connection)
74 {
75     if(ident.name.empty() && ident.category.empty())
76     {
77         return 0;
78     }
79 
80     //
81     // Create new reference
82     //
83     return new FixedReference(_instance,
84                               _communicator,
85                               ident,
86                               "",  // Facet
87                               connection->endpoint()->datagram() ? Reference::ModeDatagram : Reference::ModeTwoway,
88                               connection->endpoint()->secure(),
89                               Ice::Protocol_1_0,
90                               _instance->defaultsAndOverrides()->defaultEncoding,
91                               connection,
92                               -1,
93                               Ice::Context(),
94                               IceUtil::Optional<bool>());
95 }
96 
97 ReferencePtr
create(const string & str,const string & propertyPrefix)98 IceInternal::ReferenceFactory::create(const string& str, const string& propertyPrefix)
99 {
100     if(str.empty())
101     {
102         return 0;
103     }
104 
105     const string delim = " \t\r\n";
106 
107     string s(str);
108     string::size_type beg;
109     string::size_type end = 0;
110 
111     beg = s.find_first_not_of(delim, end);
112     if(beg == string::npos)
113     {
114         throw ProxyParseException(__FILE__, __LINE__, "no non-whitespace characters found in `" + s + "'");
115     }
116 
117     //
118     // Extract the identity, which may be enclosed in single
119     // or double quotation marks.
120     //
121     string idstr;
122     end = IceUtilInternal::checkQuote(s, beg);
123     if(end == string::npos)
124     {
125         throw ProxyParseException(__FILE__, __LINE__, "mismatched quotes around identity in `" + s + "'");
126     }
127     else if(end == 0)
128     {
129         end = s.find_first_of(delim + ":@", beg);
130         if(end == string::npos)
131         {
132             end = s.size();
133         }
134         idstr = s.substr(beg, end - beg);
135     }
136     else
137     {
138         beg++; // Skip leading quote
139         idstr = s.substr(beg, end - beg);
140         end++; // Skip trailing quote
141     }
142 
143     if(beg == end)
144     {
145         throw ProxyParseException(__FILE__, __LINE__, "no identity in `" + s + "'");
146     }
147 
148     //
149     // Parsing the identity may raise IdentityParseException.
150     //
151     Identity ident = Ice::stringToIdentity(idstr);
152 
153     if(ident.name.empty())
154     {
155         //
156         // An identity with an empty name and a non-empty
157         // category is illegal.
158         //
159         if(!ident.category.empty())
160         {
161             throw IllegalIdentityException(__FILE__, __LINE__, ident);
162         }
163         //
164         // Treat a stringified proxy containing two double
165         // quotes ("") the same as an empty string, i.e.,
166         // a null proxy, but only if nothing follows the
167         // quotes.
168         //
169         else if(s.find_first_not_of(delim, end) != string::npos)
170         {
171             throw ProxyParseException(__FILE__, __LINE__, "invalid characters after identity in `" + s + "'");
172         }
173         else
174         {
175             return 0;
176         }
177     }
178 
179     string facet;
180     Reference::Mode mode = Reference::ModeTwoway;
181     bool secure = false;
182     Ice::EncodingVersion encoding = _instance->defaultsAndOverrides()->defaultEncoding;
183     Ice::ProtocolVersion protocol = Protocol_1_0;
184     string adapter;
185 
186     while(true)
187     {
188         beg = s.find_first_not_of(delim, end);
189         if(beg == string::npos)
190         {
191             break;
192         }
193 
194         if(s[beg] == ':' || s[beg] == '@')
195         {
196             break;
197         }
198 
199         end = s.find_first_of(delim + ":@", beg);
200         if(end == string::npos)
201         {
202             end = s.length();
203         }
204 
205         if(beg == end)
206         {
207             break;
208         }
209 
210         string option = s.substr(beg, end - beg);
211         if(option.length() != 2 || option[0] != '-')
212         {
213             throw ProxyParseException(__FILE__, __LINE__, "expected a proxy option but found `" + option + "' in `" +
214                                       s + "'");
215         }
216 
217         //
218         // Check for the presence of an option argument. The
219         // argument may be enclosed in single or double
220         // quotation marks.
221         //
222         string argument;
223         string::size_type argumentBeg = s.find_first_not_of(delim, end);
224         if(argumentBeg != string::npos)
225         {
226             if(s[argumentBeg] != '@' && s[argumentBeg] != ':' && s[argumentBeg] != '-')
227             {
228                 beg = argumentBeg;
229                 end = IceUtilInternal::checkQuote(s, beg);
230                 if(end == string::npos)
231                 {
232                     throw ProxyParseException(__FILE__, __LINE__, "mismatched quotes around value for " + option +
233                                               " option in `" + s + "'");
234                 }
235                 else if(end == 0)
236                 {
237                     end = s.find_first_of(delim + ":@", beg);
238                     if(end == string::npos)
239                     {
240                         end = s.size();
241                     }
242                     argument = s.substr(beg, end - beg);
243                 }
244                 else
245                 {
246                     beg++; // Skip leading quote
247                     argument = s.substr(beg, end - beg);
248                     end++; // Skip trailing quote
249                 }
250             }
251         }
252 
253         //
254         // If any new options are added here,
255         // IceInternal::Reference::toString() and its derived classes must be updated as well.
256         //
257         switch(option[1])
258         {
259             case 'f':
260             {
261                 if(argument.empty())
262                 {
263                     throw ProxyParseException(__FILE__, __LINE__, "no argument provided for -f option in `" + s + "'");
264                 }
265 
266                 try
267                 {
268                     facet = unescapeString(argument, 0, argument.size(), "");
269                 }
270                 catch(const IceUtil::IllegalArgumentException& ex)
271                 {
272                     throw ProxyParseException(__FILE__, __LINE__, "invalid facet in `" + s + "': " + ex.reason());
273                 }
274 
275                 break;
276             }
277 
278             case 't':
279             {
280                 if(!argument.empty())
281                 {
282                     throw ProxyParseException(__FILE__, __LINE__, "unexpected argument `" + argument +
283                                               "' provided for -t option in `" + s + "'");
284                 }
285                 mode = Reference::ModeTwoway;
286                 break;
287             }
288 
289             case 'o':
290             {
291                 if(!argument.empty())
292                 {
293                     throw ProxyParseException(__FILE__, __LINE__, "unexpected argument `" + argument +
294                                               "' provided for -o option in `" + s + "'");
295                 }
296                 mode = Reference::ModeOneway;
297                 break;
298             }
299 
300             case 'O':
301             {
302                 if(!argument.empty())
303                 {
304                     throw ProxyParseException(__FILE__, __LINE__, "unexpected argument `" + argument +
305                                               "' provided for -O option in `" + s + "'");
306                 }
307                 mode = Reference::ModeBatchOneway;
308                 break;
309             }
310 
311             case 'd':
312             {
313                 if(!argument.empty())
314                 {
315                     throw ProxyParseException(__FILE__, __LINE__, "unexpected argument `" + argument +
316                                               "' provided for -d option in `" + s + "'");
317                 }
318                 mode = Reference::ModeDatagram;
319                 break;
320             }
321 
322             case 'D':
323             {
324                 if(!argument.empty())
325                 {
326                     throw ProxyParseException(__FILE__, __LINE__, "unexpected argument `" + argument +
327                                               "' provided for -D option in `" + s + "'");
328                 }
329                 mode = Reference::ModeBatchDatagram;
330                 break;
331             }
332 
333             case 's':
334             {
335                 if(!argument.empty())
336                 {
337                     throw ProxyParseException(__FILE__, __LINE__, "unexpected argument `" + argument +
338                                               "' provided for -s option in `" + s + "'");
339                 }
340                 secure = true;
341                 break;
342             }
343 
344             case 'e':
345             {
346                 if(argument.empty())
347                 {
348                     throw ProxyParseException(__FILE__, __LINE__, "no argument provided for -e option in `" + s + "'");
349                 }
350 
351                 try
352                 {
353                     encoding = Ice::stringToEncodingVersion(argument);
354                 }
355                 catch(const Ice::VersionParseException& ex)
356                 {
357                     throw ProxyParseException(__FILE__, __LINE__, "invalid encoding version `" + argument + "' in `" +
358                                               s + "':\n" + ex.str);
359                 }
360                 break;
361             }
362 
363             case 'p':
364             {
365                 if(argument.empty())
366                 {
367                     throw ProxyParseException(__FILE__, __LINE__, "no argument provided for -p option in `" + s + "'");
368                 }
369 
370                 try
371                 {
372                     protocol = Ice::stringToProtocolVersion(argument);
373                 }
374                 catch(const Ice::VersionParseException& ex)
375                 {
376                     throw ProxyParseException(__FILE__, __LINE__, "invalid protocol version `" + argument + "' in `" +
377                                               s + "':\n" + ex.str);
378                 }
379                 break;
380             }
381 
382             default:
383             {
384                 throw ProxyParseException(__FILE__, __LINE__, "unknown option `" + option + "' in `" + s + "'");
385             }
386         }
387     }
388 
389     if(beg == string::npos)
390     {
391         return create(ident, facet, mode, secure, protocol, encoding, vector<EndpointIPtr>(), "", propertyPrefix);
392     }
393 
394     vector<EndpointIPtr> endpoints;
395     switch(s[beg])
396     {
397         case ':':
398         {
399             vector<string> unknownEndpoints;
400             end = beg;
401 
402             while(end < s.length() && s[end] == ':')
403             {
404                 beg = end + 1;
405 
406                 end = beg;
407                 while(true)
408                 {
409                     end = s.find(':', end);
410                     if(end == string::npos)
411                     {
412                         end = s.length();
413                         break;
414                     }
415                     else
416                     {
417                         bool quoted = false;
418                         string::size_type quote = beg;
419                         while(true)
420                         {
421                             quote = s.find('\"', quote);
422                             if(quote == string::npos || end < quote)
423                             {
424                                 break;
425                             }
426                             else
427                             {
428                                 quote = s.find('\"', ++quote);
429                                 if(quote == string::npos)
430                                 {
431                                     break;
432                                 }
433                                 else if(end < quote)
434                                 {
435                                     quoted = true;
436                                     break;
437                                 }
438                                 ++quote;
439                             }
440                         }
441                         if(!quoted)
442                         {
443                             break;
444                         }
445                         ++end;
446                     }
447                 }
448 
449                 string es = s.substr(beg, end - beg);
450                 EndpointIPtr endp = _instance->endpointFactoryManager()->create(es, false);
451                 if(endp != ICE_NULLPTR)
452                 {
453                     endpoints.push_back(endp);
454                 }
455                 else
456                 {
457                     unknownEndpoints.push_back(es);
458                 }
459             }
460             if(endpoints.size() == 0)
461             {
462                 assert(!unknownEndpoints.empty());
463                 throw EndpointParseException(__FILE__, __LINE__, "invalid endpoint `" + unknownEndpoints.front() +
464                                              "' in `" + s + "'");
465             }
466             else if(unknownEndpoints.size() != 0 &&
467                     _instance->initializationData().properties->
468                                 getPropertyAsIntWithDefault("Ice.Warn.Endpoints", 1) > 0)
469             {
470                 Warning out(_instance->initializationData().logger);
471                 out << "Proxy contains unknown endpoints:";
472                 for(unsigned int idx = 0; idx < unknownEndpoints.size(); ++idx)
473                 {
474                     out << " `" << unknownEndpoints[idx] << "'";
475                 }
476             }
477 
478             return create(ident, facet, mode, secure, protocol, encoding, endpoints, "", propertyPrefix);
479             break;
480         }
481         case '@':
482         {
483             beg = s.find_first_not_of(delim, beg + 1);
484             if(beg == string::npos)
485             {
486                 throw ProxyParseException(__FILE__, __LINE__, "missing adapter id in `" + s + "'");
487             }
488 
489             string adapterstr;
490             end = IceUtilInternal::checkQuote(s, beg);
491             if(end == string::npos)
492             {
493                 throw ProxyParseException(__FILE__, __LINE__, "mismatched quotes around adapter id in `" + s + "'");
494             }
495             else if(end == 0)
496             {
497                 end = s.find_first_of(delim, beg);
498                 if(end == string::npos)
499                 {
500                     end = s.size();
501                 }
502                 adapterstr = s.substr(beg, end - beg);
503             }
504             else
505             {
506                 beg++; // Skip leading quote
507                 adapterstr = s.substr(beg, end - beg);
508                 end++; // Skip trailing quote.
509             }
510 
511             // Check for trailing whitespace.
512             if(end != string::npos && s.find_first_not_of(delim, end) != string::npos)
513             {
514                 throw ProxyParseException(__FILE__, __LINE__, "invalid trailing characters after `" +
515                                           s.substr(0, end + 1) + "' in `" + s + "'");
516             }
517 
518             try
519             {
520                 adapter = unescapeString(adapterstr, 0, adapterstr.size(), "");
521             }
522             catch(const IceUtil::IllegalArgumentException& ex)
523             {
524                 throw ProxyParseException(__FILE__, __LINE__, "invalid adapter id in `" + s + "': " + ex.reason());
525             }
526             if(adapter.size() == 0)
527             {
528                 throw ProxyParseException(__FILE__, __LINE__, "empty adapter id in `" + s + "'");
529             }
530 
531             return create(ident, facet, mode, secure, protocol, encoding, endpoints, adapter, propertyPrefix);
532             break;
533         }
534         default:
535         {
536             throw ProxyParseException(__FILE__, __LINE__, "malformed proxy `" + s + "'");
537         }
538     }
539 }
540 
541 ReferencePtr
create(const Identity & ident,InputStream * s)542 IceInternal::ReferenceFactory::create(const Identity& ident, InputStream* s)
543 {
544     //
545     // Don't read the identity here. Operations calling this
546     // constructor read the identity, and pass it as a parameter.
547     //
548 
549     if(ident.name.empty() && ident.category.empty())
550     {
551         return 0;
552     }
553 
554     //
555     // For compatibility with the old FacetPath.
556     //
557     vector<string> facetPath;
558     s->read(facetPath);
559     string facet;
560     if(!facetPath.empty())
561     {
562         if(facetPath.size() > 1)
563         {
564             throw ProxyUnmarshalException(__FILE__, __LINE__);
565         }
566         facet.swap(facetPath[0]);
567     }
568 
569     Byte modeAsByte;
570     s->read(modeAsByte);
571     Reference::Mode mode = static_cast<Reference::Mode>(modeAsByte);
572     if(mode < 0 || mode > Reference::ModeLast)
573     {
574         throw ProxyUnmarshalException(__FILE__, __LINE__);
575     }
576 
577     bool secure;
578     s->read(secure);
579 
580     Ice::ProtocolVersion protocol;
581     Ice::EncodingVersion encoding;
582     if(s->getEncoding() != Ice::Encoding_1_0)
583     {
584         s->read(protocol);
585         s->read(encoding);
586     }
587     else
588     {
589         protocol = Ice::Protocol_1_0;
590         encoding = Ice::Encoding_1_0;
591     }
592 
593     vector<EndpointIPtr> endpoints;
594     string adapterId;
595 
596     Ice::Int sz = s->readSize();
597 
598     if(sz > 0)
599     {
600         endpoints.reserve(sz);
601         while(sz--)
602         {
603             EndpointIPtr endpoint = _instance->endpointFactoryManager()->read(s);
604             endpoints.push_back(endpoint);
605         }
606     }
607     else
608     {
609         s->read(adapterId);
610     }
611 
612     return create(ident, facet, mode, secure, protocol, encoding, endpoints, adapterId, "");
613 }
614 
615 ReferenceFactoryPtr
setDefaultRouter(const RouterPrxPtr & defaultRouter)616 IceInternal::ReferenceFactory::setDefaultRouter(const RouterPrxPtr& defaultRouter)
617 {
618     if(defaultRouter == _defaultRouter)
619     {
620         return this;
621     }
622 
623     ReferenceFactoryPtr factory = new ReferenceFactory(_instance, _communicator);
624     factory->_defaultLocator = _defaultLocator;
625     factory->_defaultRouter = defaultRouter;
626     return factory;
627 }
628 
629 RouterPrxPtr
getDefaultRouter() const630 IceInternal::ReferenceFactory::getDefaultRouter() const
631 {
632     return _defaultRouter;
633 }
634 
635 ReferenceFactoryPtr
setDefaultLocator(const LocatorPrxPtr & defaultLocator)636 IceInternal::ReferenceFactory::setDefaultLocator(const LocatorPrxPtr& defaultLocator)
637 {
638     if(defaultLocator == _defaultLocator)
639     {
640         return this;
641     }
642 
643     ReferenceFactoryPtr factory = new ReferenceFactory(_instance, _communicator);
644     factory->_defaultRouter = _defaultRouter;
645     factory->_defaultLocator = defaultLocator;
646     return factory;
647 }
648 
649 LocatorPrxPtr
getDefaultLocator() const650 IceInternal::ReferenceFactory::getDefaultLocator() const
651 {
652     return _defaultLocator;
653 }
654 
ReferenceFactory(const InstancePtr & instance,const CommunicatorPtr & communicator)655 IceInternal::ReferenceFactory::ReferenceFactory(const InstancePtr& instance, const CommunicatorPtr& communicator) :
656     _instance(instance),
657     _communicator(communicator)
658 {
659 }
660 
661 void
checkForUnknownProperties(const string & prefix)662 IceInternal::ReferenceFactory::checkForUnknownProperties(const string& prefix)
663 {
664     static const string suffixes[] =
665     {
666         "EndpointSelection",
667         "ConnectionCached",
668         "PreferSecure",
669         "LocatorCacheTimeout",
670         "InvocationTimeout",
671         "Locator",
672         "Router",
673         "CollocationOptimized",
674         "Context.*"
675     };
676 
677     //
678     // Do not warn about unknown properties list if Ice prefix, ie Ice, Glacier2, etc
679     //
680     for(const char** i = IceInternal::PropertyNames::clPropNames; *i != 0; ++i)
681     {
682         if(prefix.find(*i) == 0)
683         {
684             return;
685         }
686     }
687 
688     StringSeq unknownProps;
689     PropertyDict props = _instance->initializationData().properties->getPropertiesForPrefix(prefix + ".");
690     for(PropertyDict::const_iterator p = props.begin(); p != props.end(); ++p)
691     {
692         bool valid = false;
693         for(unsigned int i = 0; i < sizeof(suffixes)/sizeof(*suffixes); ++i)
694         {
695             string prop = prefix + "." + suffixes[i];
696             if(IceUtilInternal::match(p->first, prop))
697             {
698                 valid = true;
699                 break;
700             }
701         }
702 
703         if(!valid)
704         {
705             unknownProps.push_back(p->first);
706         }
707     }
708 
709     if(unknownProps.size())
710     {
711         Warning out(_instance->initializationData().logger);
712         out << "found unknown properties for proxy '" << prefix << "':";
713         for(unsigned int i = 0; i < unknownProps.size(); ++i)
714         {
715             out << "\n    " << unknownProps[i];
716         }
717     }
718 }
719 
720 RoutableReferencePtr
create(const Identity & ident,const string & facet,Reference::Mode mode,bool secure,const Ice::ProtocolVersion & protocol,const Ice::EncodingVersion & encoding,const vector<EndpointIPtr> & endpoints,const string & adapterId,const string & propertyPrefix)721 IceInternal::ReferenceFactory::create(const Identity& ident,
722                                       const string& facet,
723                                       Reference::Mode mode,
724                                       bool secure,
725                                       const Ice::ProtocolVersion& protocol,
726                                       const Ice::EncodingVersion& encoding,
727                                       const vector<EndpointIPtr>& endpoints,
728                                       const string& adapterId,
729                                       const string& propertyPrefix)
730 {
731     DefaultsAndOverridesPtr defaultsAndOverrides = _instance->defaultsAndOverrides();
732 
733     //
734     // Default local proxy options.
735     //
736     LocatorInfoPtr locatorInfo;
737     if(_defaultLocator)
738     {
739         if(_defaultLocator->ice_getEncodingVersion() != encoding)
740         {
741             locatorInfo = _instance->locatorManager()->get(_defaultLocator->ice_encodingVersion(encoding));
742         }
743         else
744         {
745             locatorInfo = _instance->locatorManager()->get(_defaultLocator);
746         }
747     }
748     RouterInfoPtr routerInfo = _instance->routerManager()->get(_defaultRouter);
749     bool collocationOptimized = defaultsAndOverrides->defaultCollocationOptimization;
750     bool cacheConnection = true;
751     bool preferSecure = defaultsAndOverrides->defaultPreferSecure;
752     Ice::EndpointSelectionType endpointSelection = defaultsAndOverrides->defaultEndpointSelection;
753     int locatorCacheTimeout = defaultsAndOverrides->defaultLocatorCacheTimeout;
754     int invocationTimeout = defaultsAndOverrides->defaultInvocationTimeout;
755     Ice::Context ctx;
756 
757     //
758     // Override the defaults with the proxy properties if a property prefix is defined.
759     //
760     if(!propertyPrefix.empty())
761     {
762         PropertiesPtr properties = _instance->initializationData().properties;
763         if(properties->getPropertyAsIntWithDefault("Ice.Warn.UnknownProperties", 1) > 0)
764         {
765             checkForUnknownProperties(propertyPrefix);
766         }
767 
768         string property;
769 
770         property = propertyPrefix + ".Locator";
771         LocatorPrxPtr locator = ICE_UNCHECKED_CAST(LocatorPrx, _communicator->propertyToProxy(property));
772         if(locator)
773         {
774             if(locator->ice_getEncodingVersion() != encoding)
775             {
776                 locatorInfo = _instance->locatorManager()->get(locator->ice_encodingVersion(encoding));
777             }
778             else
779             {
780                 locatorInfo = _instance->locatorManager()->get(locator);
781             }
782         }
783 
784         property = propertyPrefix + ".Router";
785         RouterPrxPtr router = ICE_UNCHECKED_CAST(RouterPrx, _communicator->propertyToProxy(property));
786         if(router)
787         {
788             if(propertyPrefix.size() > 7 && propertyPrefix.substr(propertyPrefix.size() - 7, 7) == ".Router")
789             {
790                 Warning out(_instance->initializationData().logger);
791                 out << "`" << property << "=" << properties->getProperty(property)
792                     << "': cannot set a router on a router; setting ignored";
793             }
794             else
795             {
796                 routerInfo = _instance->routerManager()->get(router);
797             }
798         }
799 
800         property = propertyPrefix + ".CollocationOptimized";
801         collocationOptimized = properties->getPropertyAsIntWithDefault(property, collocationOptimized) > 0;
802 
803         property = propertyPrefix + ".ConnectionCached";
804         cacheConnection = properties->getPropertyAsIntWithDefault(property, cacheConnection) > 0;
805 
806         property = propertyPrefix + ".PreferSecure";
807         preferSecure = properties->getPropertyAsIntWithDefault(property, preferSecure) > 0;
808 
809         property = propertyPrefix + ".EndpointSelection";
810         if(!properties->getProperty(property).empty())
811         {
812             string type = properties->getProperty(property);
813             if(type == "Random")
814             {
815                 endpointSelection = ICE_ENUM(EndpointSelectionType, Random);
816             }
817             else if(type == "Ordered")
818             {
819                 endpointSelection = ICE_ENUM(EndpointSelectionType, Ordered);
820             }
821             else
822             {
823                 throw EndpointSelectionTypeParseException(__FILE__, __LINE__, "illegal value `" + type +
824                                                           "'; expected `Random' or `Ordered'");
825             }
826         }
827 
828         property = propertyPrefix + ".LocatorCacheTimeout";
829         string value = properties->getProperty(property);
830         if(!value.empty())
831         {
832             locatorCacheTimeout = properties->getPropertyAsIntWithDefault(property, locatorCacheTimeout);
833             if(locatorCacheTimeout < -1)
834             {
835                 locatorCacheTimeout = -1;
836 
837                 Warning out(_instance->initializationData().logger);
838                 out << "invalid value for " << property << "`" << properties->getProperty(property) << "'"
839                     << ": defaulting to -1";
840             }
841         }
842 
843         property = propertyPrefix + ".InvocationTimeout";
844         value = properties->getProperty(property);
845         if(!value.empty())
846         {
847             invocationTimeout = properties->getPropertyAsIntWithDefault(property, invocationTimeout);
848             if(invocationTimeout < 1 && invocationTimeout != -1)
849             {
850                 invocationTimeout = -1;
851 
852                 Warning out(_instance->initializationData().logger);
853                 out << "invalid value for " << property << "`" << properties->getProperty(property) << "'"
854                     << ": defaulting to -1";
855             }
856         }
857 
858         property = propertyPrefix + ".Context.";
859         PropertyDict contexts = properties->getPropertiesForPrefix(property);
860         for(PropertyDict::const_iterator p = contexts.begin(); p != contexts.end(); ++p)
861         {
862             ctx.insert(make_pair(p->first.substr(property.length()), p->second));
863         }
864     }
865 
866     //
867     // Create new reference
868     //
869     return new RoutableReference(_instance,
870                                  _communicator,
871                                  ident,
872                                  facet,
873                                  mode,
874                                  secure,
875                                  protocol,
876                                  encoding,
877                                  endpoints,
878                                  adapterId,
879                                  locatorInfo,
880                                  routerInfo,
881                                  collocationOptimized,
882                                  cacheConnection,
883                                  preferSecure,
884                                  endpointSelection,
885                                  locatorCacheTimeout,
886                                  invocationTimeout,
887                                  ctx);
888 }
889