0003-Add-a-config-loader-and-a-transport-registry_c96a85.patch
rsb-cil-test/Program.cs | ||
---|---|---|
13 | 13 |
{ |
14 | 14 |
class MainClass |
15 | 15 |
{ |
16 |
static readonly string host = "localhost"; |
|
17 |
static readonly int port = 30010; |
|
16 |
static readonly SocketOptions options = new SocketOptions("localhost", 30010, true); |
|
18 | 17 | |
19 | 18 |
public static void PrintEvent(Event theEvent) |
20 | 19 |
{ |
... | ... | |
36 | 35 | |
37 | 36 |
static void Main(String[] args) |
38 | 37 |
{ |
39 | ||
40 | 38 |
BasicConfigurator.Configure(); |
41 | 39 | |
42 | 40 |
var inConverters = buildConverterSelection(new List<Tuple<String, IConverter>> { |
... | ... | |
49 | 47 |
new Tuple<Type, IConverter>(typeof(JointAngles), new ProtocolBufferConverter(JointAngles.Descriptor)) |
50 | 48 |
}); |
51 | 49 | |
52 |
var listener = new Listener(new InPushConnector(new BusClientConnection(host, port), new Scope("/"), inConverters));
|
|
50 |
var listener = new Listener(new SocketInPushConnector(new BusClientConnection(options), inConverters));
|
|
53 | 51 |
listener.EventReceived += new NewEventHandler(PrintEvent); |
54 | 52 |
listener.Activate(); |
55 | 53 | |
56 |
var informer = new Informer("/test/narf", new OutConnector(new BusClientConnection(host, port),
|
|
54 |
var informer = new Informer("/test/narf", new SocketOutConnector(new BusClientConnection(options),
|
|
57 | 55 |
outConverters)); |
58 | 56 |
Console.WriteLine(informer.Scope); |
59 | 57 |
informer.Activate(); |
60 | 58 | |
61 | 59 |
for (int i = 0; i < 5; i++) |
62 | 60 |
{ |
63 | ||
64 | 61 |
var angles = new JointAngles(); |
65 | 62 |
angles.Angles.Add(1); |
66 | 63 |
informer.Send(angles); |
... | ... | |
77 | 74 | |
78 | 75 |
Console.WriteLine("\nFactory Test:"); |
79 | 76 | |
80 |
SocketConfiguration.Hostname = host; |
|
81 |
SocketConfiguration.Port = port; |
|
82 | ||
83 |
DefaultConverterRepository.Instance.addConverter(new ProtocolBufferConverter(JointAngles.Descriptor)); |
|
77 |
DefaultConverterRepository.Instance.AddConverter(new ProtocolBufferConverter(JointAngles.Descriptor)); |
|
84 | 78 | |
85 | 79 |
Informer repoInformer = Factory.Instance.CreateInformer("/test/repo"); |
86 | 80 |
Listener repoListener = Factory.Instance.CreateListener("/"); |
... | ... | |
159 | 153 |
remote.Call("voidvoid"); |
160 | 154 | |
161 | 155 |
// do some asynchronous calls |
162 |
var futureEcho = remote.CallAsync<string,string>("echo", "Async"); |
|
156 |
var futureEcho = remote.CallAsync<string, string>("echo", "Async");
|
|
163 | 157 |
remote.CallAsync("voidvoid"); |
164 | 158 |
var futureType = remote.CallAsync<string>("typevoid"); |
165 | 159 | |
... | ... | |
198 | 192 |
server.Deactivate(); |
199 | 193 |
remote.Deactivate(); |
200 | 194 |
} |
201 | ||
202 |
} |
|
195 |
} |
|
203 | 196 | |
204 | 197 |
public class ExceptionCall : DataCallback<int, Null> |
205 | 198 |
{ |
rsb-cil/Rsb/Config/ParticipantConfig.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using System.Collections.Generic; |
|
3 |
using System.Text; |
|
4 | ||
5 |
namespace Rsb.Config |
|
6 |
{ |
|
7 |
/** |
|
8 |
* Like the Java version but... |
|
9 |
* - no Introspection |
|
10 |
* - no receivingStrategy! |
|
11 |
*/ |
|
12 | ||
13 |
public class ParticipantConfig |
|
14 |
{ |
|
15 |
public Dictionary<String, TransportConfig> TransportsByName |
|
16 |
{ |
|
17 |
get; |
|
18 |
} = new Dictionary<String, TransportConfig>(); |
|
19 | ||
20 |
public HashSet<TransportConfig> EnabledTransports |
|
21 |
{ |
|
22 |
get |
|
23 |
{ |
|
24 |
HashSet<TransportConfig> enabledTransports = |
|
25 |
new HashSet<TransportConfig>(); |
|
26 |
foreach (TransportConfig config in this.TransportsByName.Values) |
|
27 |
{ |
|
28 |
if (config.Enabled) |
|
29 |
{ |
|
30 |
enabledTransports.Add(config); |
|
31 |
} |
|
32 |
} |
|
33 |
return enabledTransports; |
|
34 |
} |
|
35 |
} |
|
36 | ||
37 |
public bool HasTransport(String name) |
|
38 |
{ |
|
39 |
return this.TransportsByName.ContainsKey(name); |
|
40 |
} |
|
41 | ||
42 |
public TransportConfig GetOrCreateTransport(String transportName) |
|
43 |
{ |
|
44 |
if (this.TransportsByName.ContainsKey(transportName)) |
|
45 |
{ |
|
46 |
return this.TransportsByName[transportName]; |
|
47 |
} |
|
48 |
else |
|
49 |
{ |
|
50 |
TransportConfig newTransport = |
|
51 |
new TransportConfig(transportName); |
|
52 |
this.TransportsByName[transportName] = newTransport; |
|
53 |
return newTransport; |
|
54 |
} |
|
55 |
} |
|
56 | ||
57 |
public ParticipantConfig Copy() |
|
58 |
{ |
|
59 |
ParticipantConfig copy = new ParticipantConfig(); |
|
60 | ||
61 |
foreach (var transportName in this.TransportsByName.Keys) |
|
62 |
{ |
|
63 |
copy.TransportsByName[transportName] = TransportsByName[transportName].Copy(); |
|
64 |
} |
|
65 | ||
66 |
return copy; |
|
67 |
} |
|
68 | ||
69 |
public override String ToString() |
|
70 |
{ |
|
71 |
StringBuilder builder = new StringBuilder(57); |
|
72 |
builder.Append(GetType().Name); |
|
73 |
builder.Append("[transports={"); |
|
74 |
bool first = true; |
|
75 |
foreach (var transport in TransportsByName.Values) |
|
76 |
{ |
|
77 |
if (first) |
|
78 |
{ |
|
79 |
first = false; |
|
80 |
} |
|
81 |
else |
|
82 |
{ |
|
83 |
builder.Append(","); |
|
84 |
} |
|
85 |
builder.Append(transport.ToString()); |
|
86 |
} |
|
87 |
builder.Append("}]"); |
|
88 | ||
89 |
return builder.ToString(); |
|
90 |
} |
|
91 | ||
92 |
public override int GetHashCode() |
|
93 |
{ |
|
94 |
int result = 17 * this.TransportsByName.GetHashCode(); |
|
95 |
return result; |
|
96 |
} |
|
97 | ||
98 |
public override bool Equals(object obj) |
|
99 |
{ |
|
100 |
if (!(obj.GetType().Equals(typeof(ParticipantConfig)))) |
|
101 |
{ |
|
102 |
return false; |
|
103 |
} |
|
104 |
ParticipantConfig other = (ParticipantConfig)obj; |
|
105 |
return this.TransportsByName.Equals(other.TransportsByName); |
|
106 |
} |
|
107 |
} |
|
108 |
} |
rsb-cil/Rsb/Config/ParticipantConfigCreator.cs | ||
---|---|---|
1 |
using Rsb.Transport; |
|
2 |
using Rsb.Util; |
|
3 |
using System; |
|
4 |
using System.Collections.Generic; |
|
5 |
using System.Linq; |
|
6 |
using System.Text; |
|
7 |
using System.Threading.Tasks; |
|
8 | ||
9 |
namespace Rsb.Config |
|
10 |
{ |
|
11 |
/** |
|
12 |
* like java implementation but... |
|
13 |
* - without introspection |
|
14 |
*/ |
|
15 | ||
16 |
public class ParticipantConfigCreator |
|
17 |
{ |
|
18 |
public ParticipantConfig Create(Properties properties) |
|
19 |
{ |
|
20 |
ParticipantConfig config = new ParticipantConfig(); |
|
21 |
Reconfigure(config, properties); |
|
22 |
return config; |
|
23 |
} |
|
24 | ||
25 |
public void Reconfigure(ParticipantConfig config, Properties properties) |
|
26 |
{ |
|
27 |
foreach (String transportName in TransportRegistry.Instance.AvailableTransportNames) |
|
28 |
{ |
|
29 |
String transportPropPrefix = "transport." + transportName; |
|
30 |
Properties transportProps = properties |
|
31 |
.Filter(transportPropPrefix); |
|
32 | ||
33 |
HashSet<String> handledKeys = new HashSet<String>(); |
|
34 | ||
35 |
TransportConfig transportConfig = config |
|
36 |
.GetOrCreateTransport(transportName); |
|
37 | ||
38 |
String enabledKey = transportPropPrefix + ".enabled"; |
|
39 |
transportConfig.Enabled = transportProps.GetProperty( |
|
40 |
enabledKey, transportConfig.Enabled).AsBoolean(); |
|
41 |
handledKeys.Add(enabledKey); |
|
42 | ||
43 |
transportProps.Remove(handledKeys); |
|
44 |
transportConfig.Options.Merge(transportProps); |
|
45 |
} |
|
46 |
} |
|
47 |
} |
|
48 |
} |
rsb-cil/Rsb/Config/TransportConfig.cs | ||
---|---|---|
1 |
using Rsb.Converter; |
|
2 |
using Rsb.Util; |
|
3 |
using System; |
|
4 |
using System.Text; |
|
5 | ||
6 |
namespace Rsb.Config |
|
7 |
{ |
|
8 |
public class TransportConfig |
|
9 |
{ |
|
10 |
public String Name { get; private set; } |
|
11 |
public bool Enabled { get; set; } |
|
12 |
public Properties Options { get; set; } |
|
13 |
private IConverterRepository _converter; |
|
14 |
public IConverterRepository Converters |
|
15 |
{ |
|
16 |
get |
|
17 |
{ |
|
18 |
if (_converter == null) |
|
19 |
{ |
|
20 |
return DefaultConverterRepository.Instance; |
|
21 |
} |
|
22 |
else |
|
23 |
{ |
|
24 |
return _converter; |
|
25 |
} |
|
26 |
} |
|
27 |
set |
|
28 |
{ |
|
29 |
_converter = value; |
|
30 |
} |
|
31 |
} |
|
32 | ||
33 |
public TransportConfig(String name, bool enabled, Properties options, IConverterRepository converters) |
|
34 |
{ |
|
35 |
this.Name = name; |
|
36 |
this.Enabled = enabled; |
|
37 |
this.Options = options; |
|
38 |
this.Converters = converters; |
|
39 |
} |
|
40 | ||
41 |
public TransportConfig(String name) : this(name, false, new Properties(), null) |
|
42 |
{ |
|
43 |
} |
|
44 | ||
45 |
public override String ToString() |
|
46 |
{ |
|
47 |
StringBuilder builder = new StringBuilder(42); |
|
48 |
builder.Append(GetType().Name); |
|
49 |
builder.Append("[name='"); |
|
50 |
builder.Append(this.Name); |
|
51 |
builder.Append("', enabled="); |
|
52 |
builder.Append(this.Enabled); |
|
53 |
builder.Append(", options="); |
|
54 |
builder.Append(this.Options); |
|
55 |
builder.Append(", converters="); |
|
56 |
builder.Append(this.Converters); |
|
57 |
builder.Append(']'); |
|
58 | ||
59 |
return builder.ToString(); |
|
60 |
} |
|
61 | ||
62 |
public TransportConfig Copy() |
|
63 |
{ |
|
64 |
TransportConfig copy = new TransportConfig(Name); |
|
65 |
copy.Enabled = this.Enabled; |
|
66 |
copy.Converters = this.Converters; |
|
67 |
foreach (var key in Options.GetAvailableKeys()) |
|
68 |
{ |
|
69 |
copy.Options.SetProperty(key, Options.GetProperty(key).AsString()); |
|
70 |
} |
|
71 |
return copy; |
|
72 |
} |
|
73 | ||
74 |
public override int GetHashCode() |
|
75 |
{ |
|
76 |
int prime = 31; |
|
77 |
int result = 1; |
|
78 |
result = |
|
79 |
prime * result |
|
80 |
+ ((this.Converters == null) ? 0 : this.Converters.GetHashCode()); |
|
81 |
result = prime * result + (this.Enabled ? 1231 : 1237); |
|
82 |
result = |
|
83 |
prime * result |
|
84 |
+ ((this.Name == null) ? 0 : this.Name.GetHashCode()); |
|
85 |
result = |
|
86 |
prime |
|
87 |
* result |
|
88 |
+ ((this.Options == null) ? 0 : this.Options.GetHashCode()); |
|
89 |
return result; |
|
90 |
} |
|
91 | ||
92 |
public override bool Equals(object obj) |
|
93 |
{ |
|
94 |
if (this == obj) |
|
95 |
{ |
|
96 |
return true; |
|
97 |
} |
|
98 |
if (obj == null) |
|
99 |
{ |
|
100 |
return false; |
|
101 |
} |
|
102 |
if (!(obj.GetType().Equals(typeof(TransportConfig)))) |
|
103 |
{ |
|
104 |
return false; |
|
105 |
} |
|
106 |
TransportConfig other = (TransportConfig)obj; |
|
107 |
if (this.Converters == null) |
|
108 |
{ |
|
109 |
if (other.Converters != null) |
|
110 |
{ |
|
111 |
return false; |
|
112 |
} |
|
113 |
} |
|
114 |
else |
|
115 |
{ |
|
116 |
if (!this.Converters.Equals(other.Converters)) |
|
117 |
{ |
|
118 |
return false; |
|
119 |
} |
|
120 |
} |
|
121 |
if (this.Enabled != other.Enabled) |
|
122 |
{ |
|
123 |
return false; |
|
124 |
} |
|
125 |
if (this.Name == null) |
|
126 |
{ |
|
127 |
if (other.Name != null) |
|
128 |
{ |
|
129 |
return false; |
|
130 |
} |
|
131 |
} |
|
132 |
else if (!this.Name.Equals(other.Name)) |
|
133 |
{ |
|
134 |
return false; |
|
135 |
} |
|
136 |
if (this.Options == null) |
|
137 |
{ |
|
138 |
if (other.Options != null) |
|
139 |
{ |
|
140 |
return false; |
|
141 |
} |
|
142 |
} |
|
143 |
else if (!this.Options.Equals(other.Options)) |
|
144 |
{ |
|
145 |
return false; |
|
146 |
} |
|
147 |
return true; |
|
148 |
} |
|
149 |
} |
|
150 |
} |
rsb-cil/Rsb/Converter/DefaultConverterRepository.cs | ||
---|---|---|
3 | 3 | |
4 | 4 |
namespace Rsb.Converter |
5 | 5 |
{ |
6 |
public class DefaultConverterRepository |
|
6 |
public class DefaultConverterRepository : IConverterRepository
|
|
7 | 7 |
{ |
8 | 8 |
private static readonly DefaultConverterRepository instance = new DefaultConverterRepository(); |
9 | 9 | |
... | ... | |
36 | 36 | |
37 | 37 |
private DefaultConverterRepository() |
38 | 38 |
{ |
39 | ||
40 | 39 |
foreach (var converter in defaultConverter) |
41 | 40 |
{ |
42 |
ConverterSignature signature = converter.GetSignature(); |
|
43 | ||
44 |
deserializationConverterList.Add( |
|
45 |
new Tuple<PredicateConverterSelection<string>.Predicate, IConverter>( |
|
46 |
new IsExactMatch<string>(signature.Schema), |
|
47 |
converter |
|
48 |
)); |
|
49 | ||
50 |
serializationConverterList.Add( |
|
51 |
new Tuple<PredicateConverterSelection<Type>.Predicate, IConverter>( |
|
52 |
new IsExactMatch<Type>(signature.DataType), |
|
53 |
converter |
|
54 |
)); |
|
41 |
AddConverter(converter); |
|
55 | 42 |
} |
56 | 43 | |
57 | 44 |
DeserializationConverterSelector = new PredicateConverterSelection<string>(deserializationConverterList); |
58 | 45 |
SerializationConverterSelector = new PredicateConverterSelection<Type>(serializationConverterList); |
59 | ||
60 | 46 |
} |
61 | 47 | |
62 | 48 |
public static DefaultConverterRepository Instance |
... | ... | |
67 | 53 |
} |
68 | 54 |
} |
69 | 55 | |
70 |
public void addConverter(IConverter converter)
|
|
56 |
public void AddConverter(IConverter converter)
|
|
71 | 57 |
{ |
72 | 58 |
deserializationConverterList.Add( |
73 | 59 |
new Tuple<PredicateConverterSelection<string>.Predicate, IConverter>( |
rsb-cil/Rsb/Converter/IConverterRepository.cs | ||
---|---|---|
1 |
using System; |
|
2 | ||
3 |
namespace Rsb.Converter |
|
4 |
{ |
|
5 |
public interface IConverterRepository |
|
6 |
{ |
|
7 |
PredicateConverterSelection<string> DeserializationConverterSelector { get; } |
|
8 |
PredicateConverterSelection<Type> SerializationConverterSelector { get; } |
|
9 | ||
10 |
void AddConverter(IConverter converter); |
|
11 |
} |
|
12 |
} |
rsb-cil/Rsb/Factory.cs | ||
---|---|---|
1 | 1 |
using Rsb.Transport.Socket; |
2 | 2 |
using Rsb.Converter; |
3 | 3 |
using Rsb.Patterns; |
4 |
using Rsb.Util; |
|
5 |
using System; |
|
6 |
using Rsb.Config; |
|
7 |
using Rsb.Transport; |
|
8 |
using System.Collections.Generic; |
|
4 | 9 | |
5 | 10 |
namespace Rsb |
6 | 11 |
{ |
... | ... | |
8 | 13 |
{ |
9 | 14 |
private static readonly Factory instance = new Factory(); |
10 | 15 | |
16 |
private Properties properties = new Properties(); |
|
17 |
private ParticipantConfig defaultConfig = new ParticipantConfig(); |
|
18 | ||
11 | 19 |
// Explicit static constructor to tell C# compiler |
12 | 20 |
// not to mark type as beforefieldinit |
13 | 21 |
static Factory() |
... | ... | |
16 | 24 | |
17 | 25 |
private Factory() |
18 | 26 |
{ |
27 |
TransportRegistry.Instance.RegisterTransport("socket", new SocketFactory()); |
|
28 | ||
29 |
new ConfigLoader().Load(this.properties); |
|
30 |
new ParticipantConfigCreator().Reconfigure(this.defaultConfig, this.properties); |
|
19 | 31 |
} |
20 | 32 | |
21 | 33 |
public static Factory Instance |
... | ... | |
26 | 38 |
} |
27 | 39 |
} |
28 | 40 | |
29 |
public Informer CreateInformer(Scope scope) { |
|
30 | ||
31 |
return new Informer(scope, |
|
32 |
new OutConnector( |
|
33 |
new BusClientConnection(SocketConfiguration.Hostname, SocketConfiguration.Port), |
|
34 |
DefaultConverterRepository.Instance.SerializationConverterSelector)); |
|
41 |
public Informer CreateInformer(Scope scope) |
|
42 |
{ |
|
43 |
List<IOutConnector> connectors = new List<IOutConnector>(); |
|
44 |
foreach (TransportConfig config in defaultConfig.EnabledTransports) |
|
45 |
{ |
|
46 |
connectors.Add(TransportRegistry.Instance.GetFactory(config.Name).CreateOutConnector<Type>(config.Options, config.Converters.SerializationConverterSelector)); |
|
47 |
} |
|
48 |
// only one transport can be used right now. Actually, only one transport exists right now... |
|
49 |
return new Informer(scope, connectors[0]); |
|
35 | 50 |
} |
36 | 51 | |
37 |
public Informer CreateInformer(string scope) { |
|
52 |
public Informer CreateInformer(string scope) |
|
53 |
{ |
|
38 | 54 |
return CreateInformer(new Scope(scope)); |
39 | 55 |
} |
40 | 56 | |
41 | 57 |
public Listener CreateListener(Scope scope) |
42 | 58 |
{ |
43 | ||
44 |
return new Listener( |
|
45 |
new InPushConnector( |
|
46 |
new BusClientConnection(SocketConfiguration.Hostname, SocketConfiguration.Port), |
|
47 |
scope, |
|
48 |
DefaultConverterRepository.Instance.DeserializationConverterSelector |
|
49 |
)); |
|
59 |
List<IInPushConnector> connectors = new List<IInPushConnector>(); |
|
60 |
foreach (TransportConfig config in defaultConfig.EnabledTransports) |
|
61 |
{ |
|
62 |
IInPushConnector connector = TransportRegistry.Instance.GetFactory(config.Name).CreateInPushConnector<string>(config.Options, config.Converters.DeserializationConverterSelector); |
|
63 |
connector.SetScope(scope); |
|
64 |
connectors.Add(connector); |
|
65 |
} |
|
66 |
// only one transport can be used right now. Actually, only one transport exists right now... |
|
67 |
return new Listener(connectors[0]); |
|
50 | 68 |
} |
51 | 69 | |
52 |
public Listener CreateListener(string scope) { |
|
70 |
public Listener CreateListener(string scope) |
|
71 |
{ |
|
53 | 72 |
return CreateListener(new Scope(scope)); |
54 | 73 |
} |
55 | 74 | |
... | ... | |
77 | 96 |
{ |
78 | 97 |
return CreateLocalServer(new Scope(scope)); |
79 | 98 |
} |
80 | ||
81 | 99 |
} |
82 | 100 |
} |
rsb-cil/Rsb/Informer.cs | ||
---|---|---|
6 | 6 |
{ |
7 | 7 |
public class Informer : IActivatable |
8 | 8 |
{ |
9 | ||
10 |
private IConnector connector; |
|
9 |
private IOutConnector connector; |
|
11 | 10 |
private Guid id = Guid.NewGuid(); |
12 | 11 |
private long sequenceNumber = 1; |
13 | 12 | |
... | ... | |
17 | 16 |
private set; |
18 | 17 |
} |
19 | 18 | |
20 |
public Informer(string scope, IConnector connector) |
|
19 |
public Informer(string scope, IOutConnector connector)
|
|
21 | 20 |
: this(new Scope(scope), connector) |
22 | 21 |
{ |
23 | 22 |
} |
24 | 23 | |
25 |
public Informer(Scope scope, IConnector connector) |
|
24 |
public Informer(Scope scope, IOutConnector connector)
|
|
26 | 25 |
{ |
27 | 26 |
this.Scope = scope; |
28 | 27 |
this.connector = connector; |
rsb-cil/Rsb/Transport/ConnectorInfo.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using System.Collections.Generic; |
|
3 | ||
4 |
namespace Rsb.Transport |
|
5 |
{ |
|
6 |
public class ConnectorInfo |
|
7 |
{ |
|
8 |
public String Name { get; private set; } |
|
9 |
public HashSet<String> Schemas { get; private set; } |
|
10 |
public HashSet<String> Options { get; private set; } |
|
11 |
public bool IsRemote { get; private set; } |
|
12 | ||
13 |
public ConnectorInfo(String name, |
|
14 |
HashSet<String> schemas, |
|
15 |
HashSet<String> options, |
|
16 |
bool remote) |
|
17 |
{ |
|
18 |
this.Name = name; |
|
19 |
this.Schemas = schemas; |
|
20 |
this.Options = options; |
|
21 |
this.IsRemote = remote; |
|
22 |
} |
|
23 |
} |
|
24 |
} |
rsb-cil/Rsb/Transport/IConnector.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using Rsb.Util; |
|
3 |
namespace Rsb.Transport |
|
4 |
{ |
|
5 |
public interface IConnector : IActivatable |
|
6 |
{ |
|
7 |
void Push(Event theEvent); |
|
8 |
} |
|
9 |
} |
rsb-cil/Rsb/Transport/IInPushConnector.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using Rsb.Util; |
|
1 |
using Rsb.Util; |
|
3 | 2 |
namespace Rsb.Transport |
4 | 3 |
{ |
5 | ||
6 | 4 |
public interface IInPushConnector : IActivatable |
7 | 5 |
{ |
8 | ||
9 | 6 |
event NewEventHandler EventReceived; |
10 | 7 | |
11 | 8 |
void SetScope(Scope scope); |
12 | ||
13 | 9 |
} |
14 | 10 |
} |
rsb-cil/Rsb/Transport/IOutConnector.cs | ||
---|---|---|
1 |
using Rsb.Util; |
|
2 |
namespace Rsb.Transport |
|
3 |
{ |
|
4 |
public interface IOutConnector : IActivatable |
|
5 |
{ |
|
6 |
void Push(Event theEvent); |
|
7 |
} |
|
8 |
} |
rsb-cil/Rsb/Transport/ITransportFactory.cs | ||
---|---|---|
1 |
using Rsb.Converter; |
|
2 |
using Rsb.Util; |
|
3 |
using System; |
|
4 | ||
5 |
namespace Rsb.Transport |
|
6 |
{ |
|
7 |
public interface ITransportFactory |
|
8 |
{ |
|
9 |
ConnectorInfo GetInfo(); |
|
10 | ||
11 |
IOutConnector CreateOutConnector<KeyType>(Properties properties, IConverterSelectionStrategy<KeyType> converters); |
|
12 | ||
13 |
IInPushConnector CreateInPushConnector<KeyType>(Properties properties, IConverterSelectionStrategy<KeyType> converters); |
|
14 |
} |
|
15 |
} |
rsb-cil/Rsb/Transport/Socket/BusClientConnection.cs | ||
---|---|---|
11 | 11 |
{ |
12 | 12 |
public class BusClientConnection |
13 | 13 |
{ |
14 | ||
15 | 14 |
private static readonly log4net.ILog LOGGER = log4net.LogManager.GetLogger(typeof(BusClientConnection)); |
16 | 15 | |
17 | 16 |
private static readonly int MESSAGE_LENGTH_SIZE = 4; |
... | ... | |
19 | 18 | |
20 | 19 |
private String host; |
21 | 20 |
private int port; |
21 |
private bool noDelay; |
|
22 | 22 |
private TcpClient client = null; |
23 | 23 |
private NetworkStream stream = null; |
24 | 24 | |
25 |
public BusClientConnection(String host, int port)
|
|
25 |
public BusClientConnection(SocketOptions options)
|
|
26 | 26 |
{ |
27 |
this.host = host; |
|
28 |
this.port = port; |
|
27 |
this.host = options.Host; |
|
28 |
this.port = options.Port; |
|
29 |
this.noDelay = options.TcpNoDelay; |
|
29 | 30 |
} |
30 | 31 | |
31 | 32 |
public void Activate() |
... | ... | |
36 | 37 |
// https://stackoverflow.com/questions/18390715/why-is-the-tcpclient-slower-to-connect-with-parameters-in-the-constructor |
37 | 38 |
this.client = new TcpClient(); |
38 | 39 |
this.client.Connect(host, port); |
39 |
this.client.NoDelay = true;
|
|
40 |
this.client.NoDelay = noDelay;
|
|
40 | 41 |
this.stream = client.GetStream(); |
41 | 42 | |
42 | 43 |
handshake(); |
... | ... | |
109 | 110 |
totalReceived += currentReceived; |
110 | 111 |
} |
111 | 112 |
} |
112 | ||
113 | 113 |
} |
114 | 114 |
} |
rsb-cil/Rsb/Transport/Socket/ServerMode.cs | ||
---|---|---|
1 |
namespace Rsb.Transport.Socket |
|
2 |
{ |
|
3 |
public enum ServerMode |
|
4 |
{ |
|
5 |
YES, |
|
6 |
NO, |
|
7 |
AUTO |
|
8 |
} |
|
9 |
} |
rsb-cil/Rsb/Transport/Socket/SocketConfiguration.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using System.Collections.Generic; |
|
3 |
using System.Linq; |
|
4 |
using System.Text; |
|
5 |
using System.Threading.Tasks; |
|
6 | ||
7 |
namespace Rsb.Transport.Socket |
|
8 |
{ |
|
9 |
public static class SocketConfiguration |
|
10 |
{ |
|
11 |
public static int Port = 55555; |
|
12 |
public static string Hostname = "localhost"; |
|
13 |
} |
|
14 |
} |
rsb-cil/Rsb/Transport/Socket/SocketFactory.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using System.Collections.Generic; |
|
3 |
using Rsb.Converter; |
|
4 |
using Rsb.Util; |
|
5 | ||
6 |
namespace Rsb.Transport.Socket |
|
7 |
{ |
|
8 |
public class SocketFactory : ITransportFactory |
|
9 |
{ |
|
10 |
private static readonly String SCHEMA = "socket"; |
|
11 | ||
12 |
private static readonly String SERVER_MODE_NO = "0"; |
|
13 |
private static readonly String SERVER_MODE_YES = "1"; |
|
14 |
private static readonly String SERVER_MODE_AUTO = "auto"; |
|
15 | ||
16 |
private static readonly String PORT_KEY = "transport.socket.port"; |
|
17 |
private static readonly int DEFAULT_PORT = 55555; |
|
18 |
private static readonly String HOST_KEY = "transport.socket.host"; |
|
19 |
private static readonly String DEFAULT_HOST = "localhost"; |
|
20 |
private static readonly String NODELAY_KEY = "transport.socket.tcpnodelay"; |
|
21 |
private static readonly bool DEFAULT_NODELAY = true; |
|
22 |
private static readonly String SERVER_MODE_KEY = "transport.socket.server"; |
|
23 |
private static readonly String DEFAULT_SERVER_MODE = SERVER_MODE_NO; |
|
24 | ||
25 |
public IInPushConnector CreateInPushConnector<KeyType>(Properties properties, IConverterSelectionStrategy<KeyType> converters) |
|
26 |
{ |
|
27 |
ServerMode mode = ParseServerMode(properties); |
|
28 |
return new SocketInPushConnector( |
|
29 |
new BusClientConnection(ParseSocketOptions(properties)), (IConverterSelectionStrategy<string>)converters); |
|
30 |
} |
|
31 | ||
32 |
public IOutConnector CreateOutConnector<KeyType>(Properties properties, IConverterSelectionStrategy<KeyType> converters) |
|
33 |
{ |
|
34 |
return new SocketOutConnector(new BusClientConnection(ParseSocketOptions(properties)), (IConverterSelectionStrategy<Type>)converters); |
|
35 |
} |
|
36 | ||
37 |
public ConnectorInfo GetInfo() |
|
38 |
{ |
|
39 |
HashSet<String> schemas = new HashSet<String> |
|
40 |
{ |
|
41 |
SCHEMA |
|
42 |
}; |
|
43 |
HashSet<String> options = new HashSet<String> |
|
44 |
{ |
|
45 |
"host", |
|
46 |
"port", |
|
47 |
"server", |
|
48 |
"tcpnodelay" |
|
49 |
}; |
|
50 |
return new ConnectorInfo(SCHEMA, schemas, options, true); |
|
51 |
} |
|
52 | ||
53 |
private SocketOptions ParseSocketOptions(Properties properties) |
|
54 |
{ |
|
55 |
int port = properties.GetProperty(PORT_KEY, DEFAULT_PORT).AsInteger(); |
|
56 |
if (port < 0) |
|
57 |
{ |
|
58 |
throw new ArgumentException("Port must be a number >= 0"); |
|
59 |
} |
|
60 |
String address = properties.GetProperty(HOST_KEY, DEFAULT_HOST).AsString(); |
|
61 |
bool tcpNoDelay = properties.GetProperty(NODELAY_KEY, DEFAULT_NODELAY).AsBoolean(); |
|
62 | ||
63 |
return new SocketOptions(address, port, tcpNoDelay); |
|
64 |
} |
|
65 | ||
66 |
private ServerMode ParseServerMode(Properties properties) |
|
67 |
{ |
|
68 |
String serverModeString = |
|
69 |
properties.GetProperty(SERVER_MODE_KEY, DEFAULT_SERVER_MODE) |
|
70 |
.AsString(); |
|
71 |
ServerMode serverMode; |
|
72 | ||
73 |
if (SERVER_MODE_NO.Equals(serverModeString)) |
|
74 |
{ |
|
75 |
serverMode = ServerMode.NO; |
|
76 |
} |
|
77 |
/* NOT IMPLEMENTED YET |
|
78 |
else if (SERVER_MODE_AUTO.Equals(serverModeString)) |
|
79 |
{ |
|
80 |
serverMode = ServerMode.AUTO; |
|
81 |
} |
|
82 |
else if (SERVER_MODE_YES.Equals(serverModeString)) |
|
83 |
{ |
|
84 |
serverMode = ServerMode.YES; |
|
85 |
} |
|
86 |
*/ |
|
87 |
else |
|
88 |
{ |
|
89 |
throw new NotSupportedException(String.Format( |
|
90 |
"Unsupported server mode '{0}'", serverModeString)); |
|
91 |
} |
|
92 | ||
93 |
return serverMode; |
|
94 |
} |
|
95 |
} |
|
96 |
} |
rsb-cil/Rsb/Transport/Socket/SocketInPushConnector.cs | ||
---|---|---|
6 | 6 |
using Rsb.Protocol; |
7 | 7 |
namespace Rsb.Transport.Socket |
8 | 8 |
{ |
9 |
public class InPushConnector : IInPushConnector |
|
9 |
/** |
|
10 |
* ServerMode will not be evaluated. |
|
11 |
* Server mode does actually not exist! |
|
12 |
*/ |
|
13 |
public class SocketInPushConnector : IInPushConnector |
|
10 | 14 |
{ |
11 |
private static readonly log4net.ILog LOGGER = log4net.LogManager.GetLogger(typeof(InPushConnector)); |
|
15 |
private static readonly log4net.ILog LOGGER = log4net.LogManager.GetLogger(typeof(SocketInPushConnector));
|
|
12 | 16 | |
13 | 17 |
private BusClientConnection connection; |
14 |
private Scope scope;
|
|
18 |
private Scope scope = new Scope("/"); // default
|
|
15 | 19 |
private Thread thread; |
16 | 20 |
private volatile bool interrupted = false; |
17 | 21 |
private IConverterSelectionStrategy<string> converters; |
18 | 22 | |
19 | ||
20 |
public InPushConnector(BusClientConnection connection, Scope scope, IConverterSelectionStrategy<string> inConverters) |
|
23 |
public SocketInPushConnector(BusClientConnection connection, IConverterSelectionStrategy<string> inConverters) |
|
21 | 24 |
{ |
22 | 25 |
this.connection = connection; |
23 |
this.scope = scope; |
|
24 | 26 |
this.converters = inConverters; |
27 |
//serverMode ignored |
|
25 | 28 |
} |
26 | 29 | |
27 | 30 |
public event NewEventHandler EventReceived; |
... | ... | |
90 | 93 |
} |
91 | 94 |
} |
92 | 95 |
} |
93 | ||
94 | 96 |
} |
95 | 97 |
} |
rsb-cil/Rsb/Transport/Socket/SocketOption.cs | ||
---|---|---|
1 |
using System; |
|
2 | ||
3 |
namespace Rsb.Transport.Socket |
|
4 |
{ |
|
5 |
public class SocketOptions |
|
6 |
{ |
|
7 |
public String Host { get; set; } |
|
8 |
public int Port { get; set; } |
|
9 |
public bool TcpNoDelay { get; set; } |
|
10 | ||
11 |
public SocketOptions(String host, int port, bool tcpNoDelay) |
|
12 |
{ |
|
13 |
this.Host = host; |
|
14 |
this.Port = port; |
|
15 |
this.TcpNoDelay = tcpNoDelay; |
|
16 |
} |
|
17 |
} |
|
18 |
} |
rsb-cil/Rsb/Transport/Socket/SocketOutConnector.cs | ||
---|---|---|
6 | 6 | |
7 | 7 |
namespace Rsb.Transport.Socket |
8 | 8 |
{ |
9 |
public class OutConnector : IConnector |
|
9 |
/** |
|
10 |
* ServerMode will not be evaluated. |
|
11 |
* Server mode does actually not exist! |
|
12 |
*/ |
|
13 |
public class SocketOutConnector : IOutConnector |
|
10 | 14 |
{ |
11 | ||
12 |
private static readonly log4net.ILog LOGGER = log4net.LogManager.GetLogger(typeof(OutConnector)); |
|
15 |
private static readonly log4net.ILog LOGGER = log4net.LogManager.GetLogger(typeof(SocketOutConnector)); |
|
13 | 16 | |
14 | 17 |
private Thread thread; |
15 | 18 |
private volatile bool deactivating = false; |
... | ... | |
17 | 20 |
private BusClientConnection connection; |
18 | 21 |
private IConverterSelectionStrategy<Type> outConverters; |
19 | 22 | |
20 |
public OutConnector(BusClientConnection connection, IConverterSelectionStrategy<Type> outConverters) |
|
23 |
public SocketOutConnector(BusClientConnection connection, IConverterSelectionStrategy<Type> outConverters)
|
|
21 | 24 |
{ |
22 | 25 |
this.connection = connection; |
23 | 26 |
this.outConverters = outConverters; |
... | ... | |
74 | 77 |
} |
75 | 78 |
LOGGER.Debug("Dummy receiver terminated"); |
76 | 79 |
} |
77 | ||
78 | 80 |
} |
79 | 81 |
} |
rsb-cil/Rsb/Transport/TransportRegistry.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using System.Collections.Generic; |
|
3 |
using System.Linq; |
|
4 |
namespace Rsb.Transport |
|
5 |
{ |
|
6 |
public class TransportRegistry |
|
7 |
{ |
|
8 |
private static readonly TransportRegistry instance = new TransportRegistry(); |
|
9 | ||
10 |
private Dictionary<String, ITransportFactory> factories = new Dictionary<string, ITransportFactory>(); |
|
11 | ||
12 |
public List<String> AvailableTransportNames |
|
13 |
{ |
|
14 |
get |
|
15 |
{ |
|
16 |
return factories.Keys.ToList(); |
|
17 |
} |
|
18 |
} |
|
19 | ||
20 |
// Explicit static constructor to tell C# compiler |
|
21 |
// not to mark type as beforefieldinit |
|
22 |
static TransportRegistry() |
|
23 |
{ |
|
24 |
} |
|
25 | ||
26 |
private TransportRegistry() |
|
27 |
{ |
|
28 |
} |
|
29 | ||
30 |
public static TransportRegistry Instance |
|
31 |
{ |
|
32 |
get |
|
33 |
{ |
|
34 |
return instance; |
|
35 |
} |
|
36 |
} |
|
37 | ||
38 |
public bool HasTransport(String name) |
|
39 |
{ |
|
40 |
return factories.ContainsKey(name); |
|
41 |
} |
|
42 | ||
43 |
public ITransportFactory GetFactory(String name) |
|
44 |
{ |
|
45 |
if (!factories.ContainsKey(name)) |
|
46 |
{ |
|
47 |
throw new ArgumentException("No transport with name '" + name + "' available."); |
|
48 |
} |
|
49 |
return factories[name]; |
|
50 |
} |
|
51 | ||
52 |
public void RegisterTransport(String name, ITransportFactory factory) |
|
53 |
{ |
|
54 |
lock (factories) |
|
55 |
{ |
|
56 |
if (String.IsNullOrEmpty(name)) |
|
57 |
{ |
|
58 |
throw new ArgumentException("Transport name must not be null or empty."); |
|
59 |
} |
|
60 |
if (factories.ContainsKey(name)) |
|
61 |
{ |
|
62 |
throw new ArgumentNullException("There is already a transport with name '" + name + "'."); |
|
63 |
} |
|
64 |
if (factory == null) |
|
65 |
{ |
|
66 |
throw new ArgumentNullException("Factory instance must not be null."); |
|
67 |
} |
|
68 | ||
69 |
factories.Add(name, factory); |
|
70 |
} |
|
71 |
} |
|
72 |
} |
|
73 |
} |
rsb-cil/Rsb/Util/ConfigLoader.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using System.Collections.Generic; |
|
3 |
using System.IO; |
|
4 |
using System.Linq; |
|
5 |
using System.Text; |
|
6 |
using System.Threading.Tasks; |
|
7 | ||
8 |
namespace Rsb.Util |
|
9 |
{ |
|
10 |
public class ConfigLoader |
|
11 |
{ |
|
12 |
private static readonly String CONFIG_DEBUG_VARIABLE = "RSB_CONFIG_DEBUG"; |
|
13 | ||
14 |
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfigLoader)); |
|
15 | ||
16 |
private static void WriteDebug1(String output, params object[] refs) |
|
17 |
{ |
|
18 |
Console.WriteLine(" " + output, refs); |
|
19 |
} |
|
20 | ||
21 |
private static void WriteDebug2(String output, params object[] refs) |
|
22 |
{ |
|
23 |
Console.WriteLine(" " + output, refs); |
|
24 |
} |
|
25 | ||
26 |
private static readonly String CONFIG_FILES_VARIABLE = "RSB_CONFIG_FILES"; |
|
27 | ||
28 |
// const - to be able to be used in switch causes |
|
29 |
// const can't be static |
|
30 |
private const String CONFIG_FILE_KEY_SYSTEM = "%system"; |
|
31 |
private const String CONFIG_FILE_KEY_PREFIX = "%prefix"; |
|
32 |
private const String CONFIG_FILE_KEY_USER = "%user"; |
|
33 |
private const String CONFIG_FILE_KEY_PWD = "%pwd"; |
|
34 | ||
35 |
private static readonly String ENV_SEPARATOR = "_"; |
|
36 |
private static readonly String KEY_SEPARATOR = "."; |
|
37 | ||
38 |
private static readonly String ALL_USER = @"\Users\Public"; |
|
39 |
private static readonly String CONFIG_DIRECTORY = ".config"; // C# is more a win thing, thus instead of */etc/*, *\.config\* is considered |
|
40 |
private static readonly String CONFIG_FILE_NAME = "rsb.conf"; |
|
41 | ||
42 |
private List<String> configFilePaths = new List<String>(new String[] { |
|
43 |
CONFIG_FILE_KEY_SYSTEM, |
|
44 |
CONFIG_FILE_KEY_USER, |
|
45 |
CONFIG_FILE_KEY_PWD |
|
46 |
}.AsEnumerable()); |
|
47 | ||
48 |
private List<String> readFiles = new List<String>(); |
|
49 | ||
50 |
private string prefix; |
|
51 |
private string root; |
|
52 |
private string environmentPrefix; |
|
53 |
private bool debug; |
|
54 | ||
55 |
public ConfigLoader(String systemPrefix, String environmentPrefix) |
|
56 |
{ |
|
57 |
String customPaths = Environment.GetEnvironmentVariable(CONFIG_FILES_VARIABLE); |
|
58 |
if (customPaths != null) |
|
59 |
{ |
|
60 |
configFilePaths = (List<String>)customPaths.Split(':').AsEnumerable(); |
|
61 |
} |
|
62 | ||
63 |
this.root = Environment.GetEnvironmentVariable("HOMEDRIVE"); |
|
64 |
this.prefix = systemPrefix; |
|
65 |
this.environmentPrefix = environmentPrefix; |
|
66 |
this.debug = (Environment.GetEnvironmentVariable(CONFIG_DEBUG_VARIABLE) != null); |
|
67 |
} |
|
68 | ||
69 |
public ConfigLoader() : this("\\", "RSB_") |
|
70 |
{ |
|
71 |
} |
|
72 | ||
73 |
public Properties Load(Properties properties) |
|
74 |
{ |
|
75 |
LOG.DebugFormat("Loading properties into {0}", properties); |
|
76 | ||
77 |
this.LoadFiles(properties); |
|
78 |
this.LoadEnv(properties); |
|
79 |
return properties; |
|
80 |
} |
|
81 | ||
82 |
private void LoadFiles(Properties properties) |
|
83 |
{ |
|
84 |
LOG.DebugFormat("Loading properties for config files into {0}", properties); |
|
85 | ||
86 |
if (this.debug) |
|
87 |
{ |
|
88 |
WriteDebug1("1. Configuration files"); |
|
89 |
} |
|
90 |
int index = 1; |
|
91 |
readFiles.Clear(); |
|
92 |
foreach (String path in configFilePaths) |
|
93 |
{ |
|
94 |
ResolveAndLoadFile(index++, path, properties); |
|
95 |
} |
|
96 |
} |
|
97 | ||
98 |
private void ResolveAndLoadFile(int index, String path, Properties properties) |
|
99 |
{ |
|
100 |
switch (path) |
|
101 |
{ |
|
102 |
case CONFIG_FILE_KEY_SYSTEM: |
|
103 |
LoadFile(index, |
|
104 |
Path.GetFullPath(Path.Combine(root, ALL_USER, CONFIG_DIRECTORY, CONFIG_FILE_NAME)), |
|
105 |
"System wide config file", |
|
106 |
properties); |
|
107 |
break; |
|
108 |
case CONFIG_FILE_KEY_PREFIX: |
|
109 |
LoadFile(index, |
|
110 |
Path.GetFullPath(Path.Combine(root, prefix, CONFIG_DIRECTORY, CONFIG_FILE_NAME)), |
|
111 |
"Prefix wide config file", |
|
112 |
properties); |
|
113 |
break; |
|
114 |
case CONFIG_FILE_KEY_USER: |
|
115 |
LoadFile(index, |
|
116 |
Path.GetFullPath(Path.Combine(root, Environment.GetEnvironmentVariable("HOMEPATH"), CONFIG_DIRECTORY, CONFIG_FILE_NAME)), |
|
117 |
"User config file", |
|
118 |
properties); |
|
119 |
break; |
|
120 |
case CONFIG_FILE_KEY_PWD: |
|
121 |
LoadFile(index, |
|
122 |
Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), CONFIG_FILE_NAME)), |
|
123 |
"Current directory file", |
|
124 |
properties); |
|
125 |
break; |
|
126 |
default: |
|
127 |
LoadFile(index, |
|
128 |
path, |
|
129 |
"User specified config file", |
|
130 |
properties); |
|
131 |
break; |
|
132 |
} |
|
133 |
} |
|
134 | ||
135 |
private Properties LoadFile(int index, String path, String description, Properties properties) |
|
136 |
{ |
|
137 |
LOG.DebugFormat("Loading properties from {0} into {1} if available", path, properties); |
|
138 | ||
139 |
try |
|
140 |
{ |
|
141 |
bool exists = File.Exists(path); |
|
142 |
bool read = readFiles.Contains(path); |
|
143 | ||
144 |
if (this.debug) |
|
145 |
{ |
|
146 |
WriteDebug2("{0}. {1} \"{2}\" {3}", index, description, path, exists ? ("exists" + (read ? " and is already read" : "")) : "does not exist"); |
|
147 |
} |
|
148 | ||
149 |
if (exists) |
|
150 |
{ |
|
151 |
LOG.DebugFormat("{0} does exist, loading.", path); |
|
152 |
if (!read) |
|
153 |
{ |
|
154 |
this.LoadFile(path, properties); |
|
155 |
} |
|
156 |
} |
|
157 |
} |
|
158 |
catch (IOException ex) |
|
159 |
{ |
|
160 |
LOG.Error(String.Format("Caught IOException trying to read {0}.", path), ex); |
|
161 |
} |
|
162 |
return properties; |
|
163 |
} |
|
164 | ||
165 |
private Properties LoadFile(string path, Properties properties) |
|
166 |
{ |
|
167 |
LOG.DebugFormat("Loading properties from file {0} into {1}", path, properties); |
|
168 | ||
169 |
StreamReader reader = new StreamReader(path); |
|
170 | ||
171 |
try |
|
172 |
{ |
|
173 |
String section = ""; |
|
174 |
while (!reader.EndOfStream) |
|
175 |
{ |
|
176 |
String line = reader.ReadLine(); |
|
177 |
int index = line.IndexOf('#'); |
|
178 |
if (index != -1) |
|
179 |
{ |
|
180 |
line = line.Substring(0, index); |
|
181 |
} |
|
182 |
line = line.Trim(); |
|
183 |
if ("".Equals(line)) |
|
184 |
{ |
|
185 |
continue; |
|
186 |
} |
|
187 |
if (line.StartsWith("[") && line.EndsWith("]")) |
|
188 |
{ |
|
189 |
section = line.Substring(1, line.Length - 2); |
|
190 |
continue; |
|
191 |
} |
|
192 |
index = line.IndexOf('='); |
|
193 |
if (index == -1) |
|
194 |
{ |
|
195 |
LOG.WarnFormat("Illegal line in configuration file: `{0}`", line); |
|
196 |
continue; |
|
197 |
} |
|
198 |
String key = |
|
199 |
section + KEY_SEPARATOR |
|
200 |
+ line.Substring(0, index).Trim(); |
|
201 |
String value = line.Substring(index + 1).Trim(); |
|
202 |
LOG.DebugFormat("Parsed key {0} to be {1}. Setting in result object.", key, value); |
|
203 |
properties.SetProperty(key, value); |
|
204 |
} |
|
205 |
} |
|
206 |
finally |
|
207 |
{ |
|
208 |
reader.Close(); |
|
209 |
readFiles.Add(path); |
|
210 |
} |
|
211 | ||
212 |
return properties; |
|
213 |
} |
|
214 | ||
215 |
private Properties LoadEnv(Properties properties) |
|
216 |
{ |
|
217 |
LOG.DebugFormat("Loading properties from environment into {0}", properties); |
|
218 |
if (this.debug) |
|
219 |
{ |
|
220 |
WriteDebug1("2. Environment variables with prefix RSB_"); |
|
221 |
} |
|
222 | ||
223 |
foreach (var keyRaw in Environment.GetEnvironmentVariables().Keys) |
|
224 |
{ |
|
225 |
String key = (String)keyRaw; |
|
226 | ||
227 |
if (key.StartsWith(this.environmentPrefix)) |
|
228 |
{ |
|
229 |
String value = Environment.GetEnvironmentVariable(key); |
|
230 |
String propsKey = |
|
231 |
key.Substring(this.environmentPrefix.Length) |
|
232 |
.Replace(ENV_SEPARATOR, KEY_SEPARATOR).ToLower(new System.Globalization.CultureInfo("us-US")); |
|
233 |
if (this.debug) |
|
234 |
{ |
|
235 |
WriteDebug2("{0} (mapped to {1}) -> {2}", key, propsKey, value); |
|
236 |
} |
|
237 |
LOG.DebugFormat("Parsed from map: {0} = {1}", propsKey, value); |
|
238 |
properties.SetProperty(propsKey, value); |
|
239 |
} |
|
240 |
} |
|
241 | ||
242 |
return properties; |
|
243 |
} |
|
244 |
} |
|
245 |
} |
rsb-cil/Rsb/Util/Properties.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using System.Collections.Generic; |
|
3 |
using System.Text; |
|
4 | ||
5 |
namespace Rsb.Util |
|
6 |
{ |
|
7 |
public class Properties |
|
8 |
{ |
|
9 |
private Dictionary<String, Property> propertiesByName = |
|
10 |
new Dictionary<String, Property>(); |
|
11 | ||
12 |
public Properties() |
|
13 |
{ |
|
14 |
} |
|
15 | ||
16 |
public void Reset() |
|
17 |
{ |
|
18 |
propertiesByName.Clear(); |
|
19 |
} |
|
20 | ||
21 |
public Property GetProperty(String key) |
|
22 |
{ |
|
23 |
if (this.propertiesByName.ContainsKey(key)) |
|
24 |
{ |
|
25 |
return this.propertiesByName[key]; |
|
26 |
} |
|
27 |
else |
|
28 |
{ |
|
29 |
throw new ArgumentException( |
|
30 |
"Trying to get unknown property '" + key |
|
31 |
+ "' in Properties.getProperty()"); |
|
32 |
} |
|
33 |
} |
|
34 | ||
35 |
public Property GetProperty<TargetType>(String key, TargetType defaultValue) |
|
36 |
{ |
|
37 |
try |
|
38 |
{ |
|
39 |
return GetProperty(key); |
|
40 |
} |
|
41 |
catch (ArgumentException e) |
|
42 |
{ |
|
43 |
return new Property(defaultValue.ToString()); |
|
44 |
} |
|
45 |
} |
|
46 | ||
47 |
public void SetProperty(String key, String value) |
|
48 |
{ |
|
49 |
this.propertiesByName[key.Trim()] = new Property(value); |
|
50 |
} |
|
51 | ||
52 |
public HashSet<String> GetAvailableKeys() |
|
53 |
{ |
|
54 |
return new HashSet<String>(this.propertiesByName.Keys); |
|
55 |
} |
|
56 | ||
57 |
public bool HasProperty(String key) |
|
58 |
{ |
|
59 |
return this.propertiesByName.ContainsKey(key); |
|
60 |
} |
|
61 | ||
62 |
public Properties Filter(String desiredPrefix) |
|
63 |
{ |
|
64 |
Properties filtered = new Properties(); |
|
65 |
foreach (String key in this.propertiesByName.Keys) |
|
66 |
{ |
|
67 |
if (key.Equals(desiredPrefix) |
|
68 |
|| key.StartsWith(desiredPrefix + ".")) |
|
69 |
{ |
|
70 |
filtered.SetProperty(key, propertiesByName[key].AsString()); |
|
71 |
} |
|
72 |
} |
|
73 |
return filtered; |
|
74 |
} |
|
75 | ||
76 |
public void Remove(IEnumerable<String> keys) |
|
77 |
{ |
|
78 |
foreach (String key in keys) |
|
79 |
{ |
|
80 |
this.propertiesByName.Remove(key); |
|
81 |
} |
|
82 |
} |
|
83 | ||
84 |
public void Remove(String key) |
|
85 |
{ |
|
86 |
this.propertiesByName.Remove(key); |
|
87 |
} |
|
88 | ||
89 |
public void Merge(Properties properties) |
|
90 |
{ |
|
91 |
foreach (String key in properties.propertiesByName.Keys) |
|
92 |
{ |
|
93 |
this.propertiesByName[key] = new Property(properties.propertiesByName[key].AsString()); |
|
94 |
} |
|
95 |
} |
|
96 | ||
97 |
/* |
|
98 |
public Iterator<Entry<String, Property>> iterator() |
|
99 |
{ |
|
100 |
return this.propertiesByName.entrySet().iterator(); |
|
101 |
}*/ |
|
102 | ||
103 |
public override String ToString() |
|
104 |
{ |
|
105 |
StringBuilder builder = new StringBuilder(); |
|
106 |
builder.Append(this.GetType().Name); |
|
107 |
builder.Append("["); |
|
108 |
foreach (var k in propertiesByName.Keys) |
|
109 |
{ |
|
110 |
builder.Append(k); |
|
111 |
builder.Append("="); |
|
112 |
builder.Append(propertiesByName[k]); |
|
113 |
builder.Append(";"); |
|
114 |
} |
|
115 |
builder.Append(']'); |
|
116 | ||
117 |
return builder.ToString(); |
|
118 |
} |
|
119 | ||
120 |
public override int GetHashCode() |
|
121 |
{ |
|
122 |
int prime = 31; |
|
123 |
int result = 1; |
|
124 |
result = |
|
125 |
prime |
|
126 |
* result |