source: trunk/gli/src/org/greenstone/gatherer/collection/SaveCollectionTask.java@ 5564

Last change on this file since 5564 was 5564, checked in by mdewsnip, 21 years ago

Many more small improvements and tooltips added. Still more to come!

  • Property svn:keywords set to Author Date Id Revision
File size: 12.5 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.collection;
38
39import java.io.*;
40import java.util.*;
41import javax.swing.*;
42import org.greenstone.gatherer.Gatherer;
43import org.greenstone.gatherer.collection.Collection;
44import org.greenstone.gatherer.util.Utility;
45
46/** The actually saving of a collection must run in a thread other than the AWTEvent thread, or else the save progress box will never get updated. To that end this class provides a threaded save method, which saves the various parts of the collection to the appropriate disk location.
47 * @author John Thompson, Greenstone Digital Library, University of Waikato
48 * @version 2.3
49 */
50public class SaveCollectionTask
51 extends Thread {
52 private boolean close_after = false;
53 /** Should we exit the Gatherer once this save is complete. */
54 private boolean exit_after = false;
55 /** Do we run the import scripts once this save is complete. */
56 private boolean import_after = false;
57 /** The current collection. */
58 private Collection collection = null;
59 /** The filename of the collection we are saving. */
60 private String name = null;
61 static final private int CLOSE_COLLECTION = 0;
62 static final private int COLLECTION_COPIED = 1;
63 static final private int COLLECTION_SAVED = 2;
64 static final private int COLLECTION_CFG_SAVED = 3;
65 static final private int COPY_COLLECTION = 4;
66 static final private int MAKE_COLLECTION = 5;
67 static final private int METADATA_SAVED = 6;
68 static final private int METADATA_XML_SAVED = 7;
69 static final private int OPEN_COLLECTION = 8;
70 static final private int RESTORE_COLLECTION = 9;
71 /** Constructor.
72 * @param name The filename of the collection we are saving as.
73 */
74 public SaveCollectionTask(Collection collection) {
75 this.collection = collection;
76 }
77 /** Constructor.
78 * @param exit_after <i>true</i> to cause the Gatherer to exit once save is complete, <i>false</i> otherwise.
79 */
80 public SaveCollectionTask(Collection collection, boolean close_after, boolean exit_after) {
81 this.close_after = close_after;
82 this.collection = collection;
83 this.exit_after = exit_after;
84 }
85 /** Constructor.
86 * @param name The filename of the collection we are saving as.
87 */
88 public SaveCollectionTask(Collection collection, String name) {
89 this.collection = collection;
90 this.name = name;
91 }
92 /** <p>This method, when created in a forked process by start(), performs the actions necessary to save a collection. If this is a regular save it saves the state of the current collection, ensuring all files, metadata files, and configuration files are written to disk. If, instead, this is a "Save As" action then there as several more steps involved:</p>
93 * <p>1. Perform a regular collection save on what we will later refer to as the origin collection.</p>
94 * <p>2. Call CollectionManager.makeCollection() to create the collection structure to save into (copied collection).</p>
95 * <p>3. Copy files from the origin to the copied collections (except special collection files ending with ~).</p>
96 * <p>4. Restore origin collection by undoing file copy actions and removing the ~ from the end of collection files.</p>
97 * <p>5. Close the origin collection.</p>
98 * <p>6. Open the copied collection.</p>
99 * <p>Of course all of this takes a while, and depends on several other bits of code to work properly.</p>.
100 * @see org.greenstone.gatherer.collection.Collection
101 * @see org.greenstone.gatherer.collection.CollectionModel
102 * @see org.greenstone.gatherer.gui.GUIManager
103 * @see org.greenstone.gatherer.gui.GConfigPane
104 * @see org.greenstone.gatherer.msm.MetadataSetManager
105 * @see org.greenstone.gatherer.util.Utility
106 */
107 public void run() {
108 // Change cursor to hourglass.
109 Gatherer.g_man.wait(true);
110 // Create progress monitor box. It will display itself as necessary.
111 // WARNING: ProgressMonitors seem to be extremely dodgy, and are not recommended!
112 // ProgressMonitor spd = new ProgressMonitor(Gatherer.g_man, Dictionary.newget("SaveProgressDialog.Title", collection.getName()), null, 0, 100);
113 // spd.setMillisToDecideToPopup(100);
114 // spd.setMillisToPopup(100);
115 // 0. Force all remaining metadata.xml files to load.
116 // 1. Perform a regular collection save on what we will later refer to as the origin collection.
117 ///ystem.err.println("1. Save origin.");
118 String tmp_loc = Gatherer.c_man.getCollectionFilename();
119 String args[] = new String[1];
120 args[0] = collection.getName() + ".col";
121 try {
122 // Block until all of the metadata files have been read in.
123 collection.gdm.waitUntilComplete();
124 // Write out the metadata xml files. The destroy below is meant to do this, but never does.
125 collection.gdm.save();
126 // spd.setProgress(getValue(METADATA_XML_SAVED));
127
128 File file = new File(tmp_loc);
129 // Create backup
130 if(file.exists()) {
131 File backup = new File(tmp_loc + "~");
132 backup.deleteOnExit();
133 if(!file.renameTo(backup)) {
134 Gatherer.println("Error in CollectionManager.load(): FileRenamedException");
135 }
136 }
137
138 // Carry on.
139 collection.save();
140 // spd.setProgress(getValue(COLLECTION_SAVED));
141
142 // Write out the collection configuration file.
143 Gatherer.g_man.config_pane.saveConfiguration();
144 // spd.setProgress(getValue(COLLECTION_CFG_SAVED));
145
146 // Write out the metadata files.
147 Gatherer.c_man.msm.save();
148 // spd.setProgress(getValue(METADATA_SAVED));
149
150 collection.setSaved(true);
151 }
152 catch (Exception error) {
153 Gatherer.printStackTrace(error);
154 }
155 // Now we check whether we've finished, or is this a Save As action, in which case we've got miles to go.
156 if(name != null) {
157 // 2. Call CollectionManager.makeCollection() to create the collection structure to save into (copied collection).
158 ///ystem.err.println("2. Make copy.");
159 Gatherer.c_man.createCollection(null, null, name, null, null, null);
160 // spd.setProgress(getValue(MAKE_COLLECTION));
161 // 3. Copy files from the origin to the copied collections (except special collection files ending with ~).
162 // As part of this we must rename origin.col to copy.col
163 ///ystem.err.println("3. Copy origin.");
164 ArrayList files = new ArrayList();
165 File collection_file = new File(Gatherer.c_man.getCollectionFilename());
166 File copied_dir = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path) + name);
167 files.add(collection_file.getParentFile());
168 while(files.size() > 0) {
169 File file = (File) files.get(0);
170 files.remove(0);
171 if(file.isDirectory()) {
172 File children[] = file.listFiles();
173 for(int i = 0; i < children.length; i++) {
174 files.add(children[i]);
175 }
176 children = null;
177 }
178 else {
179 // Rename origin.col file.
180 if(file.equals(collection_file)) {
181 File copied_file = new File(copied_dir, name + ".col");
182 copy(collection_file, copied_file);
183 copied_file = null;
184 }
185 // Exclude *~ files from certain locations and lock.tmp file.
186 else if(!file.getName().endsWith("~") && !file.getName().equals(CollectionManager.LOCK_FILE)) {
187 StringTokenizer origin = new StringTokenizer(file.getAbsolutePath(), File.separator);
188 StringTokenizer destin = new StringTokenizer(copied_dir.getAbsolutePath(), File.separator);
189 while(destin.hasMoreTokens()) {
190 origin.nextToken();
191 destin.nextToken();
192 }
193 File copied_file = new File(copied_dir.getAbsolutePath());
194 while(origin.hasMoreTokens()) {
195 copied_file = new File(copied_file, origin.nextToken());
196 }
197 copy(file, copied_file);
198 copied_file = null;
199 origin = null;
200 destin = null;
201 }
202 }
203 file = null;
204 }
205 // spd.setProgress(getValue(COPY_COLLECTION));
206 // 4. Restore origin collection by undoing file copy actions and removing the ~ from the end of collection files.
207 ///ystem.err.println("4. Restore origin.");
208 Gatherer.c_man.undo.undoAll();
209 ///ystem.err.println(" - UndoAll complete.");
210 // Recurse collection tree restoring *~
211 files.clear(); // Should be empty anyway.
212 files.add(collection_file.getParentFile());
213 while(files.size() > 0) {
214 File file = (File) files.get(0);
215 files.remove(0);
216 if(file.isDirectory()) {
217 File children[] = file.listFiles();
218 for(int i = 0; i < children.length; i++) {
219 files.add(children[i]);
220 }
221 children = null;
222 }
223 else if(file.getName().endsWith("~")) {
224 String filename = file.getAbsolutePath();
225 File original_file = new File(filename.substring(0, filename.length() - 1));
226 ///ystem.err.println("Renaming " + filename);
227 if(!file.renameTo(original_file)) {
228 Gatherer.println("Error in SaveCollectionTask.run(): FileRenameException");
229 }
230 }
231 }
232 ///ystem.err.println(" - Restore *~ complete.");
233 // spd.setProgress(getValue(RESTORE_COLLECTION));
234 // 5. Close the origin collection.
235 ///ystem.err.println("5. Close origin.");
236 collection.setSaved(true);
237 Gatherer.c_man.closeCollection();
238 // spd.setProgress(getValue(CLOSE_COLLECTION));
239 // 6. Open the copied collection.
240 ///ystem.err.println("6. Open copy.");
241 Gatherer.c_man.loadCollection(copied_dir.getAbsolutePath() + File.separator + name + ".col");
242 // spd.setProgress(getValue(OPEN_COLLECTION));
243 copied_dir = null;
244 }
245 // spd.close();
246 // spd = null;
247 tmp_loc = null;
248 args = null;
249 // Reset undo queue.
250 if(Gatherer.c_man.ready()) {
251 Gatherer.c_man.undo.clear();
252 }
253 Gatherer.g_man.wait(false);
254
255 // Now we are finished action any necessary action.
256 if(import_after) {
257 Gatherer.c_man.importCollection();
258 }
259 if(close_after) {
260 Gatherer.c_man.closeCollection();
261 }
262 ///ystem.err.println("Save Complete.");
263 if(exit_after) {
264 Gatherer.self.exit();
265 }
266 }
267
268 public void setImportAfter(boolean state) {
269 import_after = true;
270 }
271
272 private void copy(File source, File destination) {
273 ///ystem.err.println("Copy: " + source.getAbsolutePath());
274 ///ystem.err.println(" to: " + destination.getAbsolutePath());
275 try {
276 destination.getParentFile().mkdirs();
277 FileInputStream f_in = new FileInputStream(source);
278 FileOutputStream f_out = new FileOutputStream(destination);
279 byte data[] = new byte[Utility.BUFFER_SIZE];
280 int data_size = 0;
281 while((data_size = f_in.read(data, 0, Utility.BUFFER_SIZE)) != -1) {
282 f_out.write(data, 0, data_size);
283 }
284 f_in.close();
285 f_out.close();
286 }
287 catch (Exception exception) {
288 Gatherer.printStackTrace(exception);
289 }
290 }
291
292 private int getValue(int reference) {
293 double multiplier;
294 if(name == null) {
295 multiplier = 1.0;
296 }
297 else {
298 multiplier = 0.25;
299 }
300 switch(reference) {
301 // Standard Save
302 case COLLECTION_SAVED:
303 return (int)((double)70 * multiplier);
304 case COLLECTION_CFG_SAVED:
305 case METADATA_SAVED:
306 case METADATA_XML_SAVED:
307 return (int)((double)10 * multiplier);
308 // Save As
309 case MAKE_COLLECTION:
310 return 5;
311 case COPY_COLLECTION:
312 return 30;
313 case RESTORE_COLLECTION:
314 return 30;
315 case CLOSE_COLLECTION:
316 return 10;
317 case OPEN_COLLECTION:
318 return 10;
319 }
320 return 0;
321 }
322}
323
324
325
326
327
Note: See TracBrowser for help on using the repository browser.