source: other-projects/FileTransfer-WebSocketPair/testGXTWithGreenstone/src/com/gs3/testGXT/server/Greenstone/GWTFileQueue.java@ 33053

Last change on this file since 33053 was 33053, checked in by ak19, 5 years ago

I still had some stuff of Nathan Kelly's (FileTransfer-WebSocketPair) sitting on my USB. Had already commited the Themes folder at the time, 2 years back. Not sure if he wanted this additional folder commited. But I didn't want to delete it and decided it will be better off on SVN. When we use his project, if we find we didn't need this test folder, we can remove it from svn then.

File size: 31.1 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 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package com.gs3.testGXT.server.Greenstone;
28
29import java.io.*;
30import java.util.*;
31
32import org.greenstone.gatherer.DebugStream;
33import org.greenstone.gatherer.Gatherer;
34import org.greenstone.gatherer.file.FileAlreadyExistsException;
35import org.greenstone.gatherer.file.InsufficientSpaceException;
36import org.greenstone.gatherer.file.ReadNotPermittedException;
37import org.greenstone.gatherer.file.UnknownFileErrorException;
38import org.greenstone.gatherer.file.WriteNotPermittedException;
39import org.greenstone.gatherer.gui.tree.DragTree;
40import org.greenstone.gatherer.util.StaticStrings;
41import org.greenstone.gatherer.util.Utility;
42
43/** A threaded object which processes a queue of file actions such as copying and movement. It also handles updating the various trees involved so they are an accurate representation of the file system they are meant to match.
44 * @author John Thompson, Greenstone Digital Library, University of Waikato
45 * @version 2.3
46 */
47public class GWTFileQueue
48extends Thread
49{
50
51
52 /** The size of the io buffer, in bytes. */
53 static final private int BUFFER_SIZE = 1024;
54
55 public static int job_size = 0;
56 public static int done_size = 0;
57 /** A list containing a queue of waiting movement jobs. */
58 private ArrayList<GWTFileJob> queue = null;
59 private static int allowance = 0;
60 public static int files_in_queue = 1;
61 public static Object monitor = new Object();
62
63 /**
64 * Set copy allowance of filequeue
65 * @param _allowance allowance in 1024 byte chunks
66 * Idealy, this would be windowed based on something like sliding window, idk
67 */
68 public static void cancelOperations() {
69 wasCancelled = cancelled = true;
70 }
71
72 private static boolean isQueueBusy = false;
73
74
75 public static void queue_busy() {isQueueBusy = true;}
76 private static void queue_free() {isQueueBusy = false;}
77
78 public static boolean isQueueBusy() {return isQueueBusy;}
79
80
81 private static boolean cancelled = false;
82 private static boolean wasCancelled = false;
83
84 public static boolean wasCancelled() {
85 boolean tmp = wasCancelled;
86 wasCancelled = false;
87 return tmp;
88 }
89
90 public void checkQueue() {
91 files_in_queue = 1;
92 }
93
94 public static void setAllowance(int _allowance) {
95 allowance = _allowance;
96 }
97 public static int getAllowance() {
98 return allowance;
99 }
100
101 public static String currentJob = null;
102
103 /** Constructor. */
104 public GWTFileQueue() {
105 DebugStream.println("FileQueue started.");
106 this.queue = new ArrayList<GWTFileJob>();
107 }
108
109
110 /** Add a new job to the queue, specifiying as many arguments as is necessary to complete this type of job (ie delete needs no target information).
111 * @param id A long id unique to all jobs created by a single action.
112 * @param source The DragComponent source of this file, most likely a DragTree.
113 * @param child The FileNode you wish to mode.
114 * @param target The DragComponent to move the file to, again most likely a DragTree.
115 * @param parent The files new FileNode parent within the target.
116 * @param type The type of this movement as an int, either COPY or DELETE.
117 */
118 public void addJob(long id, GWTFileNode source, GWTFileNode[] children, GWTFileNode target, byte type)
119 {
120 //TODO: we may have to modify children, target to fit parameters properly
121 // Queue the sub-job(s) (this may fail if we are asked to delete a read only file)
122 for (int i = 0; i < children.length; i++) {
123 addJob(id, source, children[i], target, type, -1);
124 }
125
126 files_in_queue = 1;
127 }
128
129 synchronized public void addJob(long id, GWTFileNode source, GWTFileNode target, byte type) {
130 GWTFileJob job = new GWTFileJob(id, source, target, type);
131 source.refreshChildren();
132 DebugStream.println("Adding job: " + job);
133 queue.add(job);
134
135 if(type == GWTFileJob.COPY_FILE_ONLY)
136 job_size += source.file.length();
137
138 files_in_queue = 1;
139 notify();
140 }
141
142 synchronized private void addJob(long id, GWTFileNode source, GWTFileNode child, GWTFileNode target,byte type, int position) {
143 GWTFileJob job = new GWTFileJob(id, source, target, type);
144 if(type == GWTFileJob.COPY)
145 job_size += source.file.length();
146 DebugStream.println("Adding job: " + job);
147 if(position != -1 && position <= queue.size() + 1) {
148 queue.add(position, job);
149 }
150 else {
151 queue.add(job);
152 }
153
154 files_in_queue = 1;
155 notify();
156 }
157
158 /** Calculates the total deep file size of the selected file nodes.
159 * @param files a FileNode[] of selected files
160 * @return true if a cancel was signaled, false otherwise
161 * @see org.greenstone.gatherer.file.FileManager.Task#run()
162 */
163 public boolean calculateSize(ArrayList<GWTFileNode> files)
164 {
165 //job_size = 0;
166 // Calculate the total file size of all the selected file nodes
167 Vector<GWTFileNode> remaining = new Vector<GWTFileNode>();
168 for (int i = 0; i < files.size(); i++) {
169 remaining.add(files.get(i));
170 }
171 while (remaining.size() > 0) {
172 GWTFileNode node = remaining.remove(0);
173 job_size += node.getFile().length();
174 if (node.isLeaf()) {
175 job_size += node.getFile().length();
176 }
177 else {
178 for (int i = 0; i < node.getChildCount(); i++) {
179 remaining.add((GWTFileNode) node.getChildAt(i));
180 }
181 }
182 }
183
184 // Now we return if calculation was cancelled so that the FileManagers Task can skip the addJob phase correctly.
185 /*if (cancel_action) {
186 cancel_action = false; // reset
187 return true;
188 }
189 else {
190 */
191 return false;
192 //}
193 }
194
195 /** This method is called to cancel the job queue at the next available moment. */
196 public void cancelAction() {
197 clearJobs();
198 files_in_queue = queue.size();
199 }
200
201 //this doesn't seem to ever even happen
202 synchronized private void addFileJob(long id, GWTFileNode source, GWTFileNode target, byte type)
203 {
204 queue.add(new GWTFileJob(id, source, target, type));
205
206 //job_size += source.file.length();
207 //System.err.println(source.file.length());
208
209 files_in_queue = 1;
210
211 notify();
212 }
213
214 private void doEmptyDirectoryDelete(GWTFileJob file_job)
215 {
216 GWTFileNode source_node = file_job.getOrigin();
217 File source_directory = source_node.getFile();
218
219 // If the directory isn't empty then this will fail
220 if (source_directory.delete() == false) {
221 // The source directory couldn't be deleted, so give the user the option of continuing or cancelling
222
223 //TODO: there should be a dialog here
224 System.err.println("Could not delete item - non-empty directory");
225 clearJobs(); // Aborting action
226 return;
227 }
228 }
229
230 private void doDirectoryDelete(GWTFileJob file_job)
231 {
232 GWTFileNode source_node = file_job.getOrigin();
233 File source_directory = source_node.getFile();
234
235 // Add a new Delete job for each child of this directory (except metadata.xml files)
236 source_node.refresh();
237 for (int i = 0; i < source_node.size(); i++) {
238 GWTFileNode child_file_node = (GWTFileNode) source_node.getChildAtUnfiltered(i);
239 if (!child_file_node.getFile().getName().equals(StaticStrings.METADATA_XML)) {
240 addFileJob(file_job.ID(), child_file_node, null, GWTFileJob.DELETE);
241 }
242 }
243
244 // Treat metadata.xml files spehttp://www.waikato.ac.nz/contacts/map/cially: delete them first
245 for (int i = 0; i < source_node.size(); i++) {
246 GWTFileNode child_file_node = (GWTFileNode) source_node.getChildAtUnfiltered(i);
247 if (child_file_node.getFile().getName().equals(StaticStrings.METADATA_XML)) {
248 addFileJob(file_job.ID(), child_file_node, null, GWTFileJob.DELETE);
249 break;
250 }
251 }
252
253 // The last thing we will do is delete this directory (which should be empty by then)
254 addFileJob(file_job.ID(), source_node, null, GWTFileJob.DELETE_EMPTY_DIRECTORY);
255 }
256
257
258 private void doDirectoryCopy(GWTFileJob file_job)
259 {
260 GWTFileNode source_node = file_job.getOrigin();
261 GWTFileNode target_node = file_job.getDestination();
262
263 File source_directory = source_node.getFile();
264 File target_directory = new File(target_node.getFile(), source_directory.getName());
265
266 // Check that the source directory doesn't contain the target directory (will create a cyclic loop)
267 if (target_directory.getAbsolutePath().startsWith(source_directory.getAbsolutePath())) {
268 System.err.println("Item contains itself: cannot copy");
269 clearJobs(); // Aborting action
270 return;
271 }
272
273 // The target directory shouldn't already exist
274 if (target_directory.exists()) {
275 System.err.println("Target already exists...");
276 clearJobs(); // Aborting action
277 return;
278 }
279
280 target_directory.mkdirs();
281
282 // Create a node for the new directory in the collection tree
283 /*FileSystemModel target_model = new FileSystemModel((FileSystemModel) file_job.target.getTreeModel();
284 CollectionTreeNode new_target_node = new CollectionTreeNode(target_directory);
285 SynchronizedTreeModelTools.insertNodeInto(target_model, target_node, new_target_node);
286 new_target_node.setParent(target_node);
287
288 // Copy the non-folder level metadata assigned to the original directory to the new directory
289 ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToExternalFile(source_directory);
290 MetadataXMLFileManager.addMetadata((CollectionTreeNode) new_target_node, assigned_metadata);
291 */
292 // Add a new Copy job for each child of this directory (except metadata.xml files)
293 //TODO: will need to do a lot of hacking here to make it work
294 /*
295
296 */
297
298 String target = target_node.getFile().getAbsolutePath() + "/" + source_node.getFile().getName();
299 System.err.println("Target: " + target);
300 GWTFileNode new_target = new GWTFileNode(new File(target));
301
302 source_node.refreshChildren();
303
304 for (int i = 0; i < source_node.size(); i++) {
305 GWTFileNode child_file_node = (GWTFileNode) source_node.getChildAtUnfiltered(i);
306 if (!child_file_node.getFile().getName().equals(StaticStrings.METADATA_XML)) {
307 addFileJob(file_job.ID(), child_file_node, new_target, GWTFileJob.COPY);
308 }
309 }
310
311 }
312
313 private void doDirectoryMove(GWTFileJob file_job)
314 {
315 GWTFileNode source_node = file_job.getOrigin();
316 GWTFileNode target_node = file_job.getDestination();
317
318 File source_directory = source_node.getFile();
319 File target_directory = new File(target_node.getFile(), source_directory.getName());
320 if (file_job.type == GWTFileJob.RENAME) {
321 // This is the only difference between moves and renames
322 target_directory = target_node.getFile();
323 target_node = (GWTFileNode) source_node.getParent();
324 }
325
326 // Check the target directory isn't the source directory
327 if (target_directory.equals(source_directory)) {
328 DebugStream.println("Target directory is the source directory!");
329 return;
330 }
331
332 // The target directory shouldn't already exist
333 if (target_directory.exists()) {
334 System.err.println("Target directory already exists");
335 //todo: error dialog
336 clearJobs(); // Aborting action
337
338 return;
339 }
340 target_directory.mkdirs();
341
342 /*
343 // Create a node for the new directory in the collection tree
344 FileSystemModel target_model = (FileSystemModel) file_job.target.getTreeModel();
345 CollectionTreeNode new_target_node = new CollectionTreeNode(target_directory);
346 SynchronizedTreeModelTools.insertNodeInto(target_model, target_node, new_target_node);
347 new_target_node.setParent(target_node);
348
349 // Move the folder level metadata assigned to the original directory to the new directory
350 ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToFile(source_directory);
351 MetadataXMLFileManager.removeMetadata((CollectionTreeNode) source_node, assigned_metadata);
352 MetadataXMLFileManager.addMetadata((CollectionTreeNode) new_target_node, assigned_metadata);
353
354 // The last thing we will do is delete this directory
355 addFileJob(file_job.ID(), file_job.source, source_node, null, null, FileJob.DELETE);
356
357 // Treat metadata.xml files specially: delete them last
358 source_node.refresh();
359 for (int i = 0; i < source_node.size(); i++) {
360 FileNode child_file_node = (FileNode) source_node.getChildAtUnfiltered(i);
361 if (child_file_node.getFile().getName().equals(StaticStrings.METADATA_XML)) {
362 addFileJob(file_job.ID(), file_job.source, child_file_node, null, null, FileJob.DELETE);
363 break;
364 }
365 }
366
367 // Add a new Move job for each child of this directory (except metadata.xml files)
368 for (int i = 0; i < source_node.size(); i++) {
369 FileNode child_file_node = (FileNode) source_node.getChildAtUnfiltered(i);
370 if (!child_file_node.getFile().getName().equals(StaticStrings.METADATA_XML)) {
371 addFileJob(file_job.ID(), file_job.source, child_file_node, file_job.target, new_target_node, FileJob.MOVE);
372 }
373 }
374 */
375 }
376
377
378 private void doFileDelete(GWTFileJob file_job)
379 {
380 GWTFileNode source_node = file_job.getOrigin();
381 File source_file = source_node.getFile();
382
383 // Almost all files will be deleted from the collection tree (exception: files in "Downloaded Files")
384 /*if (source_node instanceof CollectionTreeNode) {
385 // If we're deleting a metadata.xml file we must unload it
386 boolean metadata_xml_file = source_file.getName().equals(StaticStrings.METADATA_XML);
387 if (metadata_xml_file) {
388 MetadataXMLFileManager.unloadMetadataXMLFile(source_file);
389 }
390 // Otherwise remove any metadata assigned directly to the file
391 else {
392 ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToFile(source_file);
393 MetadataXMLFileManager.removeMetadata((CollectionTreeNode) source_node, assigned_metadata);
394 }
395 }*/
396
397 // Delete the source file
398 if (!Utility.delete(source_file)) {
399 // The source file couldn't be deleted, so give the user the option of continuing or cancelling
400 System.err.println("Couldn't delete file");
401 //TODO: we'll have to put a dialog or something here later
402 clearJobs(); // Aborting action
403
404 return;
405 }
406
407 // Remove the node from the model
408 //SynchronizedTreeModelTools.removeNodeFromParent(file_job.source.getTreeModel(), source_node);
409 }
410
411
412 private void doFileCopy(GWTFileJob file_job)
413 {
414
415 GWTFileNode source_node = file_job.getOrigin();
416 GWTFileNode target_node = file_job.getDestination();
417
418 currentJob = "Copying " + source_node.getURLEncodedFileName() + " to " + target_node.getURLEncodedFilePath();
419
420 File source_file = source_node.getFile();
421 File target_file = new File(target_node.getFile(), source_file.getName());
422
423 // The target file shouldn't already exist -- if it does ask the user whether they want to overwrite
424 boolean overwrite_file = false;
425 if (target_file.exists()) {
426 //we always overwrite the file because this has been pre-resolved
427
428 overwrite_file = true;
429 }
430
431 // Copy the file
432 try {
433 copyFile(source_file, target_file, true);
434 }
435 catch (FileAlreadyExistsException exception) {
436 // This should not ever happen, since we've called copyFile with overwrite set
437 DebugStream.printStackTrace(exception);
438 return;
439 }
440 catch (FileNotFoundException exception) {
441 DebugStream.printStackTrace(exception);
442 System.err.println("file not found");
443 //TODO: dialog
444 clearJobs(); // Aborting action
445
446 // Refresh the source tree model
447 //FileSystemModel source_model = file_job.source.getTreeModel();
448 //source_model.refresh(new TreePath(((FileNode) file_job.getOrigin().getParent()).getPath()));
449 return;
450 }
451 catch (InsufficientSpaceException exception) {
452 DebugStream.printStackTrace(exception);
453 System.err.println("No space exception");
454 //TODO: dialog
455 clearJobs(); // Aborting action
456 return;
457 }
458 catch (IOException exception) {
459 DebugStream.printStackTrace(exception);
460 System.err.println("IOexception?");
461 //TODO: dialog
462 clearJobs(); // Aborting action
463 return;
464 }
465 catch (ReadNotPermittedException exception) {
466 DebugStream.printStackTrace(exception);
467 System.err.println("Read not permitted");
468 //TODO: dialog
469 clearJobs(); // Aborting action
470 return;
471 }
472 catch (UnknownFileErrorException exception) {
473 DebugStream.printStackTrace(exception);
474 System.err.println("Unknown File Error");
475 //TODO: dialog
476 clearJobs(); // Aborting action
477
478 return;
479 }
480 catch (WriteNotPermittedException exception) {
481 DebugStream.printStackTrace(exception);System.err.println("file not found");
482 System.err.println("Write not permitted");
483 //TODO: dialog
484 clearJobs(); // Aborting action
485
486 return;
487 }
488
489 //CollectionTreeNode new_target_node = new CollectionTreeNode(target_file);
490 if (overwrite_file == false) {
491 // Add the new node into the tree
492 //FileSystemModel target_model = file_job.target.getTreeModel();
493 //SynchronizedTreeModelTools.insertNodeInto(target_model, target_node, new_target_node);
494 }
495 //Gatherer.c_man.fireFileAddedToCollection(target_file);
496
497 // Copy the non-folder level metadata assigned to the original file to the new file
498 if (file_job.type == GWTFileJob.COPY) {
499 // do metadata too
500 //ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToExternalFile(source_file);
501 //MetadataXMLFileManager.addMetadata((CollectionTreeNode) new_target_node, assigned_metadata);
502 }
503 }
504
505
506 private void doFileMove(GWTFileJob file_job)
507 {
508 GWTFileNode source_node = file_job.getOrigin();
509 GWTFileNode target_node = file_job.getDestination();
510
511 File source_file = source_node.getFile();
512 File target_file = new File(target_node.getFile(), source_file.getName());
513 if (file_job.type == GWTFileJob.RENAME) {
514 // This is the only difference between moves and renames
515 target_file = target_node.getFile();
516 target_node = (GWTFileNode) source_node.getParent();
517 }
518
519 // Check the target file isn't the source file
520 if (target_file.equals(source_file)) {
521 DebugStream.println("Target file is the source file!");
522 return;
523 }
524
525
526 ///we ALWAYS overwrite, because these files have been pre-resolved
527 // The target file shouldn't already exist
528 /*if (target_file.exists()) {
529 int result = showOverwriteDialog(target_file.getName());
530 if (result == JOptionPane.NO_OPTION) {
531 // Don't overwrite
532 return;
533 }
534 if (result == JOptionPane.CANCEL_OPTION) {
535 clearJobs(); // Aborting action
536 return;
537 }
538 }*/
539
540
541 // Move the file by renaming it
542 if (!source_file.renameTo(target_file)) {
543 String args[] = { source_file.getName(), target_file.getAbsolutePath() };
544 System.err.println("Couldn't rename file");
545 //TODO: dialog
546 clearJobs(); // Aborting action
547 //}
548 return;
549 }
550
551 //TODO: modify the metadata FM to only take in source files
552
553 // Remove the node from the source model and add it to the target model
554 //SynchronizedTreeModelTools.removeNodeFromParent(file_job.source.getTreeModel(), source_node);
555 //CollectionTreeNode new_target_node = new CollectionTreeNode(target_file);
556 //FileSystemModel target_model = file_job.target.getTreeModel();
557 //SynchronizedTreeModelTools.insertNodeInto(target_model, target_node, new_target_node);
558
559 // Move the non-folder level metadata assigned to the original file to the new file
560 //ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToFile(source_file);
561 //MetadataXMLFileManager.removeMetadata((CollectionTreeNode) source_node, assigned_metadata);
562 //MetadataXMLFileManager.addMetadata((CollectionTreeNode) new_target_node, assigned_metadata);
563 }
564
565
566 /** all this does is move the metadata, and delete the source */
567 private void doFileReplace(GWTFileJob file_job)
568 {
569 GWTFileNode source_node = file_job.getOrigin();
570 GWTFileNode target_node = file_job.getDestination();
571
572 File source_file = source_node.getFile();
573 File target_file = target_node.getFile();
574
575 //TODO: metadata part
576 /*
577 // Move the non-folder level metadata assigned to the original file to the new file
578 CollectionTreeNode new_target_node = new CollectionTreeNode(target_file);
579 ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToFile(source_file);
580 MetadataXMLFileManager.removeMetadata((CollectionTreeNode) source_node, assigned_metadata);
581 MetadataXMLFileManager.addMetadata((CollectionTreeNode) new_target_node, assigned_metadata);
582 */
583 // now delete the original
584 doFileDelete(file_job);
585 }
586
587
588 private void processFileJob(GWTFileJob file_job)
589 {
590 files_in_queue = queue.size();
591 DebugStream.println("Processing file job " + file_job + "...");
592
593 // Ensure that the source file exists
594 File source_file = file_job.getOrigin().getFile();
595 if (!source_file.exists()) {
596 // The source file doesn't exist, so give the user the option of continuing or cancelling
597 System.err.println("Source file does not exist: cancelling job");
598 //TODO: some sort of dialog
599 clearJobs(); // Aborting action
600 }
601
602 // Enable the "Stop" button
603 //TODO: enable client side stop button
604 //stop_button.setEnabled(true);
605
606 // Delete empty directory job
607 if (file_job.type == GWTFileJob.DELETE_EMPTY_DIRECTORY) {
608 System.err.println("Deleting empty directory...");
609 doEmptyDirectoryDelete(file_job);
610 return;
611 }
612
613 // Delete job
614 if (file_job.type == GWTFileJob.DELETE) {
615 System.err.println("Deleting file " + file_job.getOrigin().displayFileName);
616 if (source_file.isFile()) {
617 long source_file_size = source_file.length();
618 doFileDelete(file_job);
619 done_size += source_file_size;
620 }
621 else {
622 doDirectoryDelete(file_job);
623 }
624 return;
625 }
626
627 // Copy job
628 if (file_job.type == GWTFileJob.COPY || file_job.type == GWTFileJob.COPY_FILE_ONLY) {
629 System.err.println("Copying file " + source_file.getName() + " to the destination " + file_job.getDestination().file.getAbsolutePath());
630 //file_status.setText(Dictionary.get("FileActions.Copying", formatPath("FileActions.Copying", source_file.getAbsolutePath(), file_status.getSize().width)));
631 if (source_file.isFile()) {
632 long source_file_size = source_file.length();
633 doFileCopy(file_job);
634 //done_size += source_file_size;
635 }
636 else {
637 doDirectoryCopy(file_job);
638 }
639 return;
640 }
641
642 // Move (or rename) job
643 if (file_job.type == GWTFileJob.MOVE || file_job.type == GWTFileJob.RENAME) {
644 System.err.println("Moving file " + source_file.getName() + " to the destination " + file_job.getDestination().file.getAbsolutePath());
645 //file_status.setText(Dictionary.get("FileActions.Moving", formatPath("FileActions.Moving", source_file.getAbsolutePath(), file_status.getSize().width)));
646 if (source_file.isFile()) {
647 long source_file_size = source_file.length();
648 doFileMove(file_job);
649 done_size += source_file_size;
650 //progress.addValue(source_file_size); // Update progress bar
651 }
652 else {
653 doDirectoryMove(file_job);
654 }
655 return;
656 }
657
658 // Replace job
659 if (file_job.type == GWTFileJob.REPLACE) {
660
661 //file_status.setText(Dictionary.get("FileActions.Replacing", formatPath("FileActions.Replacing", source_file.getAbsolutePath(), file_status.getSize().width)));
662 doFileReplace(file_job);
663 return;
664 }
665 }
666
667 /*private int showErrorDialog(String error_message)
668 {
669 Object[] options = { Dictionary.get("General.OK"), Dictionary.get("General.Cancel") };
670 int result = JOptionPane.showOptionDialog(Gatherer.g_man, error_message, Dictionary.get("General.Error"), JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[0]);
671 if (result == 0) {
672 return JOptionPane.OK_OPTION;
673 }
674 else {
675 return JOptionPane.CANCEL_OPTION;
676 }
677 }
678
679
680 private int showOverwriteDialog(String target_file_name)
681 {
682 // Has "yes to all" been set?
683 if (yes_to_all) {
684 return JOptionPane.YES_OPTION;
685 }
686
687 Object[] options = { Dictionary.get("General.Yes"), Dictionary.get("FileActions.Yes_To_All"), Dictionary.get("General.No"), Dictionary.get("General.Cancel") };
688 int result = JOptionPane.showOptionDialog(Gatherer.g_man, Dictionary.get("FileActions.File_Exists", target_file_name), Dictionary.get("General.Warning"), JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]);
689 if (result == 0) {
690 return JOptionPane.YES_OPTION;
691 }
692 else if (result == 1) {
693 yes_to_all = true;
694 return JOptionPane.YES_OPTION;
695 }
696 else if (result == 2) {
697 return JOptionPane.NO_OPTION;
698 }
699 else {
700 return JOptionPane.CANCEL_OPTION;
701 }
702 }*/
703
704
705 public void run()
706 {
707 super.setName("FileQueue");
708
709 while (!Gatherer.exit) {
710 // Retrieve the next job
711 int position = queue.size() - 1;
712 if (position >= 0) {
713 // We have a file job, so process it
714 processFileJob((GWTFileJob) queue.remove(position));
715 }
716 else {
717 // No jobs, so reset and wait until we are notified of one
718 synchronized(this) {
719 // Force both workspace and collection trees to refresh
720 if (Gatherer.g_man != null && Gatherer.c_man.ready()) {
721 Gatherer.g_man.refreshWorkspaceTree(DragTree.COLLECTION_CONTENTS_CHANGED);
722 // Gatherer.g_man.refreshCollectionTree(DragTree.COLLECTION_CONTENTS_CHANGED);
723 }
724
725 // Reset status area
726 //file_status.setText(Dictionary.get("FileActions.No_Activity"));
727 //progress.reset();
728 //progress.setString(Dictionary.get("FileActions.No_Activity"));
729
730 // Reset "yes to all" and "cancel" flags
731 //yes_to_all = false;
732 //cancel_action = false;
733
734 // Wait for a new file job
735 try {
736 wait();
737 }
738 catch (InterruptedException exception) {}
739 }
740 }
741 }
742 }
743
744
745 /** Register the button that will be responsible for stopping executing file actions.
746 * @param stop_button a JButton
747 */
748 /*public void registerStopButton(JButton stop_button) {
749 this.stop_button = stop_button;
750 }*/
751
752
753 synchronized private void clearJobs() {
754 queue.clear();
755 }
756
757 /** Copy the contents from the source directory to the destination
758 * directory.
759 * @param source The source directory
760 * @param destination The destination directory
761 * @see org.greenstone.gatherer.Gatherer
762 */
763 public void copyDirectoryContents(File source, File destination, boolean overwrite)
764 throws FileAlreadyExistsException, FileNotFoundException, InsufficientSpaceException, IOException, ReadNotPermittedException, UnknownFileErrorException, WriteNotPermittedException
765 {
766 if (!source.isDirectory()) return;
767 // check that dest dirs exist
768 destination.mkdirs();
769
770 File [] src_files = source.listFiles();
771 if (src_files.length == 0) return; // nothing to copy
772 for (int i=0; i<src_files.length; i++) {
773 File f = src_files[i];
774 String f_name = f.getName();
775 File new_file = new File(destination, f_name);
776 if (f.isDirectory()) {
777 copyDirectoryContents(f, new_file, overwrite);
778 } else if (f.isFile()) {
779 copyFile(f, new_file, overwrite);
780 }
781 }
782 }
783
784 /** Preserving old default behavior of copyDirContents method, where overwrite is false. */
785 public void copyDirectoryContents(File source, File destination) throws FileAlreadyExistsException, FileNotFoundException, InsufficientSpaceException, IOException, ReadNotPermittedException, UnknownFileErrorException, WriteNotPermittedException
786 {
787 copyDirectoryContents(source, destination, false);
788 }
789
790
791 /** Copy a file from the source location to the destination location.
792 * @param source The source File.
793 * @param destination The destination File.
794 * @see org.greenstone.gatherer.Gatherer
795 */
796 public void copyFile(File source, File destination, boolean overwrite)
797 throws FileAlreadyExistsException, FileNotFoundException, InsufficientSpaceException, IOException, ReadNotPermittedException, UnknownFileErrorException, WriteNotPermittedException
798 {
799 queue_busy();
800
801 if (source.isDirectory()) {
802 destination.mkdirs();
803 return;
804 }
805
806 // Check if the origin file exists.
807 if (!source.exists()) {
808 DebugStream.println("Couldn't find the source file.");
809 throw new FileNotFoundException();
810 }
811
812 // Make sure the destination file does not exist.
813 if (destination.exists() && !overwrite) {
814 throw new FileAlreadyExistsException();
815 }
816
817 // Open an input stream to the source file
818 FileInputStream f_in = null;
819 try {
820 f_in = new FileInputStream(source);
821 }
822 catch (FileNotFoundException exception) {
823 // A FileNotFoundException translates into a ReadNotPermittedException in this case
824 throw new ReadNotPermittedException(exception.toString());
825 }
826
827 // Create an necessary directories for the target file
828 File dirs = destination.getParentFile();
829 dirs.mkdirs();
830
831 // Open an output stream to the target file
832 FileOutputStream f_out = null;
833 try {
834 f_out = new FileOutputStream(destination);
835 }
836 catch (FileNotFoundException exception) {
837 // A FileNotFoundException translates into a WriteNotPermittedException in this case
838 f_in.close();
839 throw new WriteNotPermittedException(exception.toString());
840 }
841
842 // Copy the file
843 byte data[] = new byte[BUFFER_SIZE];
844 int data_size = 0;
845
846 synchronized (monitor) {
847 while ((data_size = f_in.read(data, 0, BUFFER_SIZE)) != -1 && !cancelled) {
848 if(allowance <= 0 && data_size == BUFFER_SIZE) {
849 //no use waiting on literally the last chunk
850 try {
851 monitor.notify();
852 monitor.wait();
853 } catch (InterruptedException e) {
854 //do nothing - we need only wait
855 }
856 }
857
858 long destination_size = destination.length();
859
860 try {
861 f_out.write(data, 0, data_size);
862 done_size += data_size;
863 }
864 /* If an IO exception occurs, we can do some math to determine if the number of bytes written to the file was less than expected.
865 * If so we can assume a InsufficientSpace exception. If not we just throw the exception again. */
866 catch (IOException io_exception) {
867 f_in.close();
868 f_out.close();
869
870 if (destination_size + (long) data_size > destination.length()) {
871 // Determine the difference (which I guess is in bytes).
872 long difference = (destination_size + (long) data_size) - destination.length();
873 // Transform that into a human readable string.
874 String message = Utility.formatFileLength(difference);
875 throw new InsufficientSpaceException(message);
876 }
877 else {
878 throw(io_exception);
879 }
880 }
881 allowance--;
882 }
883
884 if(cancelled) {
885 queue.clear();
886 job_size = done_size;
887 cancelled = false;
888
889 //ensure no trace of the file remains: delete it
890 try {
891 destination.delete();
892 } catch (Exception e) {
893 e.printStackTrace();
894 }
895
896 //make sure we close these, or else we lock that file for good!
897 f_in.close();
898 f_out.close();
899 }
900
901 allowance = 0;
902 files_in_queue = queue.size();
903
904 queue_free();
905 monitor.notify();
906 }
907
908 // Flush and close the streams to ensure all bytes are written.
909 f_in.close();
910 f_out.close();
911
912 //allowance = 0;
913
914 // We have now, in theory, produced an exact copy of the source file. Check this by comparing sizes.
915 if(!destination.exists() || (/*!cancel_action && */source.length() != destination.length())) {
916 throw new UnknownFileErrorException();
917 }
918
919 // If we were cancelled, ensure that none of the destination file exists.
920 if (cancelled) {
921 destination.delete();
922 }
923 }
924}
Note: See TracBrowser for help on using the repository browser.