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 package uk.ac.rdg.resc.jstyx.client;
30
31 import java.io.File;
32 import java.io.FileFilter;
33 import java.io.FilenameFilter;
34 import java.io.IOException;
35 import java.util.ArrayList;
36
37 import org.apache.log4j.Logger;
38
39 import uk.ac.rdg.resc.jstyx.client.CStyxFile;
40 import uk.ac.rdg.resc.jstyx.StyxException;
41
42 /***
43 * Wraps a CStyxFile as a java.io.File. This allows Styx servers to be browsed
44 * by Java-based filesystem viewers
45 *
46 * @author Jon Blower
47 * $Revision: 259 $
48 * $Date: 2005-05-23 17:48:23 +0100 (Mon, 23 May 2005) $
49 * $Log$
50 * Revision 1.3 2005/05/23 16:48:17 jonblower
51 * Overhauled CStyxFile (esp. asynchronous methods) and StyxConnection (added cache of CStyxFiles)
52 *
53 * Revision 1.2 2005/03/11 13:58:25 jonblower
54 * Merged MINA-Test_20059309 into main line of development
55 *
56 * Revision 1.1.2.1 2005/03/11 08:29:52 jonblower
57 * Moved to log4j logging system (from apache commons logging)
58 *
59 * Revision 1.1 2005/03/07 08:27:51 jonblower
60 * Initial import
61 *
62 */
63 public class FileWrapper extends File
64 {
65 private static final Logger log = Logger.getLogger(FileWrapper.class);
66
67 private CStyxFile file;
68
69 /***
70 * Creates a new instance of FileWrapper that wraps the given CStyxFile.
71 * @todo What happens if the file isn't connected to an open connection yet?
72 */
73 public FileWrapper(CStyxFile file)
74 {
75 super(file.getPath());
76 this.file = file;
77 log.debug("Created FileWrapper(" + file.getPath() + ")");
78 }
79
80 /***
81 * @return the CStyxFile that this FileWrapper wraps
82 */
83 public CStyxFile getCStyxFile()
84 {
85 return this.file;
86 }
87
88 /***
89 * Gets the name of the file, i.e. the last part of the path
90 */
91 public String getName()
92 {
93 return this.file.getName();
94 }
95
96 /***
97 * Gets the full path of the file. Makes sure that "/" is used as the separator
98 */
99 public String getPath()
100 {
101 return this.file.getPath();
102 }
103
104 /***
105 * @return a string representing the parent of this file, or null if this
106 * is the root directory
107 */
108 public String getParent()
109 {
110 log.debug("Called getParent() for " + this.getPath());
111 String path = this.file.getPath();
112 if (path.endsWith("/"))
113 {
114 path = path.substring(0, path.length() - 1);
115 }
116 int lastSlash = path.lastIndexOf("/");
117 if (lastSlash == -1)
118 {
119
120 return null;
121 }
122 else
123 {
124
125 return path.substring(0, lastSlash);
126 }
127 }
128
129 /***
130 * @return the parent of this FileWrapper as another FileWrapper, or null
131 * if this file does not have a parent
132 */
133 public File getParentFile()
134 {
135 log.debug("Called getParentFile() for " + this.getPath());
136 String parentPath = this.getParent();
137 if (parentPath == null)
138 {
139 return null;
140 }
141 if (parentPath.equals(this.getPath()))
142 {
143
144 return null;
145 }
146 else
147 {
148 CStyxFile newFile = this.file.getConnection().getFile(parentPath);
149 return new FileWrapper(newFile);
150 }
151 }
152
153 /***
154 * @return true if this path starts with a slash (always return true
155 * since CStyxFile always stores the full pathname)
156 */
157 public boolean isAbsolute()
158 {
159 if (!this.getPath().startsWith("/"))
160 {
161 log.warn("Path " + this.getPath() + " is not absolute");
162 }
163 return true;
164 }
165
166 /***
167 * @return the absolute pathname of this file. Simply returns this.getPath()
168 * since pathnames are always absolute.
169 */
170 public String getAbsolutePath()
171 {
172 return this.getPath();
173 }
174
175 /***
176 * @return a FileWrapper representing the absolute pathname. Simply returns
177 * this object, since pathnames are always absolute
178 */
179 public File getAbsoluteFile()
180 {
181 return this;
182 }
183
184 /***
185 * @return the canonical filename, i.e. the unique filename after removing
186 * . and .. parts of the path. Simply returns the absolute path.
187 */
188 public String getCanonicalPath() throws IOException
189 {
190 return this.getAbsolutePath();
191 }
192
193 /***
194 * @return a FileWrapper that represents the canonical filename. Simply
195 * returns the absolute File (i.e. this object)
196 */
197 public File getCanonicalFile() throws IOException
198 {
199 return this.getAbsoluteFile();
200 }
201
202 /***
203 * Tests whether this FileWrapper wraps a directory
204 */
205 public boolean isDirectory()
206 {
207 try
208 {
209 return this.file.isDirectory();
210 }
211 catch(StyxException se)
212 {
213 log.error(se.getMessage());
214 return false;
215 }
216 }
217
218 /***
219 * Tests whether this FileWrapper wraps a normal file (i.e. not a directory)
220 * @todo Should test that it's not an auth file, append-only, exclusive etc
221 */
222 public boolean isFile()
223 {
224 return !this.isDirectory();
225 }
226
227 /***
228 * @return the length of the file in bytes
229 */
230 public long length()
231 {
232 try
233 {
234 return this.file.getLength();
235 }
236 catch(StyxException se)
237 {
238 log.error(se.getMessage());
239 return 0;
240 }
241 }
242
243 /***
244 * @return The time that the file was last modified, in milliseconds
245 * since the epoch
246 */
247 public long lastModified()
248 {
249 try
250 {
251 return this.file.getLastModified().getTime();
252 }
253 catch(StyxException se)
254 {
255 log.error(se.getMessage());
256 return 0;
257 }
258 }
259
260 /***
261 * @return Array of strings naming the files and directories in the directory
262 * that this FileWrapper represents. Returns null if this is not a directory.
263 */
264 public String[] list()
265 {
266 log.debug("Called (String[])list() for " + this.getPath());
267 try
268 {
269 CStyxFile[] files = this.file.getChildren();
270 if (files == null)
271 {
272 return null;
273 }
274 String[] filenames = new String[files.length];
275 for (int i = 0; i < files.length; i++)
276 {
277 filenames[i] = files[i].getPath();
278 }
279 return filenames;
280 }
281 catch(StyxException se)
282 {
283 log.error(se.getMessage());
284 return null;
285 }
286 }
287
288 /***
289 * Returns an array of abstract pathnames denoting the files and
290 * directories in the directory denoted by this abstract pathname that
291 * satisfy the specified filter.
292 */
293 public String[] list(FilenameFilter filter)
294 {
295 log.debug("Called (String[])list(FilenameFilter) for " + this.getPath());
296 try
297 {
298 CStyxFile[] files = this.file.getChildren();
299 if (files == null)
300 {
301 return null;
302 }
303 ArrayList v = new ArrayList();
304 for (int i = 0; i < files.length; i++)
305 {
306 String name = files[i].getPath();
307 if ((filter == null) || filter.accept(this, name))
308 {
309 v.add(name);
310 }
311 }
312 return (String[])(v.toArray(new String[0]));
313 }
314 catch(StyxException se)
315 {
316 log.error(se.getMessage());
317 return null;
318 }
319 }
320
321 /***
322 * Returns an array of FileWrappers denoting the files in this
323 * directory.
324 */
325 public File[] listFiles()
326 {
327 log.debug("Called (File[])listFiles() for " + this.getPath());
328 try
329 {
330 CStyxFile[] files = this.file.getChildren();
331 if (files == null)
332 {
333 return null;
334 }
335 FileWrapper[] wrappers = new FileWrapper[files.length];
336 for (int i = 0; i < files.length; i++)
337 {
338 wrappers[i] = new FileWrapper(files[i]);
339 }
340 return wrappers;
341 }
342 catch(StyxException se)
343 {
344 log.error(se.getMessage());
345 return null;
346 }
347 }
348
349 /***
350 * Returns an array of abstract pathnames denoting the files and
351 * directories in the directory denoted by this abstract pathname that
352 * satisfy the specified filter.
353 */
354 public File[] listFiles(FilenameFilter filter)
355 {
356 log.debug("Called (File[])listFiles(FilenameFilter) for " + this.getPath());
357 try
358 {
359 CStyxFile[] files = this.file.getChildren();
360 if (files == null)
361 {
362 return null;
363 }
364 ArrayList v = new ArrayList();
365 for (int i = 0; i < files.length; i++)
366 {
367 String name = files[i].getPath();
368 if ((filter == null) || filter.accept(this, name))
369 {
370 v.add(new FileWrapper(files[i]));
371 }
372 }
373 return (FileWrapper[])(v.toArray(new FileWrapper[0]));
374 }
375 catch(StyxException se)
376 {
377 log.error(se.getMessage());
378 return null;
379 }
380 }
381
382 /***
383 * Returns an array of abstract pathnames denoting the files and
384 * directories in the directory denoted by this abstract pathname that
385 * satisfy the specified filter.
386 */
387 public File[] listFiles(FileFilter filter)
388 {
389 log.debug("Called (File[])listFiles(FileFilter) for " + this.getPath());
390 try
391 {
392 CStyxFile[] files = this.file.getChildren();
393 if (files == null)
394 {
395 return null;
396 }
397 ArrayList v = new ArrayList();
398 for (int i = 0; i < files.length; i++)
399 {
400 FileWrapper wrapper = new FileWrapper(files[i]);
401 if ((filter == null) || filter.accept(wrapper))
402 {
403 v.add(wrapper);
404 }
405 }
406 return (FileWrapper[])(v.toArray(new FileWrapper[0]));
407 }
408 catch(StyxException se)
409 {
410 log.error(se.getMessage());
411 return null;
412 }
413 }
414
415 /***
416 * Lists available filesystem roots. At the moment this just returns a
417 * single-membered array of java.io.File with the member "/". So it is
418 * not connected to the root of the remote Styx filesystem. Is this
419 * going to work? We can't get the root of the real remote filesystem because
420 * this is a static method.
421 */
422 public static File[] listRoots()
423 {
424 log.debug("Called FileWrapper.listRoots()");
425 return new File[]{new File("/")};
426 }
427
428 }