1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.indi.server;
20
21 import java.io.IOException;
22 import java.net.URL;
23 import java.nio.channels.ClosedChannelException;
24 import java.nio.channels.SelectableChannel;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Enumeration;
28 import java.util.HashSet;
29 import java.util.PropertyResourceBundle;
30 import java.util.Queue;
31 import java.util.Set;
32 import java.util.concurrent.LinkedBlockingQueue;
33
34 import javax.xml.parsers.ParserConfigurationException;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.indi.clientmessages.GetProperties;
39 import org.indi.objects.TransferType;
40 import org.indi.objects.Vector;
41 import org.indi.reactor.EventHandler;
42 import org.indi.reactor.EventHandlerFactory;
43 import org.indi.reactor.Reactor;
44 import org.xml.sax.SAXException;
45
46
47
48
49
50
51
52 public class IndiServer {
53
54 private final Log log = LogFactory.getLog(IndiServer.class);
55
56
57
58 public Collection<BasicDevice> drivers;
59
60
61
62 public Collection<ClientHandler> clientHandlers;
63
64
65
66 public Reactor reactor;
67
68
69
70 public String version = "1.0";
71
72
73
74
75 public Set<Observer> observers;
76
77
78
79
80
81
82 public IndiServer() throws IOException {
83 this.observers = new HashSet<Observer>();
84 this.reactor = new Reactor();
85 Queue<Object> toDriverQueue = new LinkedBlockingQueue<Object>();
86 this.drivers = new ArrayList<BasicDevice>();
87 this.reactor.register(new Dispatcher(toDriverQueue, this));
88 Acceptor a = new Acceptor(this.reactor, new EventHandlerFactory() {
89 public EventHandler produce(Reactor r, SelectableChannel ch)
90 throws ClosedChannelException, IOException {
91 try {
92 return new ClientHandler(r, ch);
93 } catch (ParserConfigurationException e) {
94 e.printStackTrace();
95 } catch (SAXException e) {
96 e.printStackTrace();
97 }
98 return null;
99 }
100 }, 7624, toDriverQueue);
101 this.clientHandlers = a.getClientHandlers();
102 }
103
104
105
106
107
108
109
110 public void addDriver(BasicDevice driver) {
111 this.drivers.add(driver);
112 }
113
114
115
116
117
118
119
120 public void addObserver(Observer o) {
121 this.observers.add(o);
122 String dev = o.getDevice();
123 GetProperties gp = new GetProperties(this.version, dev);
124 for (Device d : this.drivers) {
125 String name = d.getName();
126 if (name == null) {
127 continue;
128 }
129 if (name.equals(dev)) {
130 d.onGetProperties(gp);
131 }
132 }
133 }
134
135
136
137
138
139
140
141 public void removeObserver(Observer o) {
142 this.observers.remove(o);
143 }
144
145
146
147
148
149
150
151
152
153
154
155 public void sendToClients(org.indi.objects.Object object,
156 TransferType type, String message) {
157 for (ClientHandler ch : this.clientHandlers) {
158 ch.send(object, type, message);
159 }
160 if (object instanceof Vector) {
161 Vector vector = (Vector) object;
162 vector.setTransferType(type);
163 for (Observer o : this.observers) {
164 if (vector.getDevice().equals(o.getDevice())) {
165 if (o.getName().equals(vector.getName())
166 || vector.getTransferType() == TransferType.Del) {
167 if ((vector.getTransferType() == TransferType.Set)
168 && o.getState() == ObserverState.State) {
169 if (o.laststate == vector.getState()) {
170 return;
171 } else {
172 o.laststate = vector.getState();
173 }
174 }
175 o.onObserved(vector);
176 }
177 }
178 ;
179
180 }
181 }
182 }
183
184
185
186
187
188 public static void main(String[] args) {
189 try {
190 new IndiServer().startServer(args);
191 } catch (IOException e) {
192 e.printStackTrace();
193 }
194 }
195
196
197
198
199
200 private void startServer(String[] args) {
201 try {
202 ArrayList<String> deveiceToStart = new ArrayList<String>();
203 nameScanForDevicesToStart(args, deveiceToStart);
204 classNameScanForDevicesToStart(args, deveiceToStart);
205 if (!startAtLeastOneDevice(deveiceToStart)) {
206 this.log.error("no drivers successfully started!");
207 } else {
208 while (true) {
209 this.reactor.handleEvents(10);
210 }
211 }
212 } catch (IOException e) {
213 this.log.error("could not start indi server due to exception", e);
214 }
215 }
216
217 private void classNameScanForDevicesToStart(String[] args,
218 ArrayList<String> devicesToStart) {
219 for (String element : args) {
220 if (element.length() > 0) {
221 try {
222 Class driverClass = Thread.currentThread()
223 .getContextClassLoader().loadClass(element);
224 if (driverClass.isAssignableFrom(BasicDevice.class)) {
225 devicesToStart.add(element);
226 } else {
227 this.log
228 .error("argument is not a driver or driver class ("
229 + element + ")");
230 }
231 } catch (ClassNotFoundException e) {
232 this.log.error("argument is not a driver class (" + element
233 + ")", e);
234 }
235 }
236 }
237 }
238
239 private void nameScanForDevicesToStart(String[] args,
240 ArrayList<String> driversToStart) throws IOException {
241 Enumeration<URL> driverresources = Thread.currentThread()
242 .getContextClassLoader().getResources("META-INF/indi");
243 while (driverresources.hasMoreElements()) {
244 URL url = driverresources.nextElement();
245 PropertyResourceBundle bundle = new PropertyResourceBundle(url
246 .openStream());
247 Enumeration<String> keys = bundle.getKeys();
248 while (keys.hasMoreElements()) {
249 String driverClassName = keys.nextElement();
250 String driverName = bundle.getString(driverClassName);
251 boolean driverActivated = false;
252 for (int index = 0; index < args.length; index++) {
253 if (args[index].equals(driverName)) {
254 driversToStart.add(driverClassName);
255 driverActivated = true;
256 args[index] = "";
257 }
258 }
259 if (!driverActivated) {
260 this.log.info("detected deacivated driver for "
261 + driverName + " (" + driverClassName + ")");
262 } else {
263 this.log.info("detected acivated driver for " + driverName
264 + " (" + driverClassName + ")");
265 }
266 }
267 }
268 }
269
270
271
272
273
274
275 private boolean startAtLeastOneDevice(ArrayList<String> driversToStart) {
276 boolean atLeastOnDriverStarted = false;
277 for (String driverClassName : driversToStart) {
278 try {
279 Class driverClass = Thread.currentThread()
280 .getContextClassLoader().loadClass(driverClassName);
281 addDriver((BasicDevice) driverClass.getConstructor(
282 IndiServer.class).newInstance(this));
283 this.log.info("Successfuly started driver class "
284 + driverClassName);
285 atLeastOnDriverStarted = true;
286 } catch (Exception e) {
287 this.log.error("could not instanciate Driver: "
288 + driverClassName + " due to exception", e);
289 }
290 }
291 return atLeastOnDriverStarted;
292 }
293 }