View Javadoc

1   package org.indi.server;
2   
3   import java.io.ByteArrayInputStream;
4   import java.io.IOException;
5   import java.io.InputStream;
6   import java.io.OutputStream;
7   import java.io.SequenceInputStream;
8   import java.util.Queue;
9   import java.util.concurrent.LinkedBlockingQueue;
10  
11  import javax.xml.parsers.SAXParserFactory;
12  
13  import org.indi.clientmessages.GetProperties;
14  import org.indi.objects.BlobVector;
15  import org.indi.objects.NumberVector;
16  import org.indi.objects.SwitchVector;
17  import org.indi.objects.TextVector;
18  import org.indi.objects.Vector;
19  import org.indi.reactor.QueueHandler;
20  
21  /**
22   * A class to allow indidrivers written in C to interact with this indiserver
23   * writing in Java. The class acts as a proxy class communicating with the
24   * indidriver that runs in a diffrent process via the stdin stdout streams.
25   * 
26   * @author Dirk Hünniger
27   * 
28   */
29  public class ExternalDevice extends BasicDevice implements
30  	QueueHandler<java.lang.Object>, Runnable {
31      /**
32       * process the indiserver writen in C is runnning in
33       */
34      private Process process;
35      /**
36       * the input strem connected to the porcess of the driver
37       */
38      private final InputStream in;
39      /**
40       * the output stream connected to the driver
41       */
42      private final OutputStream out;
43      /**
44       * the input stream used to read by the sax parser to read from the driver.
45       * It is connected to the stdout stream of the driver but contains an
46       * additional prelude used to intialize the sax parser
47       */
48      private final InputStream fromDriver;
49      /**
50       * a queue into which the parsing thread writes the indiobjects reacieved
51       * from the driver
52       */
53      private final Queue<java.lang.Object> threadToDeviceQueue;
54  
55      /**
56       * class constuctor
57       * 
58       * @param server
59       *                the server to host the driver
60       * @param command
61       *                the command to start the external driver
62       */
63      public ExternalDevice(IndiServer server, String command) {
64  	super(server);
65  	try {
66  	    this.process = Runtime.getRuntime().exec(command);
67  	} catch (IOException e) {
68  	    throw new RuntimeException(e);
69  	}
70  	this.in = this.process.getInputStream();
71  	this.out = this.process.getOutputStream();
72  	try {
73  	    this.out.write("<enableBLOB>Also</enableBLOB>".getBytes("UTF-8"));
74  	} catch (Exception e) {
75  	    throw new RuntimeException(e);
76  	}
77  	InputStream prelude = new ByteArrayInputStream(
78  		"<?xml version=\"1.0\" encoding=\"UTF-8\"?> <doc>".getBytes());
79  	this.fromDriver = new SequenceInputStream(prelude, this.in);
80  	this.threadToDeviceQueue = new LinkedBlockingQueue<java.lang.Object>();
81  	server.reactor.register(this);
82  	(new Thread(this)).start();
83      }
84  
85      /**
86       * run asynchronously. Entrypoint of the parsing thread.
87       */
88      public void run() {
89  	javax.xml.parsers.SAXParser parser;
90  	try {
91  	    parser = SAXParserFactory.newInstance().newSAXParser();
92  	} catch (Exception e) {
93  	    throw new RuntimeException(e);
94  	}
95  	org.indi.client.SaxHandler h = new org.indi.client.SaxHandler(
96  		this.threadToDeviceQueue);
97  	try {
98  	    parser.parse(this.fromDriver, h);
99  	    // while (true) {
100 	    // System.out.print(in.read());
101 	    // }
102 	} catch (Exception e) {
103 	    throw new RuntimeException(e);
104 	}
105     }
106 
107     @Override
108     public void onNew(SwitchVector vector) {
109 	sendVector(vector);
110     }
111 
112     @Override
113     public void onNew(NumberVector vector) {
114 	sendVector(vector);
115     }
116 
117     @Override
118     public void onNew(BlobVector vector) {
119 	sendVector(vector);
120     }
121 
122     @Override
123     public void onNew(TextVector vector) {
124 	sendVector(vector);
125     }
126 
127     /**
128      * Send a vector to external driver
129      * 
130      * @param vector
131      *                the vector to be sent
132      */
133     public void sendVector(Vector vector) {
134 	try {
135 	    this.out.write(vector.getXML(vector.getTransferType()).getBytes());
136 	    this.out.flush();
137 	} catch (IOException e) {
138 	    throw new RuntimeException(e);
139 	}
140     }
141 
142     @Override
143     public void onGetProperties(GetProperties o) {
144 	try {
145 	    this.out.write((o.getXML()).getBytes("UTF-8"));
146 	    this.out.flush();
147 	} catch (IOException e) {
148 	    throw new RuntimeException(e);
149 	}
150     }
151 
152     /**
153      * 
154      * @return the queue connecting the parsing thread to the device
155      */
156     public Queue<java.lang.Object> getQueue() {
157 	return this.threadToDeviceQueue;
158     }
159 
160     /**
161      * called by the reactor when a new item is available in the queue. (it has
162      * been put into the queue by the parsing thread)
163      * 
164      * @param input
165      *                the item just received from the queue
166      */
167     public void onRead(java.lang.Object input) {
168 	org.indi.objects.Object i = (org.indi.objects.Object) input;
169 	sendToClients(i, i.getTransferType(), i.getMessage());
170     }
171 
172     /**
173      * Runs an indiserver hosting an external device.
174      * 
175      * @param args
176      *                Command line arguments (ignored)
177      * @throws IOException
178      */
179     public static void main(String[] args) throws IOException {
180 	IndiServer s = new IndiServer();
181 	new ExternalDevice(s, "/home/dirk/indi/src/examples/tutorial_three");
182 	while (true) {
183 	    s.reactor.handleEvents(10);
184 	}
185     }
186 }