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 cadSimulatorProperties;
/**
* 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
{
cadSimulatorProperties = new Properties();
cadSimulatorProperties.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);
throw new SimulationException(SimulationException.INITIALIZE_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 =
cadSimulatorProperties.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.INITIALIZE_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.INITIALIZE_ERROR);
}
theModel = new CADSimulatorState();
theModel.addObserver(theViewer);
theCoordinator = new Coordinator(theModel);
startRegistry(Integer.parseInt(
cadSimulatorProperties.getProperty(
CAD_PROPERTIES.COOR_RMI_PORT.name).trim()));
startRegistry(Integer.parseInt(
cadSimulatorProperties.getProperty(
CAD_PROPERTIES.CAD_RMI_PORT.name).trim()));
theSimulationCntrlMgr = new SimulationClockManager(theCoordinator);
theATMSMgr = new ATMSManager(
cadSimulatorProperties.getProperty(
CAD_PROPERTIES.ATMS_PROP_FILE.name));
theTrafficMgr = new TrafficModelManager(
cadSimulatorProperties.getProperty(
CAD_PROPERTIES.TRAFFICMGR_PROP_FILE.name),
theCoordinator);
theMediaMgr = new MediaManager(
cadSimulatorProperties.getProperty(
CAD_PROPERTIES.MEDIA_PROP_FILE.name),
theATMSMgr, theModel);
theParamicsSimMgr = new ParamicsSimulationManager(
cadSimulatorProperties.getProperty(
CAD_PROPERTIES.PARAMICS_PROP_FILE.name),
theCoordinator, theMediaMgr);
theSoundPlayer = new SoundPlayer(
cadSimulatorProperties.getProperty(
CAD_PROPERTIES.AUDIO_LOCATION.name));
theSoundPlayer.start();
theIncidentMgr = new IncidentManager(theCoordinator, theSoundPlayer);
//Begin accepting Client connections
CADSimulatorSocketHandler tmsh = new CADSimulatorSocketHandler(
Integer.parseInt(cadSimulatorProperties.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 (cadSimulatorProperties.getProperty(
CAD_PROPERTIES.CMS_XML_FILE.name) != null)
{
CMSDiversionDB.getInstance().loadFromXML(
DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(new File(cadSimulatorProperties.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 "
+ cadSimulatorProperties.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);
}
}
}