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