1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.indi.server;
19
20 import java.io.IOException;
21 import java.io.PipedInputStream;
22 import java.io.PipedOutputStream;
23 import java.nio.ByteBuffer;
24 import java.nio.channels.ReadableByteChannel;
25 import java.nio.channels.SelectableChannel;
26 import java.nio.channels.SelectionKey;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.Queue;
30
31 import javax.xml.parsers.ParserConfigurationException;
32 import javax.xml.parsers.SAXParser;
33 import javax.xml.parsers.SAXParserFactory;
34
35 import org.indi.clientmessages.BlobEnable;
36 import org.indi.clientmessages.EnableBlob;
37 import org.indi.clientmessages.GetProperties;
38 import org.indi.objects.BlobVector;
39 import org.indi.objects.Message;
40 import org.indi.objects.TransferType;
41 import org.indi.objects.Vector;
42 import org.indi.reactor.OutputQueue;
43 import org.indi.reactor.Reactor;
44 import org.xml.sax.SAXException;
45
46
47
48
49
50
51
52
53 class BlobEnabler {
54
55
56
57 public BlobEnable defaults;
58
59
60
61 public Map<String, BlobEnable> specific;
62
63
64
65
66
67 public BlobEnabler() {
68 this.specific = new HashMap<String, BlobEnable>();
69 this.defaults = BlobEnable.Never;
70 }
71 }
72
73
74
75
76
77
78
79 public class ClientHandler extends OutputQueue implements Runnable {
80
81
82
83 private final PipedInputStream fromClient;
84
85
86
87 private final PipedOutputStream toThread;
88
89
90
91 private Queue<java.lang.Object> threadToDriverQueue;
92
93
94
95 private final SAXParser parser;
96
97
98
99 private Map<String, BlobEnabler> blobEnableMap = null;
100
101
102
103 private String device = null;
104
105
106
107 private boolean allDevices = false;
108
109
110
111 BlobEnable defaults = BlobEnable.Never;
112
113
114
115
116
117
118
119
120
121
122
123
124 public ClientHandler(Reactor r, SelectableChannel ch) throws IOException,
125 ParserConfigurationException, SAXException {
126 super(r, ch);
127 this.fromClient = new PipedInputStream();
128 this.toThread = new PipedOutputStream(this.fromClient);
129 this.toThread.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?> <doc>"
130 .getBytes());
131 this.parser = SAXParserFactory.newInstance().newSAXParser();
132 this.blobEnableMap = new HashMap<String, BlobEnabler>();
133 }
134
135
136
137
138
139
140
141 public void setQueue(Queue<java.lang.Object> queue) {
142 this.threadToDriverQueue = queue;
143 (new Thread(this)).start();
144 }
145
146
147
148
149 public void run() {
150 SaxHandler h = new SaxHandler(this.threadToDriverQueue, this);
151 try {
152 this.parser.parse(this.fromClient, h);
153 } catch (SAXException e) {
154 e.printStackTrace();
155 } catch (IOException e) {
156 e.printStackTrace();
157 }
158 }
159
160 @Override
161
162
163
164
165 public void onRead() throws IOException {
166 ByteBuffer input = ByteBuffer.allocate(10000);
167 try {
168 ((ReadableByteChannel) this.channel).read(input);
169 } catch (IOException e) {
170 register(this.registeredOperations
171 - (SelectionKey.OP_READ & this.registeredOperations));
172 return;
173 }
174 input.flip();
175 if (input.position() == input.limit()) {
176 onClientDisconnected();
177 return;
178 }
179 if (input.position() == input.limit()) {
180 register(this.registeredOperations
181 - (SelectionKey.OP_READ & this.registeredOperations));
182 }
183 this.toThread.write(input.array(), input.position(), input.limit());
184 input.clear();
185 }
186
187
188
189
190
191 private void onClientDisconnected() {
192 this.reactor.unregister(this);
193 }
194
195
196
197
198
199
200 public void onGetProperties(GetProperties o) {
201 if (o.device == null) {
202 this.allDevices = true;
203 } else {
204 this.device = o.device;
205 }
206 }
207
208
209
210
211
212
213
214
215 public synchronized void onEnableBlob(EnableBlob eb) {
216 if (this.device == null) {
217 this.defaults = eb.blobenable;
218 }
219 BlobEnabler ber = this.blobEnableMap.get(eb.device);
220 if (ber == null) {
221 BlobEnabler be = new BlobEnabler();
222 if (eb.name == null) {
223 be.defaults = eb.blobenable;
224 this.blobEnableMap.put(eb.device, be);
225 } else {
226 be.specific.put(eb.name, eb.blobenable);
227 this.blobEnableMap.put(eb.device, be);
228 }
229 } else {
230 if (eb.name == null) {
231 ber.defaults = eb.blobenable;
232 } else {
233 ber.specific.put(eb.name, eb.blobenable);
234 }
235 }
236 }
237
238
239
240
241
242
243
244
245
246
247
248 private static boolean getEnabled(boolean blob, BlobEnable be) {
249 if (blob) {
250 switch (be) {
251 case Only:
252 return true;
253 case Also:
254 return true;
255 case Never:
256 return false;
257 }
258 } else {
259 switch (be) {
260 case Only:
261 return false;
262 case Also:
263 return true;
264 case Never:
265 return true;
266 }
267 }
268 throw new RuntimeException();
269 }
270
271
272
273
274
275
276
277
278
279 public synchronized boolean getVectorEnabled(Vector vec) {
280 BlobEnabler ber = this.blobEnableMap.get(vec.getDevice());
281 if (ber == null) {
282 return getEnabled(vec instanceof BlobVector, this.defaults);
283 } else {
284 BlobEnable be = ber.specific.get(vec.getName());
285 if (be == null) {
286 return getEnabled(vec instanceof BlobVector, ber.defaults);
287 } else {
288 return getEnabled(vec instanceof BlobVector, be);
289 }
290 }
291 }
292
293
294
295
296
297
298
299
300
301
302
303 public synchronized void send(org.indi.objects.Object object,
304 TransferType type, String message) {
305 String dev = null;
306 if (object instanceof Vector) {
307 Vector vec = (Vector) object;
308 dev = vec.getDevice();
309 if (!getVectorEnabled(vec)) {
310 return;
311 }
312 }
313 if (object instanceof Message) {
314 dev = ((Message) object).getDevice();
315 BlobEnabler ber = this.blobEnableMap.get(dev);
316 if (ber == null) {
317 if (!getEnabled(false, this.defaults)) {
318 return;
319 }
320 } else {
321 if (!getEnabled(false, ber.defaults)) {
322 return;
323 }
324 }
325 }
326 if ((dev == this.device) | (this.allDevices)) {
327 String data = object.getXML(type, message);
328 ByteBuffer output = ByteBuffer.allocate(data.length());
329 output.put(data.getBytes());
330 output.flip();
331 write(output);
332 }
333 }
334 }