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