source: tmcsimulator/trunk/src/tmcsim/client/ClockClient.java @ 64

Revision 64, 8.3 KB checked in by jdalbey, 9 years ago (diff)

Renamed to ClockClient?, added build target for it.

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