Klassenbiliothek fuer Dateiverwaltung
ulrich
23 hours ago d618b8d94aef4de9750a7a4681b7d667fc5d657a
commit | author | age
e369b9 1 /*
c45b52 2   fm - File management class library
e369b9 3   Copyright (C) 2024  Ulrich Hilger
U 4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU Affero General Public License as
7   published by the Free Software Foundation, either version 3 of the
8   License, or (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU Affero General Public License for more details.
14
15   You should have received a copy of the GNU Affero General Public License
16   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
18 package de.uhilger.fm;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.nio.file.FileVisitResult;
23 import java.nio.file.FileVisitor;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.nio.file.attribute.BasicFileAttributes;
27
28 /**
a11f6c 29  * Ein FileVisitor zum Verschieben, Kopieren oder Loeschen ganzer Ordnerstrukturen mit
e369b9 30  * Hilfe der Methode Files.walkFileTree von java.nio.
U 31  *
32  * @author Ulrich Hilger
33  * @version 1, 14. Mai 2021
34  */
a11f6c 35 public class FileOpsVisitor extends FileHelper implements FileVisitor {
e369b9 36
U 37   private Path targetDir;
38   private int operation;
39
973951 40   /**
U 41    * Den Zielordner fuer Kopier- oder Verschiebeoperationen angeben
42    * 
43    * @param targetDir der Zielordner
44    */
e369b9 45   public void setTargetDir(Path targetDir) {
U 46     this.targetDir = targetDir;
47   }
48
49   /**
973951 50    * Die gewuenschte Dateioperation angeben,
U 51    * OP_COPY, OP_MOVE oder OP_DELETE
e369b9 52    *
973951 53    * @param op die Dateioperation
e369b9 54    */
U 55   public void setOperation(int op) {
56     this.operation = op;
57   }
58
973951 59   /**
U 60    * Dafuer sorgen, dass beim Kopieren oder Verschieben kein am Ziel bereits existierender 
61    * Ordner ueberschrieben wird, indem am Ziel fuer einen bereits existierenden Ordner ein  
62    * anderer Name mit laufender Nummer erzeugt wird.
63    * 
a11f6c 64    * Invoked for a directory before entries in the directory are visited. If this method 
U 65    * returns CONTINUE, then entries in the directory are visited. If this method returns 
66    * SKIP_SUBTREE or SKIP_SIBLINGS then entries in the directory (and any descendants) 
67    * will not be visited.
68    * 
973951 69    * @param dir Zielordner
U 70    * @param attrs die gewuenschten Attribute
71    * @return gibt stets FileVisitResult.CONTINUE zurueck
72    * @throws IOException wenn etwas schief geht
73    */
e369b9 74   @Override
a11f6c 75   public FileVisitResult preVisitDirectory(Object dir, BasicFileAttributes attrs) 
U 76           throws IOException {
973951 77     if (operation != Eraser.OP_DELETE) {
e369b9 78       if (dir instanceof Path) {
U 79         Path sourceDir = (Path) dir;
80         File destFile = targetDir.resolve(sourceDir.getFileName()).toFile();
81         //logger.fine("sourceDir: " + sourceDir + ", destFile: " + destFile);
82         if (destFile.exists()) {
83           File newDir = getNewFileName(destFile);
84           destFile.renameTo(newDir);
85         }
86         destFile.mkdir();
87         this.targetDir = destFile.toPath();
88         //logger.fine("targetDir now: " + targetDir.toString());
89       }
90     }
91     return FileVisitResult.CONTINUE;
92   }
93
a11f6c 94   /**
U 95    * Fuer jede Datei die gewuenschte Dateioperation ausführen
96    * 
97    * Invoked for a file in a directory.
98    * 
99    * @param file  die zu bearbeitende Datei a reference to the file
100    * @param attrs  the directory's basic attributes
101    * @return  stets FileVisitResult.CONTINUE
102    * @throws IOException wenn etwas schief geht
103    */
e369b9 104   @Override
U 105   public FileVisitResult visitFile(Object file, BasicFileAttributes attrs) throws IOException {
973951 106     if(operation != Eraser.OP_DELETE) {
e369b9 107       if (file instanceof Path) {
U 108         Path source = (Path) file;
109         File destFile = targetDir.resolve(source.getFileName()).toFile();
110         if (destFile.exists()) {
111           destFile = getNewFileName(destFile);
112         }
973951 113         if (operation == Mover.OP_MOVE) {
e369b9 114           Files.move(source, destFile.toPath());
973951 115         } else if (operation == Mover.OP_COPY) {
e369b9 116           Files.copy(source, destFile.toPath());
U 117         }
118       }
119     } else {
120      Files.delete((Path) file);
121     }
122     return FileVisitResult.CONTINUE;
123   }
124
a11f6c 125   /**
U 126    * Bei diesem Visitor bleibt diese Methode ungenutzt, hier muessten noch Faelle 
127    * behandelt werden, die zu einem Abbruch fuehren und ggf. ein Rollback realisiert werden. 
128    * 
129    * Invoked for a file that could not be visited. This method is invoked if the file's attributes 
130    * could not be read, the file is a directory that could not be opened, and other reasons.
131    * 
132    * @param file  die Datei, bei der es zum Abbruch kam
133    * @param exc  the I/O exception that prevented the file from being visited
134    * @return stets FileVisitResult.CONTINUE
135    * @throws IOException wenn etwas schief laeuft
136    */
e369b9 137   @Override
U 138   public FileVisitResult visitFileFailed(Object file, IOException exc) throws IOException {
139     return FileVisitResult.CONTINUE;
140   }
141
a11f6c 142   /**
U 143    * Fuer jede Datei Schritte ausfuehren, wie sie sich nach einer Dateioperation ergeben. 
144    * Hier wird beim Verschieben von Dateien das Quellverzeichnis geloescht, nachdem es zum 
145    * Ziel uebertragen wurde.
146    * 
147    * Invoked for a directory after entries in the directory, and all of their descendants, 
148    * have been visited. This method is also invoked when iteration of the directory completes 
149    * prematurely (by a visitFile method returning SKIP_SIBLINGS, or an I/O error when 
150    * iterating over the directory).
151    * 
152    * @param dir   der fertig durchlaufene Quellordner
153    * @param exc  null if the iteration of the directory completes without an error; otherwise 
154    * the I/O exception that caused the iteration of the directory to complete prematurely
155    * @return
156    * @throws IOException 
157    */
e369b9 158   @Override
U 159   public FileVisitResult postVisitDirectory(Object dir, IOException exc) throws IOException {
973951 160     if (operation != Eraser.OP_DELETE) {
e369b9 161       if (dir instanceof Path) {
U 162         Path finishedDir = (Path) dir;
163         targetDir = targetDir.getParent();
973951 164         if(operation == Mover.OP_MOVE) {
e369b9 165           //logger.fine("delete " + finishedDir.toString());
U 166           Files.delete(finishedDir);
167         }
168       }
169       //logger.fine("targetDir now: " + targetDir.toString());
170     } else {
171       Files.delete((Path) dir);
172     }
173     return FileVisitResult.CONTINUE;
174   }
175
176 }