package tmcsim.cadsimulator; import java.io.File; import java.io.FileInputStream; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.util.Calendar; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import javax.swing.JWindow; import javax.swing.UIManager; import javax.xml.parsers.DocumentBuilderFactory; import tmcsim.cadsimulator.db.CMSDiversionDB; import tmcsim.cadsimulator.managers.ATMSManager; import tmcsim.cadsimulator.managers.IncidentManager; import tmcsim.cadsimulator.managers.MediaManager; import tmcsim.cadsimulator.managers.ParamicsSimulationManager; import tmcsim.cadsimulator.managers.SimulationClockManager; import tmcsim.cadsimulator.managers.TrafficModelManager; import tmcsim.cadsimulator.viewer.model.CADSimulatorState; import tmcsim.common.SimulationException; import tmcsim.interfaces.CADViewer; /** * CADSimulator is main class for the CAD Simulator application. At construction * the Coordinator, CoordinatorViewer, and all CAD Simulator Managers are * initialized and data relationships are established. Simulation control is * managed through the Coordinator and Managers. The CADSimulator contains the * instances of all Manager Objects that are used to control the Simulation flow * of data.
*
* * The CADSimulator is initialized with a properties file containing the * following data items:
* * -----------------------------------------------------------------------------
* CADClientPort The port number to use for remote CAD Client connections.
* CoordinatorRMIPort The port number to use for binding the Coordinator.
* CMSDiversionXML The filepath for the xml file containing initialization data * for the Diversion "database." AudioFileLocation The root directory path where * audio files are referenced from.
* ParamicsProperties The filepath for the properties file to initialize the * ParamicsControlManager.
* ATMSProperties The filepath for the properties file to initialize the * ATMSManager.
* MediaProperties The filepath for the properties file to initialize the * MediaManager.
* ErrorFile The filename of the error file used for logging errors.
* ----------------------------------------------------------------------------
* Example File:
* CADClientPort = 4444
* CoordinatorRMIPort = 4445
* CMSDiversionXML = ../data/cmsdiversions.xml
* AudioFileLocation = ../audio/
* ParamicsProperties = ../config/paramics.properties
* ATMSProperties = ../config/atms.properties
* MediaProperties = ../config/media.properties
* ErrorFile = cad_sim_error.xml
*
* * @author Matthew Cechini (mcechini@calpoly.edu) jdalbey * @version $Date: 2009/04/17 16:27:46 $ $Revision: 1.5 $ */ public class CADServer { private static final String CONFIG_FILE_NAME = "cad_simulator_config.properties"; /** * Error logger. */ private static Logger cadSimLogger = Logger.getLogger("tmcsim.cadsimulator"); /** * Enumeration containing properties name values. See CADSimulator class * description for more information. * * @author Matthew * @see CADServer */ private static enum CAD_PROPERTIES { /** * RMI port to accept CAD Client connections. */ CLIENT_PORT("CADClientPort"), /** * RMI port to bind the Coordinator to for RMI communication. */ COOR_RMI_PORT("CoordinatorRMIPort"), CAD_RMI_PORT("CADRmiPort"), /** * Filepath for xml file containing diversion data. */ CMS_XML_FILE("CMSDiversionXML"), /** * Filepath for xml file containing dvd control data. */ DVD_XML_FILE("DVDPlayerXML"), /** * Filepath for xml file containing still image control data. */ IMAGE_XML_FILE("StillImagesXML"), /** * Root directory path where audio files are referenced from. */ AUDIO_LOCATION("AudioFileLocation"), /** * Filepath for the properties file to initialize the media manager. */ MEDIA_PROP_FILE("MediaProperties"), /** * Filepath for the properties file to initialize the paramics control * manager. */ PARAMICS_PROP_FILE("ParamicsProperties"), /** * Filepath for the properties file to initialize the atms manager. */ ATMS_PROP_FILE("ATMSProperties"), /** * Filepath for the properties file to initialize the traffic manager. */ TRAFFICMGR_PROP_FILE("TrafficMgrProperties"), /** * Class name of desired user interface. */ USER_INTERFACE("UserInterface"); public String name; private CAD_PROPERTIES(String nam) { name = nam; } }; /** NOTE: Protected fields are accessed by Coordinator */ /** * CADSimulatorViewer instance. */ protected static CADViewer theViewer; //protected static CADSimulatorViewer theViewer; //protected static CADConsoleViewer theConsole; protected static CADSimulatorState theModel; /** * Coordinator instance. */ protected static Coordinator theCoordinator; /** * SoundPlayer instance. */ protected static SoundPlayer theSoundPlayer = null; /** * SimulationControlManager instance. */ protected static SimulationClockManager theSimulationCntrlMgr = null; /** * ParamicsSimulationManager instance. */ protected static ParamicsSimulationManager theParamicsSimMgr = null; /** * IncidentManager instance. */ protected static IncidentManager theIncidentMgr = null; /** * MediaManager instance. */ protected static MediaManager theMediaMgr = null; /** * ATMSManager instance. */ protected static ATMSManager theATMSMgr = null; /** * Traffic Model Manager instance */ protected static TrafficModelManager theTrafficMgr = null; /** * Properties file for the CADSimulator. */ private Properties cadServerProperties; /** * Constructor. Load the Properties file and initialize all CAD Simulator * Managers and establish Manager data relationships. A * CADSimulatorSocketHandler is instantiated and started to being listening * for remote CAD connections. The CMSDiversionDB is initialized with the * XML data(incomplete design). * * @param propertiesFile Filename of CAD Simulator properties file. * @throws SimulationException if there is an error in initializing the CAD * Simulator. */ public CADServer(String propertiesFile) throws SimulationException { try { cadServerProperties = new Properties(); cadServerProperties.load(new FileInputStream(propertiesFile)); cadSimLogger.logp(Level.INFO, "CADSimulator", "Constructor", "Properties loaded from " + propertiesFile); } catch (Exception e) { cadSimLogger.logp(Level.SEVERE, "CADSimulator", "Constructor", "Exception in reading properties file.", e); JOptionPane.showMessageDialog(new JWindow(), e.getMessage() + "\nUser.Dir=" + System.getProperty("user.dir"), "Fatal Error - Exiting", JOptionPane.ERROR_MESSAGE); throw new SimulationException(SimulationException.PROPERTY_READ_ERROR, e); } //Create the Coordinator and register it for RMI communicator. Start the //CAD Simulator Socket Handler to begin to accept connections from CAD Clients. try { String userInterfaceName = cadServerProperties.getProperty( CAD_PROPERTIES.USER_INTERFACE.name); if (userInterfaceName == null) { cadSimLogger.logp(Level.SEVERE, "CADSimulator", "Constructor", propertiesFile + " missing property for user interface."); throw new SimulationException(SimulationException.PROPERTY_MISSING_ERROR); } try { Class uiClass = Class.forName(userInterfaceName); theViewer = (CADViewer) uiClass.newInstance(); } catch (Exception exc) { cadSimLogger.logp(Level.SEVERE, "CADSimulator", "Constructor", "Unable to instantiate user interface: " + userInterfaceName + " " + exc); throw new SimulationException(SimulationException.INSTANTIATION_FAILURE); } theModel = new CADSimulatorState(); theModel.addObserver(theViewer); theCoordinator = new Coordinator(theModel); startRegistry(Integer.parseInt( cadServerProperties.getProperty( CAD_PROPERTIES.COOR_RMI_PORT.name).trim())); startRegistry(Integer.parseInt( cadServerProperties.getProperty( CAD_PROPERTIES.CAD_RMI_PORT.name).trim())); theSimulationCntrlMgr = new SimulationClockManager(theCoordinator); theATMSMgr = new ATMSManager( cadServerProperties.getProperty( CAD_PROPERTIES.ATMS_PROP_FILE.name)); theTrafficMgr = new TrafficModelManager( cadServerProperties.getProperty( CAD_PROPERTIES.TRAFFICMGR_PROP_FILE.name), theCoordinator); theTrafficMgr.addObserver(theViewer); theTrafficMgr.run(); theMediaMgr = new MediaManager( cadServerProperties.getProperty( CAD_PROPERTIES.MEDIA_PROP_FILE.name), theATMSMgr, theModel); theParamicsSimMgr = new ParamicsSimulationManager( cadServerProperties.getProperty( CAD_PROPERTIES.PARAMICS_PROP_FILE.name), theCoordinator, theMediaMgr); theSoundPlayer = new SoundPlayer( cadServerProperties.getProperty( CAD_PROPERTIES.AUDIO_LOCATION.name)); theSoundPlayer.start(); theIncidentMgr = new IncidentManager(theCoordinator, theSoundPlayer); //Begin accepting Client connections CADSimulatorSocketHandler tmsh = new CADSimulatorSocketHandler( Integer.parseInt(cadServerProperties.getProperty( CAD_PROPERTIES.CLIENT_PORT.name).trim())); tmsh.start(); } catch (RemoteException e) { cadSimLogger.logp(Level.SEVERE, "CADSimulator", "Constructor", "Exception in starting Coordinator.", e); throw new SimulationException(SimulationException.BINDING, e); } //Load CMS Diversion Information from the XML file try { if (cadServerProperties.getProperty( CAD_PROPERTIES.CMS_XML_FILE.name) != null) { CMSDiversionDB.getInstance().loadFromXML( DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(new File(cadServerProperties.getProperty( CAD_PROPERTIES.CMS_XML_FILE.name)))); } } catch (Exception e) { cadSimLogger.logp(Level.SEVERE, "CADSimulator", "Constructor", "Exception in parsing CMSDiversion xml file.", e); JOptionPane.showMessageDialog(new JWindow(), "Unable to open " + cadServerProperties.getProperty(CAD_PROPERTIES.CMS_XML_FILE.name), "Initialization Error", JOptionPane.WARNING_MESSAGE); } theViewer.setVisible(true); } /** * Binds the Coordinator to an RMI port so that the SimulationManager can * communicate with it, and so that the Coordinator can perform RMI callback * method calls. The port numbers and RMI designators are parsed from the * properties file file. * * @param theCoor A reference to the Coordinator object. * @throws SimulationException if there are errors in binding the RMI to a * port and name. */ private void startRegistry(Integer regPort) throws SimulationException { try { // if (LocateRegistry.getRegistry(regPort) == null) // { LocateRegistry.createRegistry(regPort); String registryURL = "rmi://localhost:" + regPort + "/coordinator"; Naming.rebind(registryURL, theCoordinator); // } } catch (Exception e) { throw new SimulationException(SimulationException.BINDING, e); } } /** * Method returns a String representation of the current time. String format * is HHMM * * @return String representation of the current time. */ public static String getCADTime() { String time = new String(); Calendar rightNow = Calendar.getInstance(); if (rightNow.get(Calendar.HOUR_OF_DAY) < 10) { time += "0"; } time += (String.valueOf(rightNow.get(Calendar.HOUR_OF_DAY))); if (rightNow.get(Calendar.MINUTE) < 10) { time += "0"; } time += (String.valueOf(rightNow.get(Calendar.MINUTE))); return time; } /** * Returns a string representation of the current date. String format is: * MMDDYY * * @return String format of the date. */ public static String getCADDate() { String date = new String(); Calendar rightNow = Calendar.getInstance(); //Months are zero referenced if (rightNow.get(Calendar.MONTH) + 1 < 10) { date += "0"; } date += (String.valueOf(rightNow.get(Calendar.MONTH) + 1)); if (rightNow.get(Calendar.DAY_OF_MONTH) < 10) { date += "0"; } date += (String.valueOf(rightNow.get(Calendar.DAY_OF_MONTH))); if (rightNow.get(Calendar.YEAR) % 1000 < 10) { date += "0"; } date += (String.valueOf(rightNow.get(Calendar.YEAR) % 1000)); return date; } /** * Main class. Instantiate a CAD Simulator with the properties file * specified on the command line or the default properties file * * @param args Command line arguments. */ public static void main(String[] args) { if (System.getProperty("CONFIG_DIR") == null) { System.setProperty("CONFIG_DIR", "config"); } try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); String propFile = System.getProperty("CONFIG_DIR") + System.getProperty("file.separator") + CONFIG_FILE_NAME; new CADServer(propFile); } catch (Exception e) { cadSimLogger.logp(Level.SEVERE, "CADSimulator", "Main", "Error initializing application.", e); JOptionPane.showMessageDialog(new JWindow(), e.getMessage(), "Error - Program Exiting", JOptionPane.ERROR_MESSAGE); System.exit(-1); } } }