1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs.provider;
18
19 import org.apache.commons.vfs.FileChangeEvent;
20 import org.apache.commons.vfs.FileListener;
21 import org.apache.commons.vfs.FileName;
22 import org.apache.commons.vfs.FileObject;
23 import org.apache.commons.vfs.FileSystemException;
24 import org.apache.commons.vfs.FileType;
25
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.security.cert.Certificate;
29 import java.util.HashSet;
30 import java.util.Map;
31 import java.util.Set;
32
33 /***
34 * A file backed by another file.
35 *
36 * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
37 * @author Gary D. Gregory
38 * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
39 * @todo Extract subclass that overlays the children
40 */
41 public class DelegateFileObject
42 extends AbstractFileObject
43 implements FileListener
44 {
45 private FileObject file;
46 private final Set children = new HashSet();
47 private boolean ignoreEvent;
48
49 public DelegateFileObject(final FileName name,
50 final AbstractFileSystem fileSystem,
51 final FileObject file) throws FileSystemException
52 {
53 super(name, fileSystem);
54 this.file = file;
55 if (file != null)
56 {
57 file.getFileSystem().addListener(file, this);
58 }
59 }
60
61 /***
62 * Adds a child to this file.
63 */
64 public void attachChild(final FileName baseName, final FileType type) throws Exception
65 {
66 final FileType oldType = doGetType();
67 if (children.add(baseName.getBaseName()))
68 {
69 childrenChanged(baseName, type);
70 }
71 maybeTypeChanged(oldType);
72 }
73
74 /***
75 * Attaches or detaches the target file.
76 */
77 public void setFile(final FileObject file) throws Exception
78 {
79 final FileType oldType = doGetType();
80
81 if (file != null)
82 {
83 file.getFileSystem().addListener(file, this);
84 }
85 this.file = file;
86 maybeTypeChanged(oldType);
87 }
88
89 /***
90 * Checks whether the file's type has changed, and fires the appropriate
91 * events.
92 */
93 private void maybeTypeChanged(final FileType oldType) throws Exception
94 {
95 final FileType newType = doGetType();
96 if (oldType == FileType.IMAGINARY && newType != FileType.IMAGINARY)
97 {
98 handleCreate(newType);
99 }
100 else if (oldType != FileType.IMAGINARY && newType == FileType.IMAGINARY)
101 {
102 handleDelete();
103 }
104 }
105
106 /***
107 * Determines the type of the file, returns null if the file does not
108 * exist.
109 */
110 protected FileType doGetType() throws FileSystemException
111 {
112 if (file != null)
113 {
114 return file.getType();
115 }
116 else if (children.size() > 0)
117 {
118 return FileType.FOLDER;
119 }
120 else
121 {
122 return FileType.IMAGINARY;
123 }
124 }
125
126 /***
127 * Determines if this file can be read.
128 */
129 protected boolean doIsReadable() throws FileSystemException
130 {
131 if (file != null)
132 {
133 return file.isReadable();
134 }
135 else
136 {
137 return true;
138 }
139 }
140
141 /***
142 * Determines if this file can be written to.
143 */
144 protected boolean doIsWriteable() throws FileSystemException
145 {
146 if (file != null)
147 {
148 return file.isWriteable();
149 }
150 else
151 {
152 return false;
153 }
154 }
155
156 /***
157 * Determines if this file is hidden.
158 */
159 protected boolean doIsHidden() throws FileSystemException
160 {
161 if (file != null)
162 {
163 return file.isHidden();
164 }
165 else
166 {
167 return false;
168 }
169 }
170
171 /***
172 * Lists the children of the file.
173 */
174 protected String[] doListChildren() throws Exception
175 {
176 if (file != null)
177 {
178 final FileObject[] children = file.getChildren();
179 final String[] childNames = new String[children.length];
180 for (int i = 0; i < children.length; i++)
181 {
182 childNames[i] = children[i].getName().getBaseName();
183 }
184 return childNames;
185 }
186 else
187 {
188 return (String[]) children.toArray(new String[children.size()]);
189 }
190 }
191
192 /***
193 * Creates this file as a folder.
194 */
195 protected void doCreateFolder() throws Exception
196 {
197 ignoreEvent = true;
198 try
199 {
200 file.createFolder();
201 }
202 finally
203 {
204 ignoreEvent = false;
205 }
206 }
207
208 /***
209 * Deletes the file.
210 */
211 protected void doDelete() throws Exception
212 {
213 ignoreEvent = true;
214 try
215 {
216 file.delete();
217 }
218 finally
219 {
220 ignoreEvent = false;
221 }
222 }
223
224 /***
225 * Returns the size of the file content (in bytes). Is only called if
226 * {@link #doGetType} returns {@link FileType#FILE}.
227 */
228 protected long doGetContentSize() throws Exception
229 {
230 return file.getContent().getSize();
231 }
232
233 /***
234 * Returns the attributes of this file.
235 */
236 protected Map doGetAttributes()
237 throws Exception
238 {
239 return file.getContent().getAttributes();
240 }
241
242 /***
243 * Sets an attribute of this file.
244 */
245 protected void doSetAttribute(final String atttrName,
246 final Object value)
247 throws Exception
248 {
249 file.getContent().setAttribute(atttrName, value);
250 }
251
252 /***
253 * Returns the certificates of this file.
254 */
255 protected Certificate[] doGetCertificates() throws Exception
256 {
257 return file.getContent().getCertificates();
258 }
259
260 /***
261 * Returns the last-modified time of this file.
262 */
263 protected long doGetLastModifiedTime() throws Exception
264 {
265 return file.getContent().getLastModifiedTime();
266 }
267
268 /***
269 * Sets the last-modified time of this file.
270 */
271 protected void doSetLastModifiedTime(final long modtime)
272 throws Exception
273 {
274 file.getContent().setLastModifiedTime(modtime);
275 }
276
277 /***
278 * Creates an input stream to read the file content from.
279 */
280 protected InputStream doGetInputStream() throws Exception
281 {
282 return file.getContent().getInputStream();
283 }
284
285 /***
286 * Creates an output stream to write the file content to.
287 */
288 protected OutputStream doGetOutputStream(boolean bAppend) throws Exception
289 {
290 return file.getContent().getOutputStream(bAppend);
291 }
292
293 /***
294 * Called when a file is created.
295 */
296 public void fileCreated(final FileChangeEvent event) throws Exception
297 {
298 if (!ignoreEvent)
299 {
300 handleCreate(file.getType());
301 }
302 }
303
304 /***
305 * Called when a file is deleted.
306 */
307 public void fileDeleted(final FileChangeEvent event) throws Exception
308 {
309 if (!ignoreEvent)
310 {
311 handleDelete();
312 }
313 }
314
315 /***
316 * Called when a file is changed.
317 * <p/>
318 * This will only happen if you monitor the file using {@link org.apache.commons.vfs.FileMonitor}.
319 */
320 public void fileChanged(FileChangeEvent event) throws Exception
321 {
322 if (!ignoreEvent)
323 {
324 handleChanged();
325 }
326 }
327
328 /***
329 * Close the delegated file
330 */
331 public void close() throws FileSystemException
332 {
333 super.close();
334
335 if (file != null)
336 {
337 file.close();
338 }
339 }
340 }