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