source: tmcsimulator/trunk/src/tmcsim/cadsimulator/CADServer.java @ 664

Revision 664, 16.2 KB checked in by jdalbey, 4 years ago (diff)

Multifile commit - revise source to match revisions to config filenames. Fix broken system tests. Fix defect #160.

Line 
1package tmcsim.cadsimulator;
2
3import java.io.File;
4import java.io.FileInputStream;
5import java.lang.reflect.Constructor;
6import java.rmi.Naming;
7import java.rmi.RemoteException;
8import java.rmi.registry.LocateRegistry;
9import java.util.Calendar;
10import java.util.Properties;
11import java.util.logging.Level;
12import java.util.logging.Logger;
13import javax.swing.JOptionPane;
14import javax.swing.JWindow;
15import javax.swing.UIManager;
16import javax.xml.parsers.DocumentBuilderFactory;
17import tmcsim.cadsimulator.db.CMSDiversionDB;
18import tmcsim.cadsimulator.managers.ATMSManager;
19import tmcsim.cadsimulator.managers.IncidentManager;
20import tmcsim.cadsimulator.managers.MediaManager;
21import tmcsim.cadsimulator.managers.ParamicsSimulationManager;
22import tmcsim.cadsimulator.managers.SimulationClockManager;
23import tmcsim.cadsimulator.managers.TrafficModelManager;
24import tmcsim.cadsimulator.viewer.model.CADSimulatorState;
25import tmcsim.common.SimulationException;
26import tmcsim.interfaces.CADViewer;
27
28/**
29 * CADServer is main class for the CAD Simulator application.
30 * CADServer must be running before starting any other components of the TMCSim.
31 * At construction the Coordinator, CoordinatorViewer, and all CAD Simulator Managers are
32 * initialized and data relationships are established. Simulation control is
33 * managed through the Coordinator and Managers. The CADServer contains the
34 * instances of all Manager Objects that are used to control the Simulation flow
35 * of data.<br>
36 * There is a GUI (and for testing, a text-based UI) that displays the state
37 * of the server.
38 * <br>
39 * A properties file contains settings for many parameters of the CADServer<br>
40 *
41 * @author Matthew Cechini (mcechini@calpoly.edu)
42 * @author John Dalbey (jdalbey@calpoly.edu)
43 * @version $Date: 2009/04/17 16:27:46 $ $Revision: 1.5 $
44 */
45public class CADServer
46{
47
48    private static String CONFIG_FILE_NAME = "cad_server.properties";
49    /**
50     * Error logger.
51     */
52    private static Logger cadSimLogger = Logger.getLogger("tmcsim.cadsimulator");
53
54    /**
55     * Enumeration containing properties name values. See CADServer class
56     * description for more information.
57     *
58     * @author Matthew
59     * @see CADServer
60     */
61    private static enum CAD_PROPERTIES
62    {
63
64        /**
65         * RMI port to accept CAD Client connections.
66         */
67        CLIENT_PORT("CADClientPort"),
68        /**
69         * RMI port to bind the Coordinator to for RMI communication.
70         */
71        COOR_RMI_PORT("CoordinatorRMIPort"),
72        CAD_RMI_PORT("CADRmiPort"),
73        /**
74         * Filepath for xml file containing diversion data.
75         */
76        CMS_XML_FILE("CMSDiversionXML"),
77        /**
78         * Filepath for xml file containing dvd control data.
79         */
80        DVD_XML_FILE("DVDPlayerXML"),
81        /**
82         * Filepath for xml file containing still image control data.
83         */
84        IMAGE_XML_FILE("StillImagesXML"),
85        /**
86         * Root directory path where audio files are referenced from.
87         */
88        AUDIO_LOCATION("AudioFileLocation"),
89        /**
90         * Filepath for the properties file to initialize the media manager.
91         */
92        MEDIA_PROP_FILE("MediaProperties"),
93        /**
94         * Filepath for the properties file to initialize the paramics control
95         * manager.
96         */
97        PARAMICS_PROP_FILE("ParamicsProperties"),
98        /**
99         * Filepath for the properties file to initialize the atms manager.
100         */
101        ATMS_PROP_FILE("ATMSProperties"),
102        /**
103         * Filepath for the properties file to initialize the traffic manager.
104         */
105        TRAFFICMGR_PROP_FILE("TrafficMgrProperties"),
106        /**
107         * Class name of desired user interface.
108         */
109        USER_INTERFACE("UserInterface"),
110        /**
111         *  Filepath to which is written the simulation time.
112         */
113        ELAPSED_TIME_FILE("ElapsedTimeFile"),
114        /**
115         *  Filepath to which is written the CADcomments log.
116         */
117        CAD_COMMENTS_LOG("CADcommentsLog");
118       
119        public String name;
120
121        private CAD_PROPERTIES(String nam)
122        {
123            name = nam;
124        }
125    };
126    /** NOTE: Protected fields are accessed by Coordinator */
127    /**
128     * CADServerViewer instance.
129     */
130    protected static CADViewer theViewer;
131    //protected static CADSimulatorViewer theViewer;
132    //protected static CADConsoleViewer theConsole;
133    protected static CADSimulatorState theModel;
134    /**
135     * Coordinator instance.
136     */
137    protected static Coordinator theCoordinator;
138    /**
139     * SoundPlayer instance.
140     */
141    protected static SoundPlayer theSoundPlayer = null;
142    /**
143     * SimulationControlManager instance.
144     */
145    protected static SimulationClockManager theSimulationCntrlMgr = null;
146    /**
147     * ParamicsSimulationManager instance.
148     */
149    protected static ParamicsSimulationManager theParamicsSimMgr = null;
150    /**
151     * IncidentManager instance.
152     */
153    protected static IncidentManager theIncidentMgr = null;
154    /**
155     * MediaManager instance.
156     */
157    protected static MediaManager theMediaMgr = null;
158    /**
159     * ATMSManager instance.
160     */
161    protected static ATMSManager theATMSMgr = null;
162    /**
163     * Traffic Model Manager instance
164     */
165    protected static TrafficModelManager theTrafficMgr = null;
166   
167    /**
168     * Properties file for the CADServer, read from CONFIG_FILE_NAME.
169     */
170    private Properties cadServerProperties;
171
172    /**
173     * Constructor. Load the Properties file and initialize all CAD Simulator
174     * Managers and establish Manager data relationships. A
175     * CADSimulatorSocketHandler is instantiated and started to being listening
176     * for remote CAD connections. The CMSDiversionDB is initialized with the
177     * XML data(incomplete design).
178     *
179     * @param propertiesFile Filename of CAD Simulator properties file.
180     * @throws SimulationException if there is an error in initializing the CAD
181     * Simulator.
182     */
183    public CADServer(String propertiesFile) throws SimulationException
184    {
185
186        try
187        {
188            cadServerProperties = new Properties();
189            cadServerProperties.load(new FileInputStream(propertiesFile));
190            cadSimLogger.logp(Level.INFO, "CADServer", "Constructor",
191                    "Properties loaded from " + propertiesFile);
192        } catch (Exception e)
193        {
194            cadSimLogger.logp(Level.SEVERE, "CADServer", "Constructor",
195                    "Exception in reading properties file.", e);
196            JOptionPane.showMessageDialog(new JWindow(), e.getMessage() +
197                    "\nUser.Dir=" + System.getProperty("user.dir"),
198                    "Fatal Error - Exiting", JOptionPane.ERROR_MESSAGE);
199                       
200            throw new SimulationException(SimulationException.PROPERTY_READ_ERROR, e);
201        }
202
203        //Create the Coordinator and register it for RMI communicator.  Start the
204        //CAD Simulator Socket Handler to begin to accept connections from CAD Clients.
205        try
206        {
207            String userInterfaceName =
208                    cadServerProperties.getProperty(
209                    CAD_PROPERTIES.USER_INTERFACE.name);
210            if (userInterfaceName == null)
211            {
212                cadSimLogger.logp(Level.SEVERE, "CADServer", "Constructor",
213                        propertiesFile + " missing property for user interface.");
214                throw new SimulationException(SimulationException.PROPERTY_MISSING_ERROR);
215            }
216            try
217            {
218                Class uiClass = Class.forName(userInterfaceName);
219                Constructor<?> cons = uiClass.getConstructor(String.class);
220                theViewer = (CADViewer) cons.newInstance(propertiesFile);
221            } catch (Exception exc)
222            {
223                cadSimLogger.logp(Level.SEVERE, "CADServer", "Constructor",
224                        "Unable to instantiate user interface: " + userInterfaceName
225                        + " " + exc);
226                throw new SimulationException(SimulationException.INSTANTIATION_FAILURE);
227            }
228            theModel = new CADSimulatorState();
229            theModel.addObserver(theViewer);
230            /** Load the simulation time filename from properties */
231            String simTimeFilename =
232                    cadServerProperties.getProperty(
233                    CAD_PROPERTIES.ELAPSED_TIME_FILE.name);
234            if (simTimeFilename == null)
235            {
236                cadSimLogger.logp(Level.SEVERE, "CADServer", "Constructor",
237                        propertiesFile + " missing property for " + CAD_PROPERTIES.ELAPSED_TIME_FILE.name);
238                throw new SimulationException(SimulationException.PROPERTY_MISSING_ERROR);
239            }
240            /** Load the CAD comments log filename from properties */
241            String commentLogname =
242                    cadServerProperties.getProperty(
243                    CAD_PROPERTIES.CAD_COMMENTS_LOG.name);
244            if (commentLogname == null)
245            {
246                cadSimLogger.logp(Level.SEVERE, "CADServer", "Constructor",
247                        propertiesFile + " missing property for " + CAD_PROPERTIES.CAD_COMMENTS_LOG.name);
248                throw new SimulationException(SimulationException.PROPERTY_MISSING_ERROR);
249            }
250            theCoordinator = new Coordinator(theModel, simTimeFilename, commentLogname);
251
252            startRegistry(Integer.parseInt(
253                    cadServerProperties.getProperty(
254                    CAD_PROPERTIES.COOR_RMI_PORT.name).trim()));
255            startRegistry(Integer.parseInt(
256                    cadServerProperties.getProperty(
257                    CAD_PROPERTIES.CAD_RMI_PORT.name).trim()));
258
259            theSimulationCntrlMgr = new SimulationClockManager(theCoordinator);
260
261            theATMSMgr = new ATMSManager(
262                    cadServerProperties.getProperty(
263                    CAD_PROPERTIES.ATMS_PROP_FILE.name));
264           
265            theTrafficMgr = new TrafficModelManager(
266                    cadServerProperties.getProperty(
267                    CAD_PROPERTIES.TRAFFICMGR_PROP_FILE.name),
268                    theCoordinator);
269            theTrafficMgr.addObserver(theViewer);
270   
271            theMediaMgr = new MediaManager(
272                    cadServerProperties.getProperty(
273                    CAD_PROPERTIES.MEDIA_PROP_FILE.name),
274                    theATMSMgr, theModel);
275
276            theParamicsSimMgr = new ParamicsSimulationManager(
277                    cadServerProperties.getProperty(
278                    CAD_PROPERTIES.PARAMICS_PROP_FILE.name),
279                    theCoordinator, theMediaMgr);
280
281            theSoundPlayer = new SoundPlayer(
282                    cadServerProperties.getProperty(
283                    CAD_PROPERTIES.AUDIO_LOCATION.name));
284            theSoundPlayer.start();
285
286            theIncidentMgr = new IncidentManager(theCoordinator, theSoundPlayer);
287
288
289            //Begin accepting Client connections
290            CADSimulatorSocketHandler tmsh = new CADSimulatorSocketHandler(
291                    Integer.parseInt(cadServerProperties.getProperty(
292                    CAD_PROPERTIES.CLIENT_PORT.name).trim()));
293            tmsh.start();
294        } catch (RemoteException e)
295        {
296            cadSimLogger.logp(Level.SEVERE, "CADServer", "Constructor",
297                    "Exception in starting Coordinator.", e);
298
299            throw new SimulationException(SimulationException.BINDING, e);
300        }
301
302        //Load CMS Diversion Information from the XML file
303        try
304        {
305            if (cadServerProperties.getProperty(
306                    CAD_PROPERTIES.CMS_XML_FILE.name) != null)
307            {
308                CMSDiversionDB.getInstance().loadFromXML(
309                        DocumentBuilderFactory.newInstance().newDocumentBuilder()
310                        .parse(new File(cadServerProperties.getProperty(
311                        CAD_PROPERTIES.CMS_XML_FILE.name))));
312            }
313        } catch (Exception e)
314        {
315            cadSimLogger.logp(Level.SEVERE, "CADServer", "Constructor",
316                    "Exception in parsing CMSDiversion xml file.", e);
317
318            JOptionPane.showMessageDialog(new JWindow(), "Unable to open "
319                    + cadServerProperties.getProperty(CAD_PROPERTIES.CMS_XML_FILE.name),
320                    "Initialization Error", JOptionPane.WARNING_MESSAGE);
321        }
322
323        theViewer.setVisible(true);
324        // I think the traffic mgr has to run AFTER viewer is set visible, because
325        // inside run() it loads traffic events and wants to notify the view
326        // to update itself ... so the view must be visible first?
327        // When this stmt was prior to setVisible, we hung on setVisible.
328        theTrafficMgr.run();
329
330    }
331
332    /**
333     * Binds the Coordinator to an RMI port so that the SimulationManager can
334     * communicate with it, and so that the Coordinator can perform RMI callback
335     * method calls. The port numbers and RMI designators are parsed from the
336     * properties file file.
337     *
338     * @param theCoor A reference to the Coordinator object.
339     * @throws SimulationException if there are errors in binding the RMI to a
340     * port and name.
341     */
342    private void startRegistry(Integer regPort) throws SimulationException
343    {
344
345        try
346        {
347//            if (LocateRegistry.getRegistry(regPort) == null)
348//            {
349            LocateRegistry.createRegistry(regPort);
350            String registryURL = "rmi://localhost:" + regPort + "/coordinator";
351            Naming.rebind(registryURL, theCoordinator);
352//            }
353        } catch (Exception e)
354        {
355            throw new SimulationException(SimulationException.BINDING, e);
356        }
357    }
358
359    /**
360     * Method returns a String representation of the current time. String format
361     * is HHMM
362     *
363     * @return String representation of the current time.
364     */
365    public static String getCADTime()
366    {
367        String time = new String();
368
369        Calendar rightNow = Calendar.getInstance();
370
371        if (rightNow.get(Calendar.HOUR_OF_DAY) < 10)
372        {
373            time += "0";
374        }
375
376        time += (String.valueOf(rightNow.get(Calendar.HOUR_OF_DAY)));
377
378        if (rightNow.get(Calendar.MINUTE) < 10)
379        {
380            time += "0";
381        }
382
383        time += (String.valueOf(rightNow.get(Calendar.MINUTE)));
384
385        return time;
386    }
387
388    /**
389     * Returns a string representation of the current date. String format is:
390     * MMDDYY
391     *
392     * @return String format of the date.
393     */
394    public static String getCADDate()
395    {
396        String date = new String();
397
398        Calendar rightNow = Calendar.getInstance();
399
400        //Months are zero referenced
401        if (rightNow.get(Calendar.MONTH) + 1 < 10)
402        {
403            date += "0";
404        }
405
406        date += (String.valueOf(rightNow.get(Calendar.MONTH) + 1));
407
408        if (rightNow.get(Calendar.DAY_OF_MONTH) < 10)
409        {
410            date += "0";
411        }
412
413        date += (String.valueOf(rightNow.get(Calendar.DAY_OF_MONTH)));
414
415        if (rightNow.get(Calendar.YEAR) % 1000 < 10)
416        {
417            date += "0";
418        }
419
420        date += (String.valueOf(rightNow.get(Calendar.YEAR) % 1000));
421
422        return date;
423
424    }
425
426    /**
427     * Main class. Instantiate a CAD Simulator with the properties file
428     * specified on the command line or the default properties file
429     *
430     * @param args Command line arguments.
431     */
432    public static void main(String[] args)
433    {
434        if (System.getProperty("CONFIG_DIR") == null)
435        {
436            System.setProperty("CONFIG_DIR", "config");
437        }
438        if (System.getProperty("PROP_FILE") != null)
439        {
440            CONFIG_FILE_NAME = System.getProperty("PROP_FILE");
441        }
442        try
443        {
444            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
445            String propFile = System.getProperty("CONFIG_DIR")
446                    + System.getProperty("file.separator")
447                    + CONFIG_FILE_NAME;
448            new CADServer(propFile);
449        } catch (Exception e)
450        {
451            cadSimLogger.logp(Level.SEVERE, "CADServer", "Main",
452                    "Error initializing application.", e);
453
454            JOptionPane.showMessageDialog(new JWindow(), e.getMessage(),
455                    "Error - Program Exiting", JOptionPane.ERROR_MESSAGE);
456
457            System.exit(-1);
458        }
459
460    }
461}
Note: See TracBrowser for help on using the repository browser.