Warning: Can't use blame annotator:
svn blame failed on trunk/src/tmcsim/paramicscommunicator/ParamicsCommunicator.java: ("Can't find a temporary directory: Internal error", 20014)

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

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

Initial Import of project files

RevLine 
1package tmcsim.paramicscommunicator;
2
3import java.awt.event.WindowEvent;
4import java.awt.event.WindowListener;
5import java.io.EOFException;
6import java.io.File;
7import java.io.FileInputStream;
8import java.io.FileOutputStream;
9import java.io.IOException;
10import java.io.ObjectInputStream;
11import java.io.ObjectOutputStream;
12import java.net.ServerSocket;
13import java.net.Socket;
14import java.net.SocketTimeoutException;
15import java.util.Observable;
16import java.util.Observer;
17import java.util.Properties;
18import java.util.TreeMap;
19import java.util.logging.FileHandler;
20import java.util.logging.Level;
21import java.util.logging.Logger;
22
23import javax.swing.JOptionPane;
24import javax.swing.UIManager;
25
26import org.w3c.dom.Document;
27import org.w3c.dom.Element;
28
29import tmcsim.common.CADProtocol.PARAMICS_ACTIONS;
30import tmcsim.common.CADProtocol.PARAMICS_COMM_TAGS;
31import tmcsim.paramicscommunicator.FileIOUpdate.IO_TYPE;
32import tmcsim.paramicscommunicator.FileRegUpdate.REG_TYPE;
33import tmcsim.paramicscommunicator.gui.ParamicsCommunicatorGUI;
34import tmcsim.simulationmanager.SimulationManager;
35
36
37/**
38 * ParamicsCommunicator is the main class for this module.  The Paramics
39 * Communicator is used to provide communication between the CAD Simulator
40 * and the Paramics traffic modeler.  While the application is running, data
41 * is received on a socket from the CAD Simulator.  Transmitted data are
42 * XML documents containing information and action commands. The CAD Simulator
43 * registers readers and writers with the ParamicsCommunicator.  Any data read
44 * by a ParamicsReader is sent back to the CAD Simulator.  All data to be
45 * written by a ParamicsWriter is received through the socket.<br><br> 
46 * The properties file for the ParamicsCommunicator class contains the following data.<br>
47 * <code>
48 * -----------------------------------------------------------------------------<br>
49 * Socket Port          The port number to use for socket communication.<br>
50 * Working Directory    The working directory use for Paramics file communication.<br>
51 * Error File           The target file to use for error logging.<br>
52 * -----------------------------------------------------------------------------<br>
53 * Example File: <br>
54 * SocketPort          = 4450 <br>
55 * WorkingDirectory    = c:\\tmc_simulator\\ <br>
56 * ErrorFile           = sim_mgr_error.xml <br>
57 * -----------------------------------------------------------------------------<br>
58 * </code>
59 *
60 * @author Matthew Cechini (mcechini@calpoly.edu)
61 * @version $Date: 2009/04/17 16:27:46 $ $Revision: 1.7
62 */
63public class ParamicsCommunicator extends Observable implements Observer, Runnable {
64
65    /** Error logger. */
66    private static Logger paramLogger = Logger.getLogger("tmcsim.paramicscommunicator");
67   
68    /**
69     * Enumeration containing property names.
70     * @author Matthew Cechini
71     */
72    private static enum PROPERTIES {
73       
74        SOCKET_PORT ("SocketPort"),
75        WORKING_DIR ("WorkingDirectory");       
76       
77        public String name;
78       
79        private PROPERTIES(String n) {
80            name = n;
81        }
82    }
83   
84       
85    /** Properties object. */
86    private Properties paramicsCommProp = null; 
87   
88    /** Current working directory where files will be read and written */
89    private String workingDirectory = null;
90   
91    /** Socket used to create socket communication with the CAD Simulator.  */
92    private ServerSocket serverSocket = null;
93   
94    /** Soccket used to communicate with CAD Simulator.*/
95    private Socket paramicsSocket = null;   
96   
97    /** Input Stream for reading data from the CAD Simulator. */
98    private ObjectInputStream in = null;
99   
100    /** Output Stream for writing data to the CAD Simulator.  */
101    private ObjectOutputStream out = null;
102   
103    /** Map of all current ParamicsFileWriters referenced by I/O ID. */
104    private TreeMap<String, ParamicsFileWriter> writers = null;
105   
106    /** Map of all current ParamicsFileReaders referenced by I/O ID.  */
107    private TreeMap<String, ParamicsFileReader> readers = null;
108   
109    /** The view class for the ParamicsCommunicator. */
110    private ParamicsCommunicatorGUI theGUI;
111   
112    /**
113     * Constructor.  Read in the property values.  If the properties file
114     * does not contain a value for the working directory, open a dialog
115     * to prompt the user for the path of the Paramics working directory.
116     * An empty string is not accepted.  A null signifies that the user
117     * pressed cancel.  Prompt the user to accept the cancel and exit the
118     * application if confirmed.  Continue until a valid directory has been
119     * entered, that exists, and append a '\' to the end of the directory
120     * if necessary.
121     *
122     * Initialize the Sockets
123     * and begin communication.
124     *
125     * @param propertiesFilePath File Path of ParamicsCommunicator properties file.
126     */
127    public ParamicsCommunicator (String propertiesFile) 
128    {
129       
130        writers = new TreeMap<String, ParamicsFileWriter>();
131        readers = new TreeMap<String, ParamicsFileReader>();
132
133        theGUI = new ParamicsCommunicatorGUI();
134        addObserver(theGUI);
135        theGUI.addWindowListener(new WindowListener() {         
136            public void windowActivated(WindowEvent arg0) {};
137            public void windowClosed(WindowEvent arg0) {};
138            public void windowClosing(WindowEvent arg0) {
139                System.exit(0);
140            }
141            public void windowDeactivated(WindowEvent arg0) {};
142            public void windowDeiconified(WindowEvent arg0) {};
143            public void windowIconified(WindowEvent arg0) {};
144            public void windowOpened(WindowEvent arg0) {};
145        });
146       
147        try {
148            paramicsCommProp = new Properties();
149            paramicsCommProp.load(new FileInputStream(propertiesFile));
150           
151            if(paramicsCommProp.getProperty(PROPERTIES.SOCKET_PORT.name) == null) 
152            {
153                JOptionPane.showMessageDialog(theGUI, 
154                        "Properties file missing CAD Simulator Port information.", 
155                        "Invalid Configuration", JOptionPane.ERROR_MESSAGE);
156                System.exit(0);
157            }
158            else if(paramicsCommProp.getProperty(PROPERTIES.WORKING_DIR.name) == null || 
159                    paramicsCommProp.getProperty(PROPERTIES.WORKING_DIR.name).length() == 0) {
160               
161                try {
162                    String workingDir = null;
163                   
164                    while (workingDir == null || workingDir.length() == 0) {                       
165                        workingDir = JOptionPane.showInputDialog(null,
166                                "Please set the output directory for Paramics communication.",
167                                "Paramics Working Directory", JOptionPane.QUESTION_MESSAGE);
168                       
169                        if(workingDir == null) {
170                           
171                        }
172                        else if(!new File(workingDir).exists()) {
173                            JOptionPane.showMessageDialog(null,
174                                    "Directory does not exist.",
175                                    "Invalid Working Directory", JOptionPane.WARNING_MESSAGE);
176                           
177                            workingDir = null;
178                        }
179                        else if(!new File(workingDir).isDirectory()) {
180                            JOptionPane.showMessageDialog(null,
181                                    workingDir + " is not a directory.",
182                                    "Invalid Working Directory", JOptionPane.WARNING_MESSAGE);
183                           
184                            workingDir = null;
185                        }                       
186                    }
187
188                    if(workingDir.lastIndexOf("\\") != workingDir.length()-1) {
189                        workingDir = workingDir + "\\";
190                    }
191                   
192                    paramicsCommProp.setProperty(PROPERTIES.WORKING_DIR.name, workingDir);     
193                    paramicsCommProp.store(new FileOutputStream(propertiesFile), "");
194                } catch (IOException ioe) {
195                    paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", "Constructor", 
196                            "Exception in writing properties file.", ioe);
197                }
198               
199            }
200
201            workingDirectory = paramicsCommProp.getProperty(
202                    PROPERTIES.WORKING_DIR.name).trim();                   
203
204        } catch (Exception e) {
205            paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", "Constructor", 
206                    "Exception in reading properties file.", e);
207        }
208       
209       
210        try {
211            initializeSockets(Integer.parseInt(paramicsCommProp.getProperty(
212                    PROPERTIES.SOCKET_PORT.name).trim()));
213        }
214        catch (Exception e) {
215            paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", "Constructor", 
216                    "Exception in initializing sockets.", e);
217        }
218
219    }
220   
221    /**
222     * Transmits a message XML document object to the CAD Simulator.
223     *
224     * @param mess The ParamicsCommMessage to be transmitted.
225     */
226    private void write(Document mess) {
227       
228        synchronized(paramicsSocket) {
229            try {
230                out.writeObject(mess);
231                out.flush();
232            }
233            catch (Exception e) {
234                paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", "write", 
235                        "Exception in writing to the socket.", e);
236            }
237        }
238    }
239   
240    /**
241     * Observer/Observable update method.  The Paramics Communicator observers
242     * registered ParamicsReaders.  When messages are to be sent, they are sent
243     * through this method.  All messages are ParamicsCommMessage objects.  Send
244     * these messages to the write() method for transmission on the socket.
245     */
246    public void update(Observable o, Object arg) {     
247
248        if(arg instanceof Document) {
249            write((Document)arg);               
250        }           
251    }
252   
253    /**
254     * Runnable method.  While this thread is not interrupted, read in an
255     * object from the socket input stream.  If an object exists, call
256     * doMessage() to parse and perform the received action in the message. 
257     */
258    public void run() {
259       
260        while(true) {                       
261            try {
262                doMessage((Document)in.readObject());
263            } 
264            catch(SocketTimeoutException ste) {
265                //just try again
266            }   
267            catch(EOFException eofe) {
268                paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", 
269                        "run", "EOF Exception in reading data from the socket.", eofe);
270            }
271            catch(Exception e) {
272                paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", 
273                        "run", "Exception in reading data from the socket.", e);
274
275                JOptionPane.showMessageDialog(theGUI, 
276                        "Connection has been lost to the CAD Simulator.  " +
277                        "Paramics Communicator will now shutdown.", 
278                        "Dropped Connection", JOptionPane.ERROR_MESSAGE);
279                break;
280            }                   
281        }
282       
283       
284        try { in.close(); } catch (Exception e) {}
285        try { out.close(); } catch (Exception e) {}
286        try { serverSocket.close(); } catch (Exception e) {}
287        try { paramicsSocket.close(); } catch (Exception e) {}
288       
289    }
290   
291    /**
292     * Perform the action represented in the received XML document message.
293     * First determine if the action is from a READER, WRITER, and RESET. 
294     * If the paramics action is REGISTER, add a new ParamicsFileReader/Writer
295     * to the local list of readers/writers and update the GUI with a
296     * FileRegUpdate object. If the paramics action is UNREGISTER, remove the
297     * ParamicsFileReader/Writer from the local list of readers/writers and update
298     * the GUI with a FileRegUpdate object.  If RESET is received, clear all
299     * readers and writers.
300     *
301     * @param mess Received XML document message.
302     */
303    private void doMessage (Document mess) {
304       
305        Element rootElement = mess.getDocumentElement();
306
307        String id     = null;
308        String action = null;
309       
310        switch(PARAMICS_COMM_TAGS.fromString(rootElement.getNodeName())) {
311            case READER:
312                id     = rootElement.getAttribute(PARAMICS_COMM_TAGS.ID.tag);
313                action = rootElement.getAttribute(PARAMICS_COMM_TAGS.ACTION.tag);
314               
315                switch(PARAMICS_ACTIONS.fromString(action)) {
316                    case REGISTER:
317                        Integer interval   = Integer.parseInt(rootElement.getChildNodes().item(0).getTextContent());
318                        String  targetFile = rootElement.getChildNodes().item(1).getTextContent();
319                       
320                        readers.put(id, new ParamicsFileReader(workingDirectory, id, 
321                                interval, targetFile));
322                        readers.get(id).addObserver(this);
323                        readers.get(id).addObserver(theGUI);
324                       
325                        setChanged();
326                        notifyObservers(new FileRegUpdate(IO_TYPE.READ, 
327                                REG_TYPE.REGISTER, id, targetFile, interval));
328                        break;
329                    case UNREGISTER: 
330                        readers.get(id).deleteObserver(this);
331                        readers.get(id).deleteObserver(theGUI);
332                        readers.remove(id);
333
334                        setChanged();
335                        notifyObservers(new FileRegUpdate(IO_TYPE.READ, 
336                                REG_TYPE.UNREGISTER, id, null, null));                     
337                        break;
338                }
339                break;
340            case WRITER:
341                id     = rootElement.getAttribute(PARAMICS_COMM_TAGS.ID.tag);
342                action = rootElement.getAttribute(PARAMICS_COMM_TAGS.ACTION.tag);
343               
344                switch(PARAMICS_ACTIONS.fromString(action)) {
345                    case REGISTER:
346                        String targetFile = rootElement.getChildNodes().item(0).getTextContent(); 
347                       
348                        writers.put(id, new ParamicsFileWriter(id, 
349                                workingDirectory, targetFile));
350                        writers.get(id).addObserver(theGUI);
351                       
352                        setChanged();
353                        notifyObservers(new FileRegUpdate(IO_TYPE.WRITE, 
354                                REG_TYPE.REGISTER, id, targetFile, null));     
355                        break;
356                    case UNREGISTER: 
357                        writers.remove(id);
358                       
359                        writers.get(id).deleteObserver(theGUI);
360
361                        setChanged();
362                        notifyObservers(new FileRegUpdate(IO_TYPE.WRITE, 
363                                REG_TYPE.UNREGISTER, id, null, null));
364                        break;
365                    case WRITE_FILE:
366                        writers.get(id).writeMessage((Element)rootElement.getChildNodes().item(0));
367                        break;
368                }
369                break;
370            case RESET:
371                readers.clear();
372                writers.clear();
373                break;
374        }   
375    }
376   
377    /**
378     * Method waits to accept a socket connection from the CAD Simulator. 
379     * When a connection has been established the method exits.  The input and
380     * output streams are created on the new socket.
381     *
382     * @param socketPort Socket port to use for establishing Socket communication.
383     * @throws IOException if there is an exception in establishing Socket communication.
384     */
385    private void initializeSockets(Integer socketPort) throws IOException {
386   
387        boolean waiting = true;
388       
389        try {
390            serverSocket = new ServerSocket(socketPort);           
391            //delay for accept timeout(milliseconds)       
392            serverSocket.setSoTimeout(10 * 1000); 
393        }
394        catch (IOException ioe) {
395            throw new IOException("Exception in creating " +
396                    "the server socket on port " + socketPort);
397        }
398       
399        while(waiting) {           
400            try{
401                paramicsSocket = serverSocket.accept();
402                waiting = false;
403            } 
404            catch(SocketTimeoutException ste) {
405                System.out.println("...waiting...");
406            }   
407            catch(IOException ioe) {
408                throw new IOException("Exception in creating " +
409                        "the receiving socket on port " + socketPort);
410            }
411        }
412
413       
414        //** out must be performed before in to unlock for connecting socket **//
415        try {       
416            out     = new ObjectOutputStream(paramicsSocket.getOutputStream());
417            in      = new ObjectInputStream(paramicsSocket.getInputStream());
418        }
419        catch (IOException ioe) {
420            throw new IOException("Exception in creating input " +
421                    "and output streams on socket.");
422        }
423           
424    }
425
426    /**
427     * Construct the ParamicsCommunicator with the properties file path,
428     * either from the command line arguments or default.
429     *
430     * @param args Command line arguments.
431     */
432    public static void main(String[] args) {
433
434        try
435        {
436            if(System.getProperty("PARAMICS_COMM_PROPERTIES") != null)
437            {
438                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
439   
440                new Thread(new ParamicsCommunicator(System.getProperty(
441                        "PARAMICS_COMM_PROPERTIES"))).start();
442            }
443            else
444            {
445                throw new Exception ("PARAMICS_COMM_PROPERTIES system property not defined.");
446            }
447        } 
448        catch (Exception e) 
449        {
450            paramLogger.logp(Level.SEVERE, "ParamicsCommunicator", "Main", 
451                    "Error occured initializing application", e);
452
453            JOptionPane.showMessageDialog(null, e.getMessage(), 
454                    "Error - Program Exiting", JOptionPane.ERROR_MESSAGE); 
455           
456            System.exit(-1);
457        }
458   
459       
460    }   
461   
462}
Note: See TracBrowser for help on using the repository browser.