1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2.impl;
18
19 import java.io.File;
20 import java.util.ArrayList;
21 import java.util.Random;
22
23 import org.apache.commons.io.FileUtils;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.commons.vfs2.FileObject;
27 import org.apache.commons.vfs2.FileSelector;
28 import org.apache.commons.vfs2.FileSystemException;
29 import org.apache.commons.vfs2.VfsLog;
30 import org.apache.commons.vfs2.provider.AbstractVfsComponent;
31 import org.apache.commons.vfs2.provider.FileReplicator;
32 import org.apache.commons.vfs2.provider.TemporaryFileStore;
33 import org.apache.commons.vfs2.provider.UriParser;
34 import org.apache.commons.vfs2.util.Messages;
35
36
37
38
39 public class DefaultFileReplicator extends AbstractVfsComponent implements FileReplicator, TemporaryFileStore {
40
41 private static final Log log = LogFactory.getLog(DefaultFileReplicator.class);
42 private static final int MASK = 0xffff;
43
44 private static final Random RANDOM = new Random();
45
46 private static final char[] TMP_RESERVED_CHARS = {'?', '/', '\\', ' ', '&', '"', '\'', '*', '#', ';', ':', '<', '>', '|'};
47
48 private final ArrayList<Object> copies = new ArrayList<>();
49 private long fileCount;
50 private File tempDir;
51 private boolean tempDirMessageLogged;
52
53
54
55
56 public DefaultFileReplicator() {
57 }
58
59
60
61
62
63
64 public DefaultFileReplicator(final File tempDir) {
65 this.tempDir = tempDir;
66 }
67
68
69
70
71
72
73 protected void addFile(final Object file) {
74 synchronized (copies) {
75 copies.add(file);
76 }
77 }
78
79
80
81
82
83
84
85
86 @Override
87 public File allocateFile(final String baseName) throws FileSystemException {
88
89 final String actualBaseName = createFilename(baseName);
90 synchronized (this) {
91 fileCount++;
92 }
93
94 return createAndAddFile(tempDir, actualBaseName);
95 }
96
97
98
99
100 @Override
101 public void close() {
102
103 synchronized (copies) {
104 while (!copies.isEmpty()) {
105 deleteFile((File) removeFile());
106 }
107 }
108
109
110 if (tempDir != null && tempDir.exists()) {
111 final String[] list = tempDir.list();
112 if (list != null && list.length == 0) {
113 tempDir.delete();
114 tempDir = null;
115 }
116 }
117 }
118
119
120
121
122
123
124
125
126
127 protected File createAndAddFile(final File parent, final String baseName) throws FileSystemException {
128 final File file = createFile(tempDir, baseName);
129
130 addFile(file);
131 return file;
132 }
133
134
135
136
137
138
139
140
141
142 protected File createFile(final File parent, final String name) throws FileSystemException {
143 return new File(parent, UriParser.decode(name));
144 }
145
146
147
148
149
150
151
152 protected String createFilename(final String baseName) {
153
154
155
156
157
158 final String safeBaseName = UriParser.encode(baseName, TMP_RESERVED_CHARS).replace('%', '_');
159 return "tmp_" + getFilecount() + "_" + safeBaseName;
160 }
161
162
163
164
165
166
167 protected void deleteFile(final File file) {
168 try {
169 final FileObject fileObject = getContext().toFileObject(file);
170 fileObject.deleteAll();
171 } catch (final FileSystemException e) {
172 final String message = Messages.getString("vfs.impl/delete-temp.warn", file.getName());
173 VfsLog.warn(getLogger(), log, message, e);
174 }
175 }
176
177
178
179
180
181
182 protected long getFilecount() {
183 return fileCount;
184 }
185
186
187
188
189
190
191 @Override
192 public void init() throws FileSystemException {
193 if (tempDir == null) {
194 tempDir = new File(FileUtils.getTempDirectoryPath(), "vfs_cache").getAbsoluteFile();
195 }
196
197 fileCount = RANDOM.nextInt() & MASK;
198
199 if (!tempDirMessageLogged) {
200 final String message = Messages.getString("vfs.impl/temp-dir.debug", tempDir);
201 VfsLog.debug(getLogger(), log, message);
202
203 tempDirMessageLogged = true;
204 }
205 }
206
207
208
209
210
211
212
213
214 protected Object removeFile() {
215 synchronized (copies) {
216 return copies.remove(0);
217 }
218 }
219
220
221
222
223
224
225 protected void removeFile(final Object file) {
226 synchronized (copies) {
227 copies.remove(file);
228 }
229 }
230
231
232
233
234
235
236
237
238
239 @Override
240 public File replicateFile(final FileObject srcFile, final FileSelector selector) throws FileSystemException {
241 final String baseName = srcFile.getName().getBaseName();
242 final File file = allocateFile(baseName);
243
244
245 final FileObject destFile = getContext().toFileObject(file);
246 destFile.copyFrom(srcFile, selector);
247
248 return file;
249 }
250 }