source: tmcsimulator/trunk/src/tmcsim/paramicscommunicator/ParamicsFileWriter.java @ 41

Revision 41, 9.5 KB checked in by jdalbey, 10 years ago (diff)

Hack CAD Simulator and CAD Client to display Neil's custom Cardfile.xml.

Line 
1package tmcsim.paramicscommunicator;
2
3import java.io.File;
4import java.io.FileWriter;
5import java.io.IOException;
6import java.util.LinkedList;
7import java.util.Observable;
8import java.util.Timer;
9import java.util.TimerTask;
10import java.util.logging.Level;
11import java.util.logging.Logger;
12import org.apache.xml.serialize.OutputFormat;
13import org.apache.xml.serialize.XMLSerializer;
14import org.w3c.dom.Element;
15import tmcsim.paramicscommunicator.FileIOUpdate.IO_TYPE;
16
17/**
18 * The ParamicsFileWriter handles writing messages to a target file which is
19 * read by Paramics. Messages are received through the writeMessage() method.
20 * This object handles queueing messages and writing as the file becomes
21 * available. New data is written to the target file when it has been modified
22 * (cleared) by Paramics. If this does not happen, messages are queued and a
23 * timer is used to periodically determine if the file has become available for
24 * writing.
25 *
26 * @author Matthew Cechini
27 * @version
28 */
29public class ParamicsFileWriter extends Observable
30{
31
32    /**
33     * Duration (in ms) that the TimerTask will be scheduled to retry writing to
34     * the target file. Default = 2000ms
35     */
36    private static long TIMER_DURATION = 2000;
37    /**
38     * Error Logger.
39     */
40    private Logger paramLogger = Logger.getLogger("tmcsim.paramicscommunicator");
41    /**
42     * Linked List of messages that have been received
43     */
44    private LinkedList<Element> queuedMessages = null;
45    /**
46     *
47     */
48    private String writerID = null;
49    /**
50     * File name of the file where data is written
51     */
52    private String outputFile = null;
53    /**
54     * FileWriter used to write data to the output file.
55     */
56    private FileWriter fileWriter = null;
57    /**
58     * Value (seconds since 1/1/1970) of output file's last modifcation time
59     */
60    private long lastModified = 0;
61    /**
62     * Timer used to schedule file writing tasks.
63     */
64    private Timer writerTimer = null;
65    /**
66     * Synchronizing lock to protect File IO and message queuing.
67     */
68    private Object lock = null;
69
70    /**
71     * A TimerTask to retry writing messages that have been queued within this
72     * ParamicsWriter. If a message has been queued, see if the target file has
73     * been modified since last write. If so, write the first queued message to
74     * the file and remove the message from the queue. If writing is
75     * unsuccessful, do not remove the message from the queue. If there are no
76     * more messages in the queue, cancel this timer.
77     */
78    private class WriterTimerTask extends TimerTask
79    {
80
81        public void run()
82        {
83
84            synchronized (lock)
85            {
86                paramLogger.log(Level.INFO, "ParamicsFileWriter, WriterTimerTask "
87                        + "run() started, current queue size = " + queuedMessages.size());
88
89                //if we've queued something, continue.
90                if (queuedMessages.size() > 0)
91                {
92
93                    //if file has been modified, write to it
94                    // if file has been modifed by Paramics (i.e, cleared) since we
95                    // last wrote to it, then it's available for us to write to.
96                    if (lastModified < new File(outputFile).lastModified())
97                    {
98                        try
99                        {
100                            writeToFile(queuedMessages.getFirst());
101                            queuedMessages.remove(0);
102                        } catch (IOException ioe)
103                        {
104                            paramLogger.logp(Level.SEVERE, "ParamicsFileWriter.WriterTimerTask",
105                                    "run()", "Exception in writing to the target file: "
106                                    + outputFile + ".  Queue size = " + queuedMessages.size(), ioe);
107                        }
108
109                        //all queued messages gone, cancel timer
110                        if (queuedMessages.size() == 0)
111                        {
112                            this.cancel();
113                        }
114                    }
115                }
116            }
117        }
118    }
119
120    /**
121     * Constructor. Initialize data objects. If the target file exists, delete
122     * it, and then create a new file.
123     *
124     * @param workingDir Directory path where the output file is to be written
125     * @param mess The ParamicsCommMessage containing the outputFile filename.
126     */
127    public ParamicsFileWriter(String id, String workingDir, String targetFile)
128    {
129
130        try
131        {
132            writerID = id;
133
134            queuedMessages = new LinkedList<Element>();
135            lock = new Object();
136
137            outputFile = workingDir + targetFile;
138
139            File tempFile = new File(outputFile);
140            if (tempFile.exists())
141            {
142                tempFile.delete();
143            }
144
145            tempFile.createNewFile();
146
147            writerTimer = new Timer();
148
149        } catch (IOException ioe)
150        {
151            paramLogger.logp(Level.SEVERE, "ParamicsFileWriter", "Constructor",
152                    "Unable to create Paramics File Writer.", ioe);
153        }
154
155    }
156
157    /**
158     * Method is called when a message has been received from the CAD Simulator.
159     * If the message queue is not empty, add the new message to the queue. If
160     * the output file has not been modified (read) since last write, add the
161     * message to the queue and set a timer to repeatedly check for modification
162     * to the output file. Else, write the new message to the file. If there is
163     * an error in writing the data, queue the message start a timer to retry
164     * the writing.
165     *
166     * @param newMessage The received message which is to be written to the
167     * output file.
168     */
169    public void writeMessage(Element messageElem)
170    {
171
172        synchronized (lock)
173        {
174//            paramLogger.log(Level.INFO, "ParamicsFileWriter, writeMessage "
175//                    + "current queue size = " + queuedMessages.size());
176            double freebytes =  Runtime.getRuntime().freeMemory();
177            freebytes = freebytes / 1000000;
178            paramLogger.log(Level.INFO, "ParamicsFileWriter: "
179                    + freebytes + " MB free");
180           
181            //messages already queued... get in line, don't need to start the
182            // timer task.
183            if (queuedMessages.size() > 0)
184            {
185                queuedMessages.add(messageElem);
186
187//                paramLogger.log(Level.INFO, "Queueing message, new queue "
188//                        + "size = " + queuedMessages.size());
189            }
190            // No message queued, see if outputfile has been updated since
191            // the last time we wrote to it.
192            //No modification since last write. (first queue)
193            else if (lastModified >= new File(outputFile).lastModified())
194            {
195//                paramLogger.log(Level.INFO, "ParamicsFileWriter, writeMessage "
196//                        + "adding msg to queue.");
197                queuedMessages.add(messageElem);
198                // Start a timer to periodically see if the queue can be written
199                writerTimer.scheduleAtFixedRate(new WriterTimerTask(),
200                        0L, TIMER_DURATION);
201
202//                paramLogger.log(Level.INFO, "First message queued");
203            } 
204            //free and clear, write.
205            // last time we wrote is < modified date on file,
206            // so the file has been changed by Modeler since last time we wrote to it.
207            else
208            {
209//                paramLogger.log(Level.INFO, "ParamicsFileWriter, writeMessage "
210//                        + "try to writeToFile" + outputFile);
211                try
212                {
213                    writeToFile(messageElem);
214                } catch (IOException ioe)
215                {
216                    paramLogger.logp(Level.SEVERE, "ParamicsFileWriter",
217                            "writeMessage()", "Exception in writing to the "
218                            + "target file: " + outputFile, ioe);
219
220                    queuedMessages.add(messageElem);
221
222                    writerTimer.scheduleAtFixedRate(new WriterTimerTask(),
223                            0L, TIMER_DURATION);
224                }
225//                paramLogger.log(Level.INFO, "ParamicsFileWriter, writeMessage "
226//                        + "writeToFile succeeded.");
227            }
228        }
229    }
230
231    /**
232     * Method writes data to the output file.
233     *
234     * @param output Data to be written to the file.
235     */
236    private void writeToFile(Element output) throws IOException
237    {
238
239        fileWriter = new FileWriter(outputFile);
240
241        OutputFormat of = new OutputFormat("XML", "ISO-8859-1", true);
242        of.setIndent(1);
243        of.setIndenting(true);
244
245        XMLSerializer serializer = new XMLSerializer(fileWriter, of);
246        serializer.asDOMSerializer();
247        serializer.serialize(output);
248
249        /**
250         * Added by Nathaniel Lehrer
251         */
252        try
253        {
254            java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
255            new XMLSerializer(outputStream, of).serialize(output);
256            tmcsim.paramicslog.ParamicsLog.getInstance().writeToLog(outputStream.toString());
257        } catch (Exception e)
258        {
259            System.out.println(e);
260        }
261        /**
262         * End Add by Nathaniel Lehrer
263         */
264        fileWriter.flush();
265        fileWriter.close();
266
267        lastModified = new File(outputFile).lastModified();
268
269        setChanged();
270        notifyObservers(new FileIOUpdate(IO_TYPE.WRITE, writerID, new File(outputFile).length()));
271
272    }
273}
Note: See TracBrowser for help on using the repository browser.