1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs.impl;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.apache.commons.vfs.FileObject;
22 import org.apache.commons.vfs.FileSelector;
23 import org.apache.commons.vfs.FileSystemException;
24 import org.apache.commons.vfs.Selectors;
25 import org.apache.commons.vfs.VfsLog;
26 import org.apache.commons.vfs.provider.AbstractVfsComponent;
27 import org.apache.commons.vfs.provider.FileReplicator;
28 import org.apache.commons.vfs.provider.TemporaryFileStore;
29 import org.apache.commons.vfs.provider.UriParser;
30 import org.apache.commons.vfs.util.Messages;
31
32 import java.io.File;
33 import java.util.ArrayList;
34 import java.util.Random;
35
36 /***
37 * A simple file replicator and temporary file store.
38 *
39 * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
40 * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
41 */
42 public class DefaultFileReplicator
43 extends AbstractVfsComponent
44 implements FileReplicator, TemporaryFileStore
45 {
46 private final static Log log = LogFactory.getLog(DefaultFileReplicator.class);
47
48 private final ArrayList copies = new ArrayList();
49 private File tempDir;
50 private long filecount;
51 private boolean tempDirMessageLogged;
52
53 private char[] TMP_RESERVED_CHARS = new char[]
54 {
55 '?', '/', '//', ' ', '&', '"', '\'', '*', '#', ';', ':', '<', '>', '|'
56 };
57
58 /***
59 * constructor to set the location of the temporary directory
60 *
61 * @param tempDir
62 */
63 public DefaultFileReplicator(final File tempDir)
64 {
65 this.tempDir = tempDir;
66 }
67
68 public DefaultFileReplicator()
69 {
70 }
71
72 /***
73 * Initialises this component.
74 */
75 public void init() throws FileSystemException
76 {
77 if (tempDir == null)
78 {
79 String baseTmpDir = System.getProperty("java.io.tmpdir");
80
81 tempDir = new File(baseTmpDir, "vfs_cache").getAbsoluteFile();
82 }
83
84 filecount = new Random().nextInt() & 0xffff;
85
86 if (!tempDirMessageLogged)
87 {
88 final String message = Messages.getString("vfs.impl/temp-dir.info", tempDir);
89 VfsLog.info(getLogger(), log, message);
90
91 tempDirMessageLogged = true;
92 }
93 }
94
95 /***
96 * Closes the replicator, deleting all temporary files.
97 */
98 public void close()
99 {
100
101 synchronized (copies)
102 {
103 while (copies.size() > 0)
104 {
105 final File file = (File) removeFile();
106 deleteFile(file);
107 }
108 }
109
110
111 if (tempDir != null && tempDir.exists() && tempDir.list().length == 0)
112 {
113 tempDir.delete();
114 tempDir = null;
115 }
116 }
117
118 /***
119 * physically deletes the file from the filesystem
120 */
121 protected void deleteFile(File file)
122 {
123 try
124 {
125 final FileObject fileObject = getContext().toFileObject(file);
126 fileObject.delete(Selectors.SELECT_ALL);
127 }
128 catch (final FileSystemException e)
129 {
130 final String message = Messages.getString("vfs.impl/delete-temp.warn", file.getName());
131 VfsLog.warn(getLogger(), log, message, e);
132 }
133 }
134
135 /***
136 * removes a file from the copies list. Will be used for cleanup. <br/>
137 * Notice: The system awaits that the returning object can be cast to a java.io.File
138 */
139 protected Object removeFile()
140 {
141 synchronized (copies)
142 {
143 return copies.remove(0);
144 }
145 }
146
147 /***
148 * removes a instance from the list of copies
149 */
150 protected void removeFile(Object file)
151 {
152 synchronized (copies)
153 {
154 copies.remove(file);
155 }
156 }
157
158 /***
159 * Allocates a new temporary file.
160 */
161 public File allocateFile(final String baseName) throws FileSystemException
162 {
163
164 final String basename = createFilename(baseName);
165 synchronized (this)
166 {
167 filecount++;
168 }
169
170 final File file = createAndAddFile(tempDir, basename);
171
172 return file;
173 }
174
175 protected File createAndAddFile(final File parent, final String basename) throws FileSystemException
176 {
177 final File file = createFile(tempDir, basename);
178
179
180 addFile(file);
181
182 return file;
183 }
184
185 protected void addFile(Object file)
186 {
187 synchronized (copies)
188 {
189 copies.add(file);
190 }
191 }
192
193 protected long getFilecount()
194 {
195 return filecount;
196 }
197
198 /***
199 * create the temporary file name
200 */
201 protected String createFilename(final String baseName)
202 {
203
204
205
206
207
208 String safeBasename = UriParser.encode(baseName, TMP_RESERVED_CHARS).replace('%', '_');
209 return "tmp_" + getFilecount() + "_" + safeBasename;
210 }
211
212 /***
213 * create the temporary file
214 */
215 protected File createFile(final File parent, final String name) throws FileSystemException
216 {
217 return new File(parent, UriParser.decode(name));
218 }
219
220 /***
221 * Creates a local copy of the file, and all its descendents.
222 */
223 public File replicateFile(final FileObject srcFile,
224 final FileSelector selector)
225 throws FileSystemException
226 {
227 final String basename = srcFile.getName().getBaseName();
228 final File file = allocateFile(basename);
229
230
231 final FileObject destFile = getContext().toFileObject(file);
232 destFile.copyFrom(srcFile, selector);
233
234 return file;
235 }
236 }