1 /* DocumentEntryAutosaveThread.java
2  *
3  * created: Wed Aug 16 2000
4  *
5  * This file is part of Artemis
6  *
7  * Copyright (C) 2000  Genome Research Limited
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/io/DocumentEntryAutosaveThread.java,v 1.8 2008-08-01 12:50:16 tjc Exp $
24  */
25 
26 package uk.ac.sanger.artemis.io;
27 
28 import uk.ac.sanger.artemis.util.*;
29 import java.io.*;
30 
31 /**
32  *  This is a Thread that automatically saves a DocumentEntry to a backup file
33  *  called #entry_name# every 120 seconds.
34  *
35  *  @author Kim Rutherford <kmr@sanger.ac.uk>
36  *  @version $Id: DocumentEntryAutosaveThread.java,v 1.8 2008-08-01 12:50:16 tjc Exp $
37  **/
38 
39 public class DocumentEntryAutosaveThread extends Thread {
40   /**
41    *  Create a new DocumentEntryAutosaveThread with MIN_PRIORITY.
42    **/
DocumentEntryAutosaveThread(final DocumentEntry document_entry)43   public DocumentEntryAutosaveThread (final DocumentEntry document_entry) {
44     this.document_entry = document_entry;
45 
46     setPriority (Thread.MIN_PRIORITY);
47   }
48 
49   /**
50    *  The length of time (in seconds) to sleep for.
51    **/
52   private final static int SLEEP_TIME = 2 * 60 * 1000;
53 
54   /**
55    *  The main code for DocumentEntryAutosaveThread.  Attempts to autosave the
56    *  DocumentEntry every 2 minutes if it has unsaved changes.
57    **/
run()58   public void run () {
59     java.util.Date last_save_time = null;
60 
61     // Set to true the first time we save.
62     boolean have_saved = false;
63 
64     try {
65       // sleep for 240 seconds before starting - there is no point in attempting
66       // to save straight away
67       Thread.sleep (240000);
68     } catch (InterruptedException ie) {
69     }
70 
71     while (true) {
72       final String entry_name = document_entry.getName ();
73 
74       if (entry_name == null) {
75         continue;
76       }
77 
78       final File save_file;
79 
80       if(document_entry.getDocument() instanceof RemoteFileDocument ||
81           isMac())
82         save_file = new File(System.getProperty("user.dir")+
83                              System.getProperty("file.separator")+
84                              "#" + entry_name + "#");
85       else
86         save_file = new File ("#" + entry_name + "#");
87 
88       final java.util.Date last_change_time =
89         document_entry.getLastChangeTime ();
90 
91       // only save if there are unsaved changes and we haven't autosaved
92       // since the last change
93       if (document_entry.hasUnsavedChanges () &&
94           (last_save_time == null ||
95            last_change_time != null &&
96            last_change_time.after (last_save_time))) {
97         final Document save_document = new FileDocument (save_file);
98         try {
99           final Writer out_file = save_document.getWriter ();
100           document_entry.writeToStream (out_file);
101           out_file.close ();
102           have_saved = true;
103         } catch (IOException e) {
104           System.err.println ("warning: could not auto save to: " +
105                               save_document.getName () +
106                               " (will try again later)");
107         } catch (java.util.ConcurrentModificationException e) {
108           // this Exception means that the tree that stores the features has
109           // changed since we started writing.  since this thread doesn't
110           // change the tree, this exception is harmless, so we ignore it
111           // and try again later
112         }
113         catch(NullPointerException npe)
114         {
115           break;
116         }
117       } else {
118         if (have_saved) {
119           // auto save file isn't needed now so turn it into a backup file
120           final File new_name;
121 
122           if(document_entry.getDocument() instanceof RemoteFileDocument ||
123              isMac())
124             new_name = new File (System.getProperty("user.dir")+
125                                  System.getProperty("file.separator")+
126                                  entry_name + "~");
127           else
128             new_name = new File (entry_name + "~");
129 
130           save_file.renameTo (new_name);
131         } else {
132           // the file wasn't made by us so leave it
133         }
134       }
135 
136       last_save_time = last_change_time;
137 
138       try {
139         Thread.sleep (SLEEP_TIME);
140       } catch (InterruptedException ie) {
141       }
142     }
143   }
144 
isMac()145   private boolean isMac()
146   {
147     return System.getProperty("mrj.version") != null ||
148            System.getProperty("os.name").toLowerCase().indexOf("mac") >= 0;
149   }
150 
151   /**
152    *  The DocumentEntry we will save.
153    **/
154   private DocumentEntry document_entry;
155 }
156