source: tmcsimulator/trunk/src/tmcsim/client/ATMSDriverClient.java @ 102

Revision 102, 8.9 KB checked in by jdalbey, 9 years ago (diff)

ATMSDriverClient.java New skeleton for a CAD Client shell for ATMS Driver.

Line 
1package tmcsim.client;
2
3import java.awt.event.ActionEvent;
4import java.awt.event.ActionListener;
5import java.io.FileInputStream;
6import java.rmi.Naming;
7import java.rmi.RemoteException;
8import java.rmi.server.UnicastRemoteObject;
9import java.util.Properties;
10import java.util.concurrent.TimeUnit;
11import java.util.logging.Level;
12import java.util.logging.Logger;
13import javax.swing.JOptionPane;
14import javax.swing.JWindow;
15import javax.swing.Timer;
16import javax.swing.UIManager;
17import tmcsim.common.SimulationException;
18import tmcsim.interfaces.CADClientInterface;
19import tmcsim.interfaces.CoordinatorInterface;
20
21/**
22 * Skeleton for ATMS Driver that reads a "batch" file of highway
23 * status update commands.
24 * It operates as a client of the
25 * CAD server, using RMI to poll the server every second for the current
26 * simulation clock time.  It uses the simulation clock time
27 * to fire update commands at the desired time.
28 * Note: Sim Mgr must be running before starting this application.
29 *
30 * @author jdalbey
31 */
32public class ATMSDriverClient extends UnicastRemoteObject implements
33        CADClientInterface
34{
35    /**
36     * Error logger.
37     */
38    private static Logger cadClientLogger = Logger.getLogger("tmcsim.client");
39
40    @Override
41    public void refresh() throws RemoteException
42    {
43        throw new UnsupportedOperationException("Not supported yet.");
44    }
45
46    /**
47     * Enumeration containing properties name values. See CADClient class
48     * description for more information.
49     *
50     * @author Matthew Cechini
51     * @see CADClient
52     */
53    private static enum PROPERTIES
54    {
55        CAD_SIM_HOST("CADSimulatorHost"), CAD_SIM_PORT("CADSimulatorSocketPort"), CAD_RMI_PORT(
56        "CADRmiPort"), CLIENT_CAD_POS("CADPosition"), CLIENT_USER_ID(
57        "CADUserID"), KEYBOARD_TYPE("KeyboardType"), DISPLAY_TYPE(
58        "DisplayType");
59        public String name;
60
61        private PROPERTIES(String n)
62        {
63            name = n;
64        }
65    }
66    /**
67     * CADClientSocket Object to handle socket communication between the Client
68     * and CAD Simulator.
69     */
70    private CADClientSocket theClientSocket;
71
72    /**
73     * Properties object for the CADClient class.
74     */
75    private Properties cadClientProp;
76    /**
77     * RMI interface for communication with the remote Coordinator.
78     */
79    private static CoordinatorInterface theCoorInt;
80    /**
81     * reference to itself to be used for disconnecting from CADSimulator
82     */
83    private CADClientInterface client = this;
84    private static final String CONFIG_FILE_NAME = "cad_client_config.properties";
85    private final static int ONE_SECOND = 1000;
86
87    /**
88     * Constructor. Initialize data from parsed properties file. Create a socket
89     * connection to the CADSimulator.
90     *
91     * @param propertiesFile File path (absolute or relative) to the properties
92     * file containing configuration data.
93     */
94    public ATMSDriverClient(String propertiesFile) throws SimulationException,
95            RemoteException
96    {
97        if (!verifyProperties(propertiesFile))
98        {
99            System.exit(0);
100        }
101
102        connect(cadClientProp.getProperty(PROPERTIES.CAD_SIM_HOST.name).trim(),
103                cadClientProp.getProperty(PROPERTIES.CAD_RMI_PORT.name).trim());
104
105        // READ THE BATCH FILE OF COMMANDS and put in a queue
106        // Consider special cases:  1) time to fire first command
107        // has already past when application starts.
108        // 2.  Two commands have same fire time specified.
109        // 3.  How to "override" a command, to clear an incident.
110       
111        // Create a timer that fetches the simulation time every second.
112        Timer timer = new Timer(ONE_SECOND, new ActionListener()
113        {
114            public void actionPerformed(ActionEvent e)
115            {
116                try
117                {
118                    long simtime = theCoorInt.getCurrentSimulationTime();
119                    // Check the queue of commands to see if the first
120                    // item matches the current time.  IF so,
121                    // issue that command and remove it from queue.
122                   
123                    //theView.updateTime("" + formatInterval(simtime));
124                } catch (RemoteException ex)
125                {
126                    Logger.getLogger(ATMSDriverClient.class.getName()).log(Level.SEVERE, null, ex);
127                }
128            }
129        });
130        timer.start();
131
132        ensureProperShutdown();
133    }
134
135    /**
136     * Connect to the Coordinator's RMI object, and register this object for
137     * callback with the Coordinator.
138     *
139     * @param hostname Host name of the CAD Simulator.
140     * @param portNumber Port number of the CAD Simulator RMI communication.
141     * @throws SimulationException if there is an error creating the RMI
142     * connection.
143     */
144    protected void connect(String hostname, String portNumber)
145            throws SimulationException
146    {
147
148        String coorIntURL = "";
149
150        try
151        {
152            coorIntURL = "rmi://" + hostname + ":" + portNumber
153                    + "/coordinator";
154            theCoorInt = (CoordinatorInterface) Naming.lookup(coorIntURL);
155            theCoorInt.registerForCallback(this);
156        } catch (Exception e)
157        {
158            throw new SimulationException(SimulationException.CAD_SIM_CONNECT,
159                    e);
160        }
161    }
162
163    /**
164     * This method verifies that the CAD Simulator Host and Port values are not
165     * null. Also, if a CAD Position or User ID do not exist in the properties
166     * file, the user is prompted to enter values. These values are written to
167     * the properties file. If the user cancels the process of entering these
168     * values, the verification fails.
169     *
170     * @param propertiesFile File path (absolute or relative) to the properties
171     * file containing configuration data.
172     * @return True if the properties file is valid, false if not.
173     * @throws SimulationException if there is an exception in verifying the
174     * properties file, or if the user cancels input.
175     */
176    private boolean verifyProperties(String propertiesFile)
177            throws SimulationException
178    {
179
180        // Load the properties file.
181        try
182        {
183            cadClientProp = new Properties();
184            cadClientProp.load(new FileInputStream(propertiesFile));
185        } catch (Exception e)
186        {
187            cadClientLogger.logp(Level.SEVERE, "SimulationManager",
188                    "Constructor", "Exception in reading properties file.", e);
189
190            throw new SimulationException(SimulationException.INITIALIZE_ERROR,
191                    e);
192        }
193
194
195        // Ensure that the properties file does not have null values for the
196        // CAD Simulator's connection information.
197        if (cadClientProp.getProperty(PROPERTIES.CAD_SIM_HOST.name) == null
198                || cadClientProp.getProperty(PROPERTIES.CAD_SIM_PORT.name) == null)
199        {
200            cadClientLogger.logp(Level.SEVERE, "SimulationManager",
201                    "Constructor", "Null value in properties file.");
202            throw new SimulationException(SimulationException.INITIALIZE_ERROR);
203        }
204
205        return true;
206    }
207
208    /**
209     * Format a time in seconds as HH:MM:SS
210     *
211     * @param l
212     * @return
213     */
214    private String formatInterval(final long l)
215    {
216        final long hr = TimeUnit.SECONDS.toHours(l);
217        final long min = TimeUnit.SECONDS.toMinutes(l - TimeUnit.HOURS.toSeconds(hr));
218        final long sec = TimeUnit.SECONDS.toSeconds(l - TimeUnit.HOURS.toSeconds(hr) - TimeUnit.MINUTES.toSeconds(min));
219        return String.format("%02d:%02d:%02d", hr, min, sec);
220    }
221
222    public void ensureProperShutdown()
223    {
224        Runtime.getRuntime().addShutdownHook(new Thread()
225        {
226            public void run()
227            {
228                try
229                {
230                    theCoorInt.unregisterForCallback(client);
231                } catch (RemoteException e)
232                {
233                    e.printStackTrace();
234                }
235            }
236        });
237    }
238
239    /**
240     * Construct the CADClient with the properties file path, either from the
241     * command line arguments or default.
242     *
243     * @param args Command line arguments.
244     */
245    public static void main(String[] args)
246    {
247        if (System.getProperty("CONFIG_DIR") == null)
248        {
249            System.setProperty("CONFIG_DIR", "config");
250        }
251
252        try
253        {
254            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
255            new ATMSDriverClient(System.getProperty("CONFIG_DIR") + System.getProperty("file.separator") + CONFIG_FILE_NAME);
256
257        } catch (Exception e)
258        {
259            cadClientLogger.logp(Level.SEVERE, "SimulationManager", "Main",
260                    "Error initializing application.");
261
262            JOptionPane.showMessageDialog(new JWindow(), e.getMessage(),
263                    "Error - Program Exiting", JOptionPane.ERROR_MESSAGE);
264
265            System.exit(-1);
266        }
267
268    }
269}
Note: See TracBrowser for help on using the repository browser.