1 package org.lsst.ccs.bus.mock;
2
3 import org.lsst.ccs.bus.*;
4 import org.lsst.ccs.utilities.dispatch.CommandFor;
5 import org.lsst.ccs.utilities.dispatch.ParallelCommandDispatcher;
6
7 import java.io.IOException;
8 import java.util.ArrayList;
9 import java.util.Arrays;
10 import java.util.HashMap;
11 import java.util.List;
12
13
14
15 public class MockBusMessagingLayer implements BusMessagingLayer {
16
17
18
19 static class BusRegistry {
20 ArrayList<String>[] registry;
21
22 BusRegistry() {
23 Bus[] buses = Bus.values();
24 registry = new ArrayList[buses.length];
25 for (int ix = 0; ix < registry.length; ix++) {
26 registry[ix] = new ArrayList<String>();
27 }
28 }
29
30 }
31
32 static class AgentBehaviour {
33 ParallelCommandDispatcher[] dispatchers;
34
35 AgentBehaviour() {
36 Bus[] buses = Bus.values();
37 dispatchers = new ParallelCommandDispatcher[buses.length];
38
39
40
41
42
43
44 }
45
46 }
47
48 private static final HashMap<String, AgentBehaviour> agentMap = new HashMap<String, AgentBehaviour>();
49 private static final BusRegistry busRegistry = new BusRegistry();
50 private volatile boolean isClosed = false;
51
52 private static final BusMembershipListener[] membershipListeners = new BusMembershipListener[Bus.values().length];
53 private static final Object lock = new Object();
54
55 private boolean single ;
56
57
58 public MockBusMessagingLayer() {
59
60 }
61
62 public MockBusMessagingLayer(boolean single) {
63 this.single = single ;
64 }
65
66 @Override
67 public void register(String agentName, Bus... buses) {
68
69
70
71 if(isClosed) {isClosed = false ;}
72
73 if ((agentName == null) || ("".equals(agentName))) {
74 agentName = ANONYMOUS_AGENT;
75 }
76
77 if (buses.length == 0) {
78 buses = Bus.values();
79 }
80 synchronized (lock) {
81 AgentBehaviour behaviour = agentMap.get(agentName);
82 if (behaviour == null) {
83 behaviour = new AgentBehaviour();
84 agentMap.put(agentName, behaviour);
85 } else {
86
87
88 }
89 for (Bus bus : buses) {
90 int index = bus.ordinal();
91 busRegistry.registry[index].add(agentName);
92
93 BusMembershipListener listener = membershipListeners[index];
94 if (listener != null) {
95 listener.connecting(agentName, "");
96 }
97 if (null == behaviour.dispatchers[index]) {
98 behaviour.dispatchers[index] = new ParallelCommandDispatcher(single);
99 }
100 }
101 }
102 }
103
104 @Override
105 public void closeFor(String agentName, Bus... buses) {
106
107 if (isClosed) return;
108
109
110
111 if ((agentName == null) || ("".equals(agentName))) {
112 agentName = ANONYMOUS_AGENT;
113 }
114
115 if (buses.length == 0) {
116 buses = Bus.values();
117 }
118 synchronized (lock) {
119 AgentBehaviour behaviour = agentMap.get(agentName);
120 for (Bus bus : buses) {
121 int index = bus.ordinal();
122 busRegistry.registry[index].remove(agentName);
123 BusMembershipListener listener = membershipListeners[index];
124 if (listener != null) {
125 listener.disconnecting(agentName, "");
126 }
127 if (behaviour != null) {
128 behaviour.dispatchers[index] = null;
129 }
130 }
131 }
132 }
133
134 @Override
135 public void close() throws IOException {
136
137 isClosed = true;
138 }
139
140
141 @Override
142 public synchronized <T extends BusPayload> void sendMessage(String senderAgent, Bus<T> bus, final T message, String... destinations) throws IOException {
143 if (bus == null) throw new IllegalArgumentException("null bus");
144 if (message == null) throw new IllegalArgumentException("null message");
145 synchronized (lock) {
146
147 ArrayList<String> busAgents = busRegistry.registry[bus.ordinal()];
148 if (!busAgents.contains(senderAgent)) {
149 throw new IllegalArgumentException("agent " + senderAgent + "not registered on " + bus);
150 }
151 if (destinations.length == 0 || "".equals(destinations[0]) || "*".equals(destinations[0])) {
152
153 int index = bus.ordinal();
154 destinations = (busRegistry.registry[index]).toArray(destinations);
155 } else {
156 int length = destinations.length;
157 destinations = Arrays.copyOf(destinations, length + 1);
158 destinations[length] = ANONYMOUS_AGENT;
159
160 }
161 CommandFor<BusMessageForwarder> cmdMessage = new CommandFor<BusMessageForwarder>() {
162 @Override
163 public void invokeOn(BusMessageForwarder instance) {
164 instance.update((BusMessage) message);
165 }
166 };
167
168 List<String> failed = new ArrayList<String>();
169 for (String destination : destinations) {
170 AgentBehaviour behaviour = agentMap.get(destination);
171 if (behaviour == null) {
172 if (!destination.equals(ANONYMOUS_AGENT)) {
173 failed.add(destination);
174 }
175 continue;
176
177
178 }
179 int index = bus.ordinal();
180 ParallelCommandDispatcher dispatcher = behaviour.dispatchers[index];
181 if (dispatcher == null) {
182
183 if (!destination.equals(ANONYMOUS_AGENT)) {
184 failed.add(destination);
185 }
186
187
188 continue;
189 }
190 dispatcher.dispatchCommand(cmdMessage);
191 }
192 if (failed.size() != 0) {
193 throw new DestinationsException(failed.toArray());
194 }
195 }
196
197 }
198
199 @Override
200 public void addMessageListener(String agentName, BusMessageForwarder forwarder, Bus... buses) {
201 if (forwarder == null) throw new IllegalArgumentException("null forwarder");
202
203
204 if (isClosed) return;
205
206 if ((agentName == null) || ("".equals(agentName))) {
207 agentName = ANONYMOUS_AGENT;
208 }
209
210 if (buses.length == 0) {
211 buses = Bus.values();
212 }
213 synchronized (lock) {
214 AgentBehaviour behaviour = agentMap.get(agentName);
215 if (behaviour == null) {
216 throw new IllegalArgumentException("agent with no registration");
217 }
218
219 for (Bus bus : buses) {
220 int index = bus.ordinal();
221 ParallelCommandDispatcher dispatcher = behaviour.dispatchers[index];
222 if (dispatcher == null) {
223 throw new IllegalArgumentException(agentName + " not registered with " + bus);
224 }
225 dispatcher.addExecutant(forwarder);
226 }
227 }
228
229 }
230
231 @Override
232 public void removeMessageListener(String agentName, BusMessageForwarder forwarder, Bus... buses) {
233 if (forwarder == null) throw new IllegalArgumentException("null forwarder");
234
235
236 if (isClosed) return;
237
238 if ((agentName == null) || ("".equals(agentName))) {
239 agentName = ANONYMOUS_AGENT;
240 }
241
242 if (buses.length == 0) {
243 buses = Bus.values();
244 }
245 synchronized (lock) {
246 AgentBehaviour behaviour = agentMap.get(agentName);
247 if (behaviour == null) {
248 return;
249 }
250
251 for (Bus bus : buses) {
252 int index = bus.ordinal();
253 ParallelCommandDispatcher dispatcher = behaviour.dispatchers[index];
254 if (dispatcher == null) {
255 return;
256 }
257 dispatcher.removeExecutant(forwarder);
258 }
259 }
260 }
261
262 @Override
263 public void setMembershipListener(BusMembershipListener listener, Bus... buses) {
264 if (buses == null || buses.length == 0) {
265 buses = Bus.values();
266 }
267 synchronized (lock) {
268 for (Bus bus : buses) {
269 membershipListeners[bus.ordinal()] = listener;
270 }
271 }
272 }
273
274 @Override
275 public List<String> getConnectedNames(Bus bus) {
276 int index = bus.ordinal();
277 return busRegistry.registry[index];
278 }
279 }