1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <Ice/EndpointFactoryManager.h>
6 #include <Ice/Endpoint.h>
7 #include <Ice/OpaqueEndpointI.h>
8 #include <Ice/OutputStream.h>
9 #include <Ice/InputStream.h>
10 #include <Ice/LocalException.h>
11 #include <Ice/Instance.h>
12 #include <Ice/Properties.h>
13 #include <Ice/DefaultsAndOverrides.h>
14 #include <IceUtil/StringUtil.h>
15 
16 using namespace std;
17 using namespace Ice;
18 using namespace IceInternal;
19 
20 IceUtil::Shared* IceInternal::upCast(EndpointFactoryManager* p) { return p; }
21 
22 IceInternal::EndpointFactoryManager::EndpointFactoryManager(const InstancePtr& instance)
23     : _instance(instance)
24 {
25 }
26 
27 void
28 IceInternal::EndpointFactoryManager::initialize() const
29 {
30     for(vector<EndpointFactoryPtr>::size_type i = 0; i < _factories.size(); i++)
31     {
32         _factories[i]->initialize();
33     }
34 }
35 
36 void
37 IceInternal::EndpointFactoryManager::add(const EndpointFactoryPtr& factory)
38 {
39     IceUtil::Mutex::Lock sync(*this); // TODO: Necessary?
40 
41     //
42     // TODO: Optimize with a map?
43     //
44     for(vector<EndpointFactoryPtr>::size_type i = 0; i < _factories.size(); i++)
45     {
46         if(_factories[i]->type() == factory->type())
47         {
48             assert(false); // TODO: Exception?
49         }
50     }
51     _factories.push_back(factory);
52 }
53 
54 EndpointFactoryPtr
55 IceInternal::EndpointFactoryManager::get(Short type) const
56 {
57     IceUtil::Mutex::Lock sync(*this); // TODO: Necessary?
58 
59     //
60     // TODO: Optimize with a map?
61     //
62     for(vector<EndpointFactoryPtr>::size_type i = 0; i < _factories.size(); i++)
63     {
64         if(_factories[i]->type() == type)
65         {
66             return _factories[i];
67         }
68     }
69     return ICE_NULLPTR;
70 }
71 
72 EndpointIPtr
73 IceInternal::EndpointFactoryManager::create(const string& str, bool oaEndpoint) const
74 {
75     vector<string> v;
76     bool b = IceUtilInternal::splitString(str, " \t\n\r", v);
77     if(!b)
78     {
79         throw EndpointParseException(__FILE__, __LINE__, "mismatched quote");
80     }
81 
82     if(v.empty())
83     {
84         throw EndpointParseException(__FILE__, __LINE__, "value has no non-whitespace characters");
85     }
86 
87     string protocol = v.front();
88     v.erase(v.begin());
89 
90     if(protocol == "default")
91     {
92         protocol = _instance->defaultsAndOverrides()->defaultProtocol;
93     }
94 
95     EndpointFactoryPtr factory;
96     {
97         IceUtil::Mutex::Lock sync(*this); // TODO: Necessary?
98 
99         //
100         // TODO: Optimize with a map?
101         //
102         for(vector<EndpointFactoryPtr>::size_type i = 0; i < _factories.size(); i++)
103         {
104             if(_factories[i]->protocol() == protocol)
105             {
106                 factory = _factories[i];
107             }
108         }
109     }
110 
111     if(factory)
112     {
113 #if 1
114         EndpointIPtr e = factory->create(v, oaEndpoint);
115         if(!v.empty())
116         {
117             throw EndpointParseException(__FILE__, __LINE__, "unrecognized argument `" + v.front() +
118                                          "' in endpoint `" + str + "'");
119         }
120         return e;
121 #else
122         // Code below left in place for debugging.
123 
124         EndpointIPtr e = factory->create(str.substr(end), oaEndpoint);
125         OutputStream bs(_instance.get(), Ice::currentProtocolEncoding);
126         e->streamWrite(&bs);
127         bs.i = bs.b.begin();
128         short type;
129         bs.read(type);
130         EndpointIPtr ue = new IceInternal::OpaqueEndpointI(type, &bs);
131         consoleErr << "Normal: " << e->toString() << endl;
132         consoleErr << "Opaque: " << ue->toString() << endl;
133         return e;
134 #endif
135     }
136 
137     //
138     // If the stringified endpoint is opaque, create an unknown endpoint,
139     // then see whether the type matches one of the known endpoints.
140     //
141     if(protocol == "opaque")
142     {
143         EndpointIPtr ue = ICE_MAKE_SHARED(OpaqueEndpointI, v);
144         if(!v.empty())
145         {
146             throw EndpointParseException(__FILE__, __LINE__, "unrecognized argument `" + v.front() + "' in endpoint `" +
147                                          str + "'");
148         }
149         factory = get(ue->type());
150         if(factory)
151         {
152             //
153             // Make a temporary stream, write the opaque endpoint data into the stream,
154             // and ask the factory to read the endpoint data from that stream to create
155             // the actual endpoint.
156             //
157             OutputStream bs(_instance.get(), Ice::currentProtocolEncoding);
158             bs.write(ue->type());
159             ue->streamWrite(&bs);
160             InputStream is(bs.instance(), bs.getEncoding(), bs);
161             short type;
162             is.read(type);
163             is.startEncapsulation();
164             EndpointIPtr e = factory->read(&is);
165             is.endEncapsulation();
166             return e;
167         }
168         return ue; // Endpoint is opaque, but we don't have a factory for its type.
169     }
170 
171     return ICE_NULLPTR;
172 }
173 
174 EndpointIPtr
175 IceInternal::EndpointFactoryManager::read(InputStream* s) const
176 {
177     Short type;
178     s->read(type);
179 
180     EndpointFactoryPtr factory = get(type);
181     EndpointIPtr e;
182 
183     s->startEncapsulation();
184 
185     if(factory)
186     {
187         e = factory->read(s);
188     }
189     //
190     // If the factory failed to read the endpoint, return an opaque endpoint. This can
191     // occur if for example the factory delegates to another factory and this factory
192     // isn't available. In this case, the factory needs to make sure the stream position
193     // is preserved for reading the opaque endpoint.
194     //
195     if(!e)
196     {
197         e = ICE_MAKE_SHARED(OpaqueEndpointI, type, s);
198     }
199 
200     s->endEncapsulation();
201 
202     return e;
203 }
204 
205 void
206 IceInternal::EndpointFactoryManager::destroy()
207 {
208     for(vector<EndpointFactoryPtr>::size_type i = 0; i < _factories.size(); i++)
209     {
210         _factories[i]->destroy();
211     }
212     _factories.clear();
213 }
214