source: tmcsimulator/trunk/src/tmcsim/cadsimulator/paramicscontrol/ParamicsCommunicator.java @ 2

Revision 2, 15.0 KB checked in by jdalbey, 10 years ago (diff)

Initial Import of project files

Line 
1package tmcsim.cadsimulator.paramicscontrol;
2
3import java.io.IOException;
4import java.io.ObjectInputStream;
5import java.io.ObjectOutputStream;
6import java.net.InetSocketAddress;
7import java.net.Socket;
8import java.net.SocketTimeoutException;
9import java.util.Observable;
10import java.util.Observer;
11import java.util.TreeMap;
12import java.util.logging.Level;
13import java.util.logging.Logger;
14
15import javax.xml.parsers.DocumentBuilderFactory;
16
17import org.w3c.dom.Document;
18import org.w3c.dom.Element;
19
20import tmcsim.cadsimulator.managers.ParamicsSimulationManager;
21import tmcsim.common.CADEnums.PARAMICS_STATUS;
22import tmcsim.common.CADProtocol.PARAMICS_ACTIONS;
23import tmcsim.common.CADProtocol.PARAMICS_COMM_TAGS;
24
25/**
26 * The ParamicsCommunicator is a singleton object used to handle communication
27 * between the CADSimulator and the remote ParamicsCommunicator.  A socket
28 * connection is established to the ParamicsCommunicator, and all data is read
29 * and written through the socket.  ParamicsWriters and ParamicsReaders are
30 * registered with this object to read and write specific data to and from files
31 * on the remote ParamicsCommunicator machine.  The remote ParamicsCommunicator
32 * is notified of this registeration (and unregistration) process so there is a
33 * direct correlation between registered objects in both Communicators.  After a
34 * ParamicsReader is registered, any messages received from the remotely
35 * created reader are sent to the local ParamicsReader object.  After a writer is
36 * registered, this object is set as an Observer.  When message are to be sent,
37 * they are received through the update() method and transmitted to the remote
38 * ParamicsCommunicator.   
39 *
40 * @author
41 * @version
42 */
43public class ParamicsCommunicator extends Thread implements Observer {
44   
45    /** Error Logger. */
46    private Logger paramLogger = Logger.getLogger("tmcsim.cadsimulator.paramicscontrol");
47   
48    /** Remote Paramics Communicator host name. */
49    private static String paramicsHost   = null;
50   
51    /** Remote Paramics Communicator port. */
52    private static Integer paramicsPort  = null;
53
54    /** Instance of the Coordinator to update with Paramics status */
55    private ParamicsSimulationManager theController = null;
56   
57    /** private used for communication with the remote Paramics Communicator. */
58    private Socket paramicsSocket = null;
59   
60    /** Input stream for reading from socket. */
61    private ObjectInputStream in     = null;
62   
63    /** Output stream for writing to the socket. */
64    private ObjectOutputStream out = null;
65   
66    /** Map of all registered paramics readers, indexed by a unique  id. */
67    private TreeMap<String, ParamicsReader> paramicsReaders = null;
68
69    /** Map of all registered paramics writers, indexed by a unique  id. */
70    private TreeMap<String, ParamicsWriter> paramicsWriters = null; 
71   
72    /**
73     * Boolean flag to designate whether a connection to the remote
74     * Paramics Communicator is established.
75     */ 
76    private boolean connected = false;
77   
78    /** Counter for assigning unique ids. */
79    private int nextIdentifier = 0;     
80   
81
82    /**
83     * Constructor.  Initialize member data.
84     */
85    public ParamicsCommunicator(ParamicsSimulationManager cntrl, 
86            String newHost, Integer newPort) {
87
88        theController  = cntrl;
89        paramicsHost   = newHost;
90        paramicsPort   = newPort;   
91       
92        paramicsReaders = new TreeMap<String, ParamicsReader>();
93        paramicsWriters = new TreeMap<String, ParamicsWriter>();
94           
95    }
96   
97    /**
98     * Returns the next unique identifier that may be used for a ParamicsWriter or
99     * ParamicsReader.
100     * @return int Next unique identifier value
101     */
102    public String nextID() {
103        return String.valueOf(nextIdentifier++);
104    }
105   
106   
107    /**
108     * Method connects to host and port where the remote paramics communicator
109     * has connected.  Input and Output streams are created on the new Socket
110     * connection.  A RESET message is sent transmitted on the socket and this
111     * thread is started. 
112     */
113    public void connect() throws IOException {
114       
115        try {
116            paramicsSocket = new Socket();
117            paramicsSocket.setSoTimeout(5000);
118            paramicsSocket.connect(new InetSocketAddress(paramicsHost, paramicsPort));
119
120            //** out must be performed before in to unlock for connected socket **//
121            out = new ObjectOutputStream(paramicsSocket.getOutputStream());
122            in  = new ObjectInputStream(paramicsSocket.getInputStream());
123        }
124        catch (IOException e) {
125            paramicsSocket.close();
126           
127            paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", "connect()", 
128                    "Exception in creating input and output streams on socket.", e);
129           
130            throw new IOException("IOException in connecting to Paramics Socket");
131        }
132
133        connected = true;
134       
135        reset();
136       
137        if(getState() == State.NEW)
138            start();
139       
140    }
141   
142    /**
143     * This thread is interrupted and if a conenction has been made,
144     * it is closed after transmitting a RESET message.
145     */
146    public void disconnect() {
147        interrupt();
148       
149        if(!connected)
150            return;     
151       
152        reset();
153       
154        cleanup();     
155                       
156    }
157
158   
159    /**
160     * Returns status of connection to remote Paramics Communicator.
161     * @return True if a connection is established, false if not.
162     */
163    public boolean isConnected() { 
164        return connected; 
165    }
166   
167    /**
168     * While a connection is established to the remote paramics communicator,
169     * read messages from the input stream.  Get the ParamicsReader from the
170     * local list whose unique ID matches that of the message sender, and call
171     * the receive() method on that reader.
172     */
173    public void run() {
174       
175        while(connected) {
176            try {               
177                Document rxMessage = (Document)in.readObject();
178                Element docElement = rxMessage.getDocumentElement();
179
180                String readerID         = docElement.getAttribute(PARAMICS_COMM_TAGS.ID.tag);               
181                ParamicsReader rxReader = paramicsReaders.get(readerID);
182               
183                if(rxReader != null) {
184                    rxReader.receive(docElement.getChildNodes().item(0));
185                }
186            }   
187            catch(SocketTimeoutException ste) {
188                //just try again
189            }       
190            catch (Exception e) {
191                paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", "run()", 
192                        "Exception in reading from the socket.", e);
193                cleanup();
194               
195                theController.updateParamicsStatus(PARAMICS_STATUS.DROPPED);
196            }
197        }       
198    }
199   
200    /**
201     * Observer/Observable update method.  The Paramics Communicator observers
202     * registered ParamicsWriters.  When messages are to be sent, they are sent
203     * through this method.  All messages are ParamicsCommMessage objects.  Send
204     * these messages to the write() method for transmission on the socket.
205     */
206    public void update(Observable o, Object arg) {     
207        write((Document)arg);               
208    }
209   
210   
211    /**
212     * If a connection has been established, transmit a message to
213     * register the reader, and add it to the local list of
214     * ParamicsReaders.
215     *
216     * @param reader The new registering ParamicsReader.
217     */
218    public void registerReader(ParamicsReader reader) {
219        if(connected && !paramicsReaders.containsKey(reader.readerID)) {
220           
221            try {
222                Document readerDoc = DocumentBuilderFactory.newInstance()
223                    .newDocumentBuilder().newDocument();
224       
225                Element readerElem = readerDoc.createElement(PARAMICS_COMM_TAGS.READER.tag);
226                readerElem.setAttribute(PARAMICS_COMM_TAGS.ID.tag, reader.readerID);
227                readerElem.setAttribute(PARAMICS_COMM_TAGS.ACTION.tag, 
228                        PARAMICS_ACTIONS.REGISTER.action);
229               
230                Element intElem = readerDoc.createElement(PARAMICS_COMM_TAGS.INTERVAL.tag);
231                intElem.appendChild(readerDoc.createTextNode(reader.interval));
232                readerElem.appendChild(intElem);   
233               
234                Element fileElem = readerDoc.createElement(PARAMICS_COMM_TAGS.TARGET_FILE.tag);
235                fileElem.appendChild(readerDoc.createTextNode(reader.targetFile));
236                readerElem.appendChild(fileElem);
237       
238                readerDoc.appendChild(readerElem);         
239                   
240                write(readerDoc);
241
242                paramicsReaders.put(reader.readerID, reader);
243            }
244            catch (Exception e) {
245                paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", 
246                        "registerReader", "Exception in registering reader.", e);
247            }       
248        }
249    }
250   
251    /**
252     * If a connection has been established, transmit a message to
253     * unregister the reader, and remove it from the local list of
254     * ParamicsReaders.
255     *
256     * @param reader The unregistering ParamicsReader.
257     */
258    public void unregisterReader(ParamicsReader reader) {
259        if(connected && paramicsReaders.containsKey(reader.readerID)) {
260           
261            try {
262                Document readerDoc = DocumentBuilderFactory.newInstance()
263                    .newDocumentBuilder().newDocument();
264       
265                Element readerElem = readerDoc.createElement(PARAMICS_COMM_TAGS.READER.tag);
266                readerElem.setAttribute(PARAMICS_COMM_TAGS.ID.tag, reader.readerID);
267                readerElem.setAttribute(PARAMICS_COMM_TAGS.ACTION.tag, 
268                        PARAMICS_ACTIONS.UNREGISTER.action);
269       
270                readerDoc.appendChild(readerElem);         
271                   
272                write(readerDoc);
273
274                paramicsReaders.remove(reader.readerID);
275            }
276            catch (Exception e) {
277                paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", 
278                        "unregisterReader", "Exception in unregistering reader.", e);
279            }           
280        }
281    }
282   
283    /**
284     * If a connection has been established, transmit a message to
285     * register the writer, and add it to the local list of
286     * ParamicsWriters.  This object is set as an observer to the
287     * registering writer.
288     *
289     * @param writer The new registering ParamicsWriter.
290     */
291    public void registerWriter(ParamicsWriter writer) {
292       
293        if(connected && !paramicsWriters.containsKey(writer.writerID)) {
294            try {
295                Document writerDoc = DocumentBuilderFactory.newInstance()
296                    .newDocumentBuilder().newDocument();
297       
298                Element writerElem = writerDoc.createElement(PARAMICS_COMM_TAGS.WRITER.tag);
299                writerElem.setAttribute(PARAMICS_COMM_TAGS.ID.tag, writer.writerID);
300                writerElem.setAttribute(PARAMICS_COMM_TAGS.ACTION.tag,
301                        PARAMICS_ACTIONS.REGISTER.action);
302               
303                Element fileElem = writerDoc.createElement(PARAMICS_COMM_TAGS.TARGET_FILE.tag);
304                fileElem.appendChild(writerDoc.createTextNode(writer.targetFile));
305                writerElem.appendChild(fileElem);
306       
307                writerDoc.appendChild(writerElem);         
308                   
309                write(writerDoc);
310
311               
312                paramicsWriters.put(writer.writerID, writer);
313               
314                writer.addObserver(this);
315            }
316            catch (Exception e) {
317                paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", 
318                        "registerWriter", "Exception in registering writer.", e);
319            }           
320        }   
321    }
322   
323    /**
324     * If a connection has been established, transmit a message to
325     * unregister the writer, and remove it from the local list of
326     * ParamicsWriters.  This object is removed as an Observer
327     * from the unregistering writer.
328     *
329     * @param writer The unregistering ParamicsWriter.
330     */
331    public void unregisterWriter(ParamicsWriter writer) {
332        if(connected && paramicsWriters.containsKey(writer.writerID)) {
333           
334            try {
335                Document writerDoc = DocumentBuilderFactory.newInstance()
336                    .newDocumentBuilder().newDocument();
337       
338                Element writerElem = writerDoc.createElement(PARAMICS_COMM_TAGS.WRITER.tag);
339                writerElem.setAttribute(PARAMICS_COMM_TAGS.ID.tag, writer.writerID);
340                writerElem.setAttribute(PARAMICS_COMM_TAGS.ACTION.tag, 
341                        PARAMICS_ACTIONS.UNREGISTER.action);
342       
343                writerDoc.appendChild(writerElem);         
344                   
345                write(writerDoc);
346                   
347                paramicsWriters.remove(writer.writerID);
348               
349                writer.deleteObserver(this);
350            }
351            catch (Exception e) {
352                paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", 
353                        "unregisterWriter", "Exception in unregistering writer.", e);
354            }
355        }   
356    }   
357   
358    protected void reset() {
359       
360        try {
361            Document resetDoc = DocumentBuilderFactory.newInstance()
362                .newDocumentBuilder().newDocument();
363       
364            Element resetElem = resetDoc.createElement(PARAMICS_COMM_TAGS.RESET.tag);
365       
366            resetDoc.appendChild(resetElem);       
367               
368            write(resetDoc);
369        }
370        catch (Exception e) {
371            paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", 
372                    "reset", "Exception in reseting.", e);
373        }
374
375    }
376   
377    /**
378     * Close the input and output streams and the socket.  Clear the lists
379     * of readers and writers, and set the connection flag to false.
380     */
381    protected void cleanup() {
382       
383        try {out.close();} catch (Exception e) {}
384        try {in.close();} catch (Exception e) {}
385        try {paramicsSocket.close();} catch (Exception e) {}
386       
387        paramicsReaders.clear();
388        paramicsWriters.clear();
389        connected = false; 
390    }   
391   
392    /**
393     * Write the parameter ParamicsCommMessage to the output stream.  Flush
394     * the stream to be sure all data is transmitted.
395     *
396     * @param message The message to transmit.
397     */
398    protected synchronized void write(Document output) {
399       
400        try {
401            out.writeObject(output);
402            out.flush();       
403        }
404        catch (Exception e) {
405            paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", "write", 
406                    "Exception in writing to the socket.", e);
407            cleanup();         
408           
409            theController.updateParamicsStatus(PARAMICS_STATUS.DROPPED);
410        }
411       
412    }
413
414       
415}
Note: See TracBrowser for help on using the repository browser.