package tmcsim.paramicslog;
import java.io.FileInputStream;
import java.io.IOException;
import java.rmi.Naming;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import tmcsim.common.SimulationException;
import tmcsim.interfaces.CoordinatorInterface;
/**
* Logs communication from ParamicsCommunicator to ParamicsSimulator.
*
* The system property "PARAMICS_LOG_CONFIG" should be set to the path where the
* properties file for this class is located.
* The data for the properties file follows.
*
* -----------------------------------------------------------------
* Log File The file to write the communication to. CAD Simulator Host The host
* that runs the CAD Simulator. CAD Simulator RMI Port The port on the host that
* runs the CAD Simulator where the RMI Coordinator object is registered to.
* -----------------------------------------------------------------
* Example File:
* LogFile=c:\\log.txt CADSimulatorHost=localhost CADSimulatorRMIPort=4445
* -----------------------------------------------------------------
*
*
* @author Nathaniel Lehrer
* @version
*/
public class ParamicsLogFileHandler extends java.util.logging.FileHandler
{
/**
* Enmeration containing property names.
*
* @author Nathaniel Lehrer
*/
private enum PROPERTIES
{
LOG_FILE("LogFile"),
CAD_SIM_HOST("CADSimulatorHost"),
CAD_SIM_PORT("CADSimulatorRMIPort");
public String name;
private PROPERTIES(String n)
{
name = n;
}
}
/**
* Error logger.
*/
private static Logger paramLogger = Logger.getLogger("tmcsim.paramicslog");
/**
* Static instance.
*/
private static ParamicsLogFileHandler instance;
private static String propertiesFile;
/**
* Properties object.
*/
private static Properties paramicsLogProp;
/**
* File log entries are written to
*/
// private static String logFile;
/**
* Stores the log entries. This contains the same information logFile.
*/
private StringBuilder log;
/**
* Remote reference to the simulation
*/
private CoordinatorInterface theCoorInt;
/**
* Object for synchronizing IO
*/
Object lock;
/**
* Creates the singleton instance of this class.
*/
public static ParamicsLogFileHandler getInstance() throws IOException
{
System.setProperty("PARAMICS_LOG_PROPERTIES", "config/paramics_communicator_logging.properties");
// Has an instance been created yet?
if (instance == null)
{
try
{
if (System.getProperty("PARAMICS_LOG_PROPERTIES") != null)
{
propertiesFile = System.getProperty("PARAMICS_LOG_PROPERTIES");
paramicsLogProp = new Properties();
paramicsLogProp.load(new FileInputStream(propertiesFile));
if ((paramicsLogProp.getProperty(PROPERTIES.LOG_FILE.name)) == null)
{
throw new Exception("Properties file missing log file location.");
}
String logFile = paramicsLogProp.getProperty(PROPERTIES.LOG_FILE.name);
instance = new ParamicsLogFileHandler(logFile);
}
else
{
throw new Exception("PARAMICS_LOG_PROPERTIES system property not defined.");
}
} catch (Exception e)
{
instance = new ParamicsLogFileHandler();
paramLogger.logp(Level.WARNING, "ParamicsLog", "static initializer",
"Error occured initializing application", e);
JOptionPane.showMessageDialog(null, e.getMessage(),
"Error - ParamicsLog will not save log to file.",
JOptionPane.ERROR_MESSAGE);
}
}
return instance;
}
/**
* Creates an instance of ParamicsLog that does not write to a file when
* writeToLog is called.
*/
private ParamicsLogFileHandler() throws IOException
{
lock = new Object();
log = new StringBuilder("");
}
/**
* Creates an instance of ParamicsLog that writes to a file when writeToLog
* is called.
*
* @param propertiesFile
*/
private ParamicsLogFileHandler(String logFile) throws IOException
{
super(logFile);
lock = new Object();
log = new StringBuilder("");
//String logFile = null;
String CADSIMHost = null;
String CADSIMPort = null;
try
{
paramicsLogProp = new Properties();
paramicsLogProp.load(new FileInputStream(propertiesFile));
if ((CADSIMHost = paramicsLogProp.getProperty(PROPERTIES.CAD_SIM_HOST.name)) == null)
{
throw new Exception("Properties file missing CAD Simulator host.");
}
else if ((CADSIMPort = paramicsLogProp.getProperty(PROPERTIES.CAD_SIM_PORT.name)) == null)
{
throw new Exception("Properties file missing CAD Simulator RMI port.");
}
try
{
connect(CADSIMHost, CADSIMPort);
} catch (Exception e)
{
JOptionPane.showMessageDialog(null,
"ParamicsLog: Could not connect to remote Coordinator object.",
"Network Error", JOptionPane.ERROR_MESSAGE);
}
// try
// {
// createLogFile(logFile);
// } catch (Exception e)
// {
// JOptionPane.showMessageDialog(null,
// "ParamicsLog: Could not create new log file.",
// "File Error", JOptionPane.ERROR_MESSAGE);
// }
} catch (Exception e)
{
paramLogger.logp(Level.WARNING, "ParamicsLog", "ParamicsLog constructor",
"Properties file incorrect or missing.", e);
JOptionPane.showMessageDialog(null,
"ParamicsLog: Properties file invalid.",
"Invalid Configuration", JOptionPane.ERROR_MESSAGE);
}
}
/**
* Connect to the Coordinator's RMI object.
*
* @param hostname Host name of the CAD Simulator.
* @param portNumber Port number of the CAD Simulator RMI communication.
* @throws SimulationException if there is an error creating the RMI
* connection.
*/
private void connect(String hostname, String portNumber)
throws SimulationException
{
String coorIntURL = "";
try
{
coorIntURL = "rmi://" + hostname + ":" + portNumber + "/coordinator";
theCoorInt = (CoordinatorInterface) Naming.lookup(coorIntURL);
} catch (Exception e)
{
paramLogger.logp(Level.WARNING, "ParamicsLog",
"establishRMIConnection", "Unable to establish RMI "
+ "communication with the CAD Simulator. URL <" + coorIntURL + ">", e);
}
}
/**
* Accessor to the entries in the log. No file IO is used.
*
* @return The entries in the log.
*/
public String getLog()
{
return log.toString();
}
/**
* Writes an entry to the log. The simulator time when the message was sent
* is prepended to the entry. Entries are padded by a blank line before and
* after them. TODO: Ensure output is written in order of request.
*
* @param entry
*/
public void publish(LogRecord rec)
{
String time = "?";
String formattedEntry;
String entry = rec.getMessage();
if (theCoorInt != null)
{
try
{
time = formatTime(theCoorInt.getCurrentSimulationTime());
} catch (Exception e)
{
paramLogger.logp(Level.WARNING, "ParamicsLog",
"RMICommunication", "Unable to communicate with RMI object", e);
}
}
formattedEntry = "\n" + "\n" + entry + "\n";
log.append(formattedEntry);
rec.setMessage(formattedEntry);
super.publish(rec);
//ParamicsLogGUI.getInstance().update(this, entry);
}
/**
* Formats the time given in seconds to hh:mm:ss format.
*
* @param time The time in seconds.
*/
public String formatTime(long time)
{
long seconds = time % 60;
long minutes = (time - seconds) / 60;
long hours = (time - seconds - minutes * 60) / 60;
return padr(hours) + ":" + padr(minutes) + ":" + padr(seconds);
}
private String padr(long n)
{
if (n < 10)
{
return "0" + n;
}
{
return "" + n;
}
}
/**
* Accessor for static instance of this class.
*
* @return The instance of this class.
*/
// public static ParamicsLogFileHandler getInstance()
// {
//
// return instance;
// }
}