source: tmcsimulator/trunk/src/tmcsim/paramicslog/ParamicsLog.java @ 664

Revision 664, 9.6 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.paramicslog;
2
3import java.io.File;
4import java.io.FileInputStream;
5import java.io.FileWriter;
6import java.io.IOException;
7import java.rmi.Naming;
8import java.util.Observable;
9import java.util.Properties;
10import java.util.logging.Level;
11import java.util.logging.Logger;
12import javax.swing.JOptionPane;
13import tmcsim.common.SimulationException;
14import tmcsim.interfaces.CoordinatorInterface;
15import tmcsim.paramicslog.gui.ParamicsLogGUI;
16
17/**
18 * Logs communication from ParamicsCommunicator to ParamicsSimulator.
19 *
20 * The system property "PARAMICS_LOG_CONFIG" should be set to the path where the
21 * properties file for this class is located. <br><br>
22 * The data for the properties file follows. <br>
23 * <code>
24 * -----------------------------------------------------------------<br>
25 * Log File The file to write the communication to. CAD Simulator Host The host
26 * that runs the CAD Simulator. CAD Simulator RMI Port The port on the host that
27 * runs the CAD Simulator where the RMI Coordinator object is registered to.
28 * -----------------------------------------------------------------<br>
29 * Example File: <br>
30 * LogFile=c:\\log.txt CADSimulatorHost=localhost CADSimulatorRMIPort=4445
31 * -----------------------------------------------------------------<br>
32 * </code>
33 *
34 * @author Nathaniel Lehrer
35 * @version
36 */
37public class ParamicsLog extends Observable
38{
39
40    /**
41     * Enmeration containing property names.
42     *
43     * @author Nathaniel Lehrer
44     */
45    private enum PROPERTIES
46    {
47
48        LOG_FILE("LogFile"),
49        CAD_SIM_HOST("CADSimulatorHost"),
50        CAD_SIM_PORT("CADSimulatorRMIPort");
51        public String name;
52
53        private PROPERTIES(String n)
54        {
55            name = n;
56        }
57    }
58    private static final String CONFIG_FILE_NAME = "logging_paramics_communicator.properties";
59    /**
60     * Error logger.
61     */
62    private static Logger paramLogger = Logger.getLogger("tmcsim.paramicslog");
63    /**
64     * Static instance.
65     */
66    private static ParamicsLog instance;
67    /**
68     * Properties object.
69     */
70    private Properties paramicsLogProp;
71    /**
72     * File log entries are written to
73     */
74    private File logFile;
75    /**
76     * Stores the log entries. This contains the same information logFile.
77     */
78    private StringBuilder log;
79    /**
80     * Remote reference to the simulation
81     */
82    private CoordinatorInterface theCoorInt;
83    /**
84     * Object for synchronizing IO
85     */
86    Object lock;
87
88    /**
89     * Creates the singleton instance of this class.
90     */
91    static
92    {
93        try
94        {
95            if (System.getProperty("CONFIG_DIR") == null)
96            {
97                System.setProperty("CONFIG_DIR", "config");
98            }
99
100            instance = new ParamicsLog(System.getProperty("CONFIG_DIR") + System.getProperty("file.separator") + CONFIG_FILE_NAME);
101        } catch (Exception e)
102        {
103            instance = new ParamicsLog();
104
105            paramLogger.logp(Level.WARNING, "ParamicsLog", "static initializer",
106                    "Error occured initializing application", e);
107
108            JOptionPane.showMessageDialog(null, e.getMessage(),
109                    "Error - ParamicsLog will not save log to file.",
110                    JOptionPane.ERROR_MESSAGE);
111        }
112
113        instance.addObserver(ParamicsLogGUI.getInstance());
114    }
115
116    /**
117     * Creates an instance of ParamicsLog that does not write to a file when
118     * writeToLog is called.
119     */
120    private ParamicsLog()
121    {
122
123        lock = new Object();
124        log = new StringBuilder("");
125    }
126
127    /**
128     * Creates an instance of ParamicsLog that writes to a file when writeToLog
129     * is called.
130     *
131     * @param propertiesFile
132     */
133    private ParamicsLog(String propertiesFile)
134    {
135        this();
136
137        String logFile = null;
138        String CADSIMHost = null;
139        String CADSIMPort = null;
140
141        try
142        {
143            paramicsLogProp = new Properties();
144            paramicsLogProp.load(new FileInputStream(propertiesFile));
145
146            if ((logFile = paramicsLogProp.getProperty(PROPERTIES.LOG_FILE.name)) == null)
147            {
148                throw new Exception("Properties file missing log file location.");
149            }
150            else if ((CADSIMHost = paramicsLogProp.getProperty(PROPERTIES.CAD_SIM_HOST.name)) == null)
151            {
152                throw new Exception("Properties file missing CAD Simulator host.");
153            }
154            else if ((CADSIMPort = paramicsLogProp.getProperty(PROPERTIES.CAD_SIM_PORT.name)) == null)
155            {
156                throw new Exception("Properties file missing CAD Simulator RMI port.");
157            }
158
159            try
160            {
161                connect(CADSIMHost, CADSIMPort);
162            } catch (Exception e)
163            {
164                JOptionPane.showMessageDialog(null,
165                        "ParamicsLog: Could not connect to remote Coordinator object.",
166                        "Network Error", JOptionPane.ERROR_MESSAGE);
167            }
168
169            try
170            {
171                createLogFile(logFile);
172            } catch (Exception e)
173            {
174                JOptionPane.showMessageDialog(null,
175                        "ParamicsLog: Could not create new log file.",
176                        "File Error", JOptionPane.ERROR_MESSAGE);
177            }
178
179        } catch (Exception e)
180        {
181
182            paramLogger.logp(Level.WARNING, "ParamicsLog", "ParamicsLog constructor",
183                    "Properties file incorrect or missing.", e);
184
185            JOptionPane.showMessageDialog(null,
186                    "ParamicsLog: Properties file invalid.",
187                    "Invalid Configuration", JOptionPane.ERROR_MESSAGE);
188        }
189    }
190
191    /**
192     * Creates the log file.
193     *
194     * @param filePath The path to the file including the file name.
195     * @throws IOException If the log file could not be created.
196     */
197    private void createLogFile(String filePath) throws IOException
198    {
199        try
200        {
201            logFile = new File(filePath);
202
203            if (logFile.exists())
204            {
205                logFile.delete();
206            }
207
208            logFile.createNewFile();
209
210        } catch (Exception e)
211        {
212
213            logFile = null;
214
215            paramLogger.logp(Level.WARNING, "ParamicsLog", "ParamicsLog constructor",
216                    "Could not create new log file.", e);
217
218            throw new IOException("Could not create log file.");
219        }
220    }
221
222    /**
223     * Connect to the Coordinator's RMI object.
224     *
225     * @param hostname Host name of the CAD Simulator.
226     * @param portNumber Port number of the CAD Simulator RMI communication.
227     * @throws SimulationException if there is an error creating the RMI
228     * connection.
229     */
230    private void connect(String hostname, String portNumber)
231            throws SimulationException
232    {
233
234        String coorIntURL = "";
235
236        try
237        {
238            coorIntURL = "rmi://" + hostname + ":" + portNumber + "/coordinator";
239
240            theCoorInt = (CoordinatorInterface) Naming.lookup(coorIntURL);
241        } catch (Exception e)
242        {
243            paramLogger.logp(Level.WARNING, "ParamicsLog",
244                    "establishRMIConnection", "Unable to establish RMI "
245                    + "communication with the CAD Simulator.  URL <" + coorIntURL + ">", e);
246        }
247    }
248
249    /**
250     * Accessor to the entries in the log. No file IO is used.
251     *
252     * @return The entries in the log.
253     */
254    public String getLog()
255    {
256
257        return log.toString();
258    }
259
260    /**
261     * Writes an entry to the log. The simulator time when the message was sent
262     * is prepended to the entry. Entries are padded by a blank line before and
263     * after them. TODO: Ensure output is written in order of request.
264     *
265     * @param entry
266     */
267    public void writeToLog(String entry)
268    {
269
270        String time = "?";
271        String formattedEntry;
272
273        if (theCoorInt != null)
274        {
275            try
276            {
277                time = formatTime(theCoorInt.getCurrentSimulationTime());
278            } catch (Exception e)
279            {
280                paramLogger.logp(Level.WARNING, "ParamicsLog",
281                        "RMICommunication", "Unable to communicate with RMI object", e);
282            }
283        }
284
285        formattedEntry = "\n" + "<!-- Time written to file: " + time + " -->\n" + entry + "\n";
286        log.append(formattedEntry);
287
288        if (logFile != null)
289        {
290            try
291            {
292                synchronized (lock)
293                {
294                    FileWriter writer = new FileWriter(logFile, true);
295                    writer.append(formattedEntry);
296                    writer.flush();
297                    writer.close();
298                }
299            } catch (IOException e)
300            {
301                paramLogger.logp(Level.WARNING, "ParamicsLog", "writeToLog",
302                        "Could not write to log file.", e);
303            }
304        }
305
306        setChanged();
307        notifyObservers(entry);
308    }
309
310    /**
311     * Formats the time given in seconds to hh:mm:ss format.
312     *
313     * @param time The time in seconds.
314     */
315    public String formatTime(long time)
316    {
317        long seconds = time % 60;
318        long minutes = (time - seconds) / 60;
319        long hours = (time - seconds - minutes * 60) / 60;
320
321        return padr(hours) + ":" + padr(minutes) + ":" + padr(seconds);
322    }
323
324    private String padr(long n)
325    {
326        if (n < 10)
327        {
328            return "0" + n;
329        }
330        {
331            return "" + n;
332        }
333    }
334
335    /**
336     * Accessor for static instance of this class.
337     *
338     * @return The instance of this class.
339     */
340    public static ParamicsLog getInstance()
341    {
342
343        return instance;
344    }
345}
Note: See TracBrowser for help on using the repository browser.