KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > vfs > provider > AbstractFileName


1 /*
2  * Copyright 2002-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.vfs.provider;
17
18 import org.apache.commons.vfs.FileName;
19 import org.apache.commons.vfs.FileSystemException;
20 import org.apache.commons.vfs.FileType;
21 import org.apache.commons.vfs.NameScope;
22 import org.apache.commons.vfs.VFS;
23
24 /**
25  * A default file name implementation.
26  *
27  * @author <a HREF="mailto:adammurdoch@apache.org">Adam Murdoch</a>
28  */

29 public abstract class AbstractFileName
30     implements FileName
31 {
32     private final String JavaDoc scheme;
33     private final String JavaDoc absPath;
34     private FileType type;
35
36     // Cached stuff
37
private String JavaDoc uri;
38     private String JavaDoc baseName;
39     private String JavaDoc rootUri;
40     private String JavaDoc extension;
41     private String JavaDoc decodedAbsPath;
42
43     public AbstractFileName(final String JavaDoc scheme,
44                             final String JavaDoc absPath, FileType type)
45     {
46         this.rootUri = null;
47         this.scheme = scheme;
48         this.type = type;
49         if (absPath != null && absPath.length() > 0)
50         {
51             if (absPath.length() > 1 && absPath.endsWith("/"))
52             {
53                 this.absPath = absPath.substring(0, absPath.length() - 1);
54             }
55             else
56             {
57                 this.absPath = absPath;
58             }
59         }
60         else
61         {
62             this.absPath = ROOT_PATH;
63         }
64     }
65
66     /**
67      * Returns the hashcode for this name.
68      */

69     public int hashCode()
70     {
71         return (getRootURI().hashCode() ^ getPath().hashCode());
72     }
73
74     /**
75      * Determines if this object is equal to another.
76      */

77     public boolean equals(final Object JavaDoc obj)
78     {
79         final AbstractFileName name = (AbstractFileName) obj;
80         return (getRootURI().equals(name.getRootURI()) && getPath().equals(name.getPath()));
81     }
82
83     /**
84      * Implement Comparable
85      *
86      * @param obj another abstractfilename
87      */

88     public int compareTo(Object JavaDoc obj)
89     {
90         final AbstractFileName name = (AbstractFileName) obj;
91         int ret = getRootURI().compareTo(name.getRootURI());
92         if (ret != 0)
93         {
94             return ret;
95         }
96
97         // return absPath.compareTo(name.absPath);
98
try
99         {
100             return getPathDecoded().compareTo(name.getPathDecoded());
101         }
102         catch (FileSystemException e)
103         {
104             throw new RuntimeException JavaDoc(e.getMessage());
105         }
106     }
107
108     /**
109      * Returns the URI of the file.
110      */

111     public String JavaDoc toString()
112     {
113         return getURI();
114     }
115
116     /**
117      * Factory method for creating name instances.
118      */

119     public abstract FileName createName(String JavaDoc absPath, FileType type);
120
121     /**
122      * Builds the root URI for this file name. Note that the root URI must not
123      * end with a separator character.
124      */

125     protected abstract void appendRootUri(StringBuffer JavaDoc buffer);
126
127     /**
128      * Returns the base name of the file.
129      */

130     public String JavaDoc getBaseName()
131     {
132         if (baseName == null)
133         {
134             final int idx = getPath().lastIndexOf(SEPARATOR_CHAR);
135             if (idx == -1)
136             {
137                 baseName = getPath();
138             }
139             else
140             {
141                 baseName = getPath().substring(idx + 1);
142             }
143         }
144
145         return baseName;
146     }
147
148     /**
149      * Returns the absolute path of the file, relative to the root of the
150      * file system that the file belongs to.
151      */

152     public String JavaDoc getPath()
153     {
154         if (VFS.isUriStyle())
155         {
156             return absPath + getUriTrailer();
157         }
158         return absPath;
159     }
160
161     protected String JavaDoc getUriTrailer()
162     {
163         return getType() == FileType.FOLDER ? "/" : "";
164     }
165
166     public String JavaDoc getPathDecoded() throws FileSystemException
167     {
168         if (decodedAbsPath == null)
169         {
170             decodedAbsPath = UriParser.decode(getPath());
171         }
172
173         return decodedAbsPath;
174     }
175
176     /**
177      * Returns the name of the parent of the file.
178      */

179     public FileName getParent()
180     {
181         final String JavaDoc parentPath;
182         final int idx = getPath().lastIndexOf(SEPARATOR_CHAR);
183         if (idx == -1 || idx == getPath().length() - 1)
184         {
185             // No parent
186
return null;
187         }
188         else if (idx == 0)
189         {
190             // Root is the parent
191
parentPath = SEPARATOR;
192         }
193         else
194         {
195             parentPath = getPath().substring(0, idx);
196         }
197         return createName(parentPath, FileType.FOLDER);
198     }
199
200     /**
201      * find the root of the filesystem
202      */

203     public FileName getRoot()
204     {
205         FileName root = this;
206         while (root.getParent() != null)
207         {
208             root = root.getParent();
209         }
210
211         return root;
212     }
213
214     /**
215      * Returns the URI scheme of this file.
216      */

217     public String JavaDoc getScheme()
218     {
219         return scheme;
220     }
221
222     /**
223      * Returns the absolute URI of the file.
224      */

225     public String JavaDoc getURI()
226     {
227         if (uri == null)
228         {
229             uri = createURI();
230         }
231         return uri;
232     }
233
234     protected String JavaDoc createURI()
235     {
236         final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
237         appendRootUri(buffer);
238         buffer.append(getPath());
239         return buffer.toString();
240     }
241
242     /**
243      * Converts a file name to a relative name, relative to this file name.
244      */

245     public String JavaDoc getRelativeName(final FileName name) throws FileSystemException
246     {
247         final String JavaDoc path = name.getPath();
248
249         // Calculate the common prefix
250
final int basePathLen = getPath().length();
251         final int pathLen = path.length();
252
253         // Deal with root
254
if (basePathLen == 1 && pathLen == 1)
255         {
256             return ".";
257         }
258         else if (basePathLen == 1)
259         {
260             return path.substring(1);
261         }
262
263         final int maxlen = Math.min(basePathLen, pathLen);
264         int pos = 0;
265         for (; pos < maxlen && getPath().charAt(pos) == path.charAt(pos); pos++)
266         {
267         }
268
269         if (pos == basePathLen && pos == pathLen)
270         {
271             // Same names
272
return ".";
273         }
274         else if (pos == basePathLen && pos < pathLen && path.charAt(pos) == SEPARATOR_CHAR)
275         {
276             // A descendent of the base path
277
return path.substring(pos + 1);
278         }
279
280         // Strip the common prefix off the path
281
final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
282         if (pathLen > 1 && (pos < pathLen || getPath().charAt(pos) != SEPARATOR_CHAR))
283         {
284             // Not a direct ancestor, need to back up
285
pos = getPath().lastIndexOf(SEPARATOR_CHAR, pos);
286             buffer.append(path.substring(pos));
287         }
288
289         // Prepend a '../' for each element in the base path past the common
290
// prefix
291
buffer.insert(0, "..");
292         pos = getPath().indexOf(SEPARATOR_CHAR, pos + 1);
293         while (pos != -1)
294         {
295             buffer.insert(0, "../");
296             pos = getPath().indexOf(SEPARATOR_CHAR, pos + 1);
297         }
298
299         return buffer.toString();
300     }
301
302     /**
303      * Returns the root URI of the file system this file belongs to.
304      */

305     public String JavaDoc getRootURI()
306     {
307         if (rootUri == null)
308         {
309             final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
310             appendRootUri(buffer);
311             buffer.append(SEPARATOR_CHAR);
312             rootUri = buffer.toString();
313         }
314         return rootUri;
315     }
316
317     /**
318      * Returns the depth of this file name, within its file system.
319      */

320     public int getDepth()
321     {
322         final int len = getPath().length();
323         if (len == 0 || (len == 1 && getPath().charAt(0) == SEPARATOR_CHAR))
324         {
325             return 0;
326         }
327         int depth = 1;
328         for (int pos = 0; pos > -1 && pos < len; depth++)
329         {
330             pos = getPath().indexOf(SEPARATOR_CHAR, pos + 1);
331         }
332         return depth;
333     }
334
335     /**
336      * Returns the extension of this file name.
337      */

338     public String JavaDoc getExtension()
339     {
340         if (extension == null)
341         {
342             getBaseName();
343             final int pos = baseName.lastIndexOf('.');
344             // if ((pos == -1) || (pos == baseName.length() - 1))
345
// imario@ops.co.at: Review of patch from adagoubard@chello.nl
346
// do not treat filenames like
347
// .bashrc c:\windows\.java c:\windows\.javaws c:\windows\.jedit c:\windows\.appletviewer
348
// as extension
349
if ((pos < 1) || (pos == baseName.length() - 1))
350             {
351                 // No extension
352
extension = "";
353             }
354             else
355             {
356                 extension = baseName.substring(pos + 1);
357             }
358         }
359         return extension;
360     }
361
362     /**
363      * Determines if another file name is an ancestor of this file name.
364      */

365     public boolean isAncestor(final FileName ancestor)
366     {
367         if (!ancestor.getRootURI().equals(getRootURI()))
368         {
369             return false;
370         }
371         return checkName(ancestor.getPath(), getPath(), NameScope.DESCENDENT);
372     }
373
374     /**
375      * Determines if another file name is a descendent of this file name.
376      */

377     public boolean isDescendent(final FileName descendent)
378     {
379         return isDescendent(descendent, NameScope.DESCENDENT);
380     }
381
382     /**
383      * Determines if another file name is a descendent of this file name.
384      */

385     public boolean isDescendent(final FileName descendent,
386                                 final NameScope scope)
387     {
388         if (!descendent.getRootURI().equals(getRootURI()))
389         {
390             return false;
391         }
392         return checkName(getPath(), descendent.getPath(), scope);
393     }
394
395     /**
396      * Returns the requested or current type of this name. <br />
397      * <p/>
398      * The "requested" type is the one determined during resolving the name. <br/>
399      * In this case the name is a {@link FileType#FOLDER} if it ends with an "/" else
400      * it will be a {@link FileType#FILE}<br/>
401      * </p>
402      * <p/>
403      * Once attached it will be changed to reflect the real type of this resource.
404      * </p>
405      *
406      * @return {@link FileType#FOLDER} or {@link FileType#FILE}
407      */

408     public FileType getType()
409     {
410         return type;
411     }
412
413     /**
414      * sets the type of this file e.g. when it will be attached.
415      *
416      * @param type {@link FileType#FOLDER} or {@link FileType#FILE}
417      */

418     void setType(FileType type) throws FileSystemException
419     {
420         if (type != FileType.FOLDER && type != FileType.FILE)
421         {
422             throw new FileSystemException("vfs.provider/filename-type.error");
423         }
424
425         this.type = type;
426     }
427
428     /**
429      * Checks whether a path fits in a particular scope of another path.
430      *
431      * @param basePath An absolute, normalised path.
432      * @param path An absolute, normalised path.
433      */

434     public static boolean checkName(final String JavaDoc basePath,
435                                     final String JavaDoc path,
436                                     final NameScope scope)
437     {
438         if (scope == NameScope.FILE_SYSTEM)
439         {
440             // All good
441
return true;
442         }
443
444         if (!path.startsWith(basePath))
445         {
446             return false;
447         }
448
449         int baseLen = basePath.length();
450         if (VFS.isUriStyle())
451         {
452             // strip the trailing "/"
453
baseLen--;
454         }
455
456         if (scope == NameScope.CHILD)
457         {
458             if (path.length() == baseLen
459                 || (baseLen > 1 && path.charAt(baseLen) != SEPARATOR_CHAR)
460                 || path.indexOf(SEPARATOR_CHAR, baseLen + 1) != -1)
461             {
462                 return false;
463             }
464         }
465         else if (scope == NameScope.DESCENDENT)
466         {
467             if (path.length() == baseLen
468                 || (baseLen > 1 && path.charAt(baseLen) != SEPARATOR_CHAR))
469             {
470                 return false;
471             }
472         }
473         else if (scope == NameScope.DESCENDENT_OR_SELF)
474         {
475             if (baseLen > 1
476                 && path.length() > baseLen
477                 && path.charAt(baseLen) != SEPARATOR_CHAR)
478             {
479                 return false;
480             }
481         }
482         else if (scope != NameScope.FILE_SYSTEM)
483         {
484             throw new IllegalArgumentException JavaDoc();
485         }
486
487         return true;
488     }
489 }
490
Popular Tags