1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 namespace IceInternal
6 {
7     using System.Collections.Generic;
8     using System.Diagnostics;
9 
10     public sealed class EndpointFactoryManager
11     {
EndpointFactoryManager(Instance instance)12         internal EndpointFactoryManager(Instance instance)
13         {
14             _instance = instance;
15             _factories = new List<EndpointFactory>();
16         }
17 
initialize()18         public void initialize()
19         {
20             foreach(EndpointFactory f in _factories)
21             {
22                 f.initialize();
23             }
24         }
25 
add(EndpointFactory factory)26         public void add(EndpointFactory factory)
27         {
28             lock(this)
29             {
30                 foreach(EndpointFactory f in _factories)
31                 {
32                     if(f.type() == factory.type())
33                     {
34                         Debug.Assert(false);
35                     }
36                 }
37                 _factories.Add(factory);
38             }
39         }
40 
get(short type)41         public EndpointFactory get(short type)
42         {
43             lock(this)
44             {
45                 foreach(EndpointFactory f in _factories)
46                 {
47                     if(f.type() == type)
48                     {
49                         return f;
50                     }
51                 }
52                 return null;
53             }
54         }
55 
create(string str, bool oaEndpoint)56         public EndpointI create(string str, bool oaEndpoint)
57         {
58             string[] arr = IceUtilInternal.StringUtil.splitString(str, " \t\r\n");
59             if(arr == null)
60             {
61                 Ice.EndpointParseException e = new Ice.EndpointParseException();
62                 e.str = "mismatched quote";
63                 throw e;
64             }
65 
66             if(arr.Length == 0)
67             {
68                 Ice.EndpointParseException e = new Ice.EndpointParseException();
69                 e.str = "value has no non-whitespace characters";
70                 throw e;
71             }
72 
73             List<string> v = new List<string>(arr);
74             string protocol = v[0];
75             v.RemoveAt(0);
76 
77             if(protocol.Equals("default"))
78             {
79                 protocol = _instance.defaultsAndOverrides().defaultProtocol;
80             }
81 
82             EndpointFactory factory = null;
83 
84             lock(this)
85             {
86                 for(int i = 0; i < _factories.Count; i++)
87                 {
88                     EndpointFactory f = _factories[i];
89                     if(f.protocol().Equals(protocol))
90                     {
91                         factory = f;
92                     }
93                 }
94             }
95 
96             if(factory != null)
97             {
98                 EndpointI e = factory.create(v, oaEndpoint);
99                 if(v.Count > 0)
100                 {
101                     Ice.EndpointParseException ex = new Ice.EndpointParseException();
102                     ex.str = "unrecognized argument `" + v[0] + "' in endpoint `" + str + "'";
103                     throw ex;
104                 }
105                 return e;
106 
107                 // Code below left in place for debugging.
108 
109                 /*
110                 EndpointI e = f.create(s.Substring(m.Index + m.Length), oaEndpoint);
111                 BasicStream bs = new BasicStream(_instance, true);
112                 e.streamWrite(bs);
113                 Buffer buf = bs.getBuffer();
114                 buf.b.position(0);
115                 short type = bs.readShort();
116                 EndpointI ue = new IceInternal.OpaqueEndpointI(type, bs);
117                 System.Console.Error.WriteLine("Normal: " + e);
118                 System.Console.Error.WriteLine("Opaque: " + ue);
119                 return e;
120                 */
121             }
122 
123             //
124             // If the stringified endpoint is opaque, create an unknown endpoint,
125             // then see whether the type matches one of the known endpoints.
126             //
127             if(protocol.Equals("opaque"))
128             {
129                 EndpointI ue = new OpaqueEndpointI(v);
130                 if(v.Count > 0)
131                 {
132                     Ice.EndpointParseException ex = new Ice.EndpointParseException();
133                     ex.str = "unrecognized argument `" + v[0] + "' in endpoint `" + str + "'";
134                     throw ex;
135                 }
136                 factory = get(ue.type());
137                 if(factory != null)
138                 {
139                     //
140                     // Make a temporary stream, write the opaque endpoint data into the stream,
141                     // and ask the factory to read the endpoint data from that stream to create
142                     // the actual endpoint.
143                     //
144                     Ice.OutputStream os = new Ice.OutputStream(_instance, Ice.Util.currentProtocolEncoding);
145                     os.writeShort(ue.type());
146                     ue.streamWrite(os);
147                     Ice.InputStream iss =
148                         new Ice.InputStream(_instance, Ice.Util.currentProtocolEncoding, os.getBuffer(), true);
149                     iss.pos(0);
150                     iss.readShort(); // type
151                     iss.startEncapsulation();
152                     EndpointI e = factory.read(iss);
153                     iss.endEncapsulation();
154                     return e;
155                 }
156                 return ue; // Endpoint is opaque, but we don't have a factory for its type.
157             }
158 
159             return null;
160         }
161 
read(Ice.InputStream s)162         public EndpointI read(Ice.InputStream s)
163         {
164             lock(this)
165             {
166                 short type = s.readShort();
167 
168                 EndpointFactory factory = get(type);
169                 EndpointI e = null;
170 
171                 s.startEncapsulation();
172 
173                 if(factory != null)
174                 {
175                     e = factory.read(s);
176                 }
177                 //
178                 // If the factory failed to read the endpoint, return an opaque endpoint. This can
179                 // occur if for example the factory delegates to another factory and this factory
180                 // isn't available. In this case, the factory needs to make sure the stream position
181                 // is preserved for reading the opaque endpoint.
182                 //
183                 if(e == null)
184                 {
185                     e = new OpaqueEndpointI(type, s);
186                 }
187 
188                 s.endEncapsulation();
189 
190                 return e;
191             }
192         }
193 
destroy()194         internal void destroy()
195         {
196             foreach(EndpointFactory f in _factories)
197             {
198                 f.destroy();
199             }
200             _factories.Clear();
201         }
202 
203         private readonly Instance _instance;
204         private readonly List<EndpointFactory> _factories;
205     }
206 
207 }
208