1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2.provider;
18
19 import org.apache.commons.lang3.StringUtils;
20 import org.apache.commons.vfs2.FileName;
21 import org.apache.commons.vfs2.FileSystemException;
22 import org.apache.commons.vfs2.FileType;
23 import org.apache.commons.vfs2.NameScope;
24 import org.apache.commons.vfs2.VFS;
25
26
27
28
29 public abstract class AbstractFileName implements FileName {
30
31
32
33
34
35
36
37
38
39
40
41
42
43 private static final char[] RESERVED_URI_CHARS = { '#', ' ' };
44
45 private final String scheme;
46 private final String absPath;
47 private FileType type;
48
49
50 private String uriString;
51 private String baseName;
52 private String rootUri;
53 private String extension;
54 private String decodedAbsPath;
55
56 private String key;
57
58 public AbstractFileName(final String scheme, final String absPath, final FileType type) {
59 this.rootUri = null;
60 this.scheme = scheme;
61 this.type = type;
62 if (StringUtils.isEmpty(absPath)) {
63 this.absPath = ROOT_PATH;
64 } else {
65 if (absPath.length() > 1 && absPath.endsWith("/")) {
66 this.absPath = absPath.substring(0, absPath.length() - 1);
67 } else {
68 this.absPath = absPath;
69 }
70 }
71 }
72
73 @Override
74 public boolean equals(final Object o) {
75 if (this == o) {
76 return true;
77 }
78 if (o == null || getClass() != o.getClass()) {
79 return false;
80 }
81
82 final AbstractFileName/../../org/apache/commons/vfs2/provider/AbstractFileName.html#AbstractFileName">AbstractFileName that = (AbstractFileName) o;
83
84 return getKey().equals(that.getKey());
85 }
86
87 @Override
88 public int hashCode() {
89 return getKey().hashCode();
90 }
91
92
93
94
95
96
97
98 @Override
99 public int compareTo(final FileName obj) {
100 final AbstractFileName/../../org/apache/commons/vfs2/provider/AbstractFileName.html#AbstractFileName">AbstractFileName name = (AbstractFileName) obj;
101 return getKey().compareTo(name.getKey());
102 }
103
104
105
106
107
108
109 @Override
110 public String toString() {
111 return getURI();
112 }
113
114
115
116
117
118
119
120
121 public abstract FileName createName(String absolutePath, FileType fileType);
122
123
124
125
126
127
128
129 protected abstract void appendRootUri(StringBuilder buffer, boolean addPassword);
130
131
132
133
134
135
136 @Override
137 public String getBaseName() {
138 if (baseName == null) {
139 final int idx = getPath().lastIndexOf(SEPARATOR_CHAR);
140 if (idx == -1) {
141 baseName = getPath();
142 } else {
143 baseName = getPath().substring(idx + 1);
144 }
145 }
146
147 return baseName;
148 }
149
150
151
152
153
154
155 @Override
156 public String getPath() {
157 if (VFS.isUriStyle()) {
158 return absPath + getUriTrailer();
159 }
160 return absPath;
161 }
162
163 protected String getUriTrailer() {
164 return getType().hasChildren() ? "/" : "";
165 }
166
167
168
169
170
171
172
173 @Override
174 public String getPathDecoded() throws FileSystemException {
175 if (decodedAbsPath == null) {
176 decodedAbsPath = UriParser.decode(getPath());
177 }
178
179 return decodedAbsPath;
180 }
181
182
183
184
185
186
187 @Override
188 public FileName getParent() {
189 final String parentPath;
190 final int idx = getPath().lastIndexOf(SEPARATOR_CHAR);
191 if (idx == -1 || idx == getPath().length() - 1) {
192
193 return null;
194 }
195 if (idx == 0) {
196
197 parentPath = SEPARATOR;
198 } else {
199 parentPath = getPath().substring(0, idx);
200 }
201 return createName(parentPath, FileType.FOLDER);
202 }
203
204
205
206
207
208
209 @Override
210 public FileName getRoot() {
211 FileName root = this;
212 while (root.getParent() != null) {
213 root = root.getParent();
214 }
215
216 return root;
217 }
218
219
220
221
222
223
224 @Override
225 public String getScheme() {
226 return scheme;
227 }
228
229
230
231
232
233
234 @Override
235 public String getURI() {
236 if (uriString == null) {
237 uriString = createURI();
238 }
239 return uriString;
240 }
241
242 protected String createURI() {
243 return createURI(false, true);
244 }
245
246
247
248
249
250
251 private String getKey() {
252 if (key == null) {
253 key = getURI();
254 }
255 return key;
256 }
257
258
259
260
261
262
263 @Override
264 public String getFriendlyURI() {
265 return createURI(false, false);
266 }
267
268 private String createURI(final boolean useAbsolutePath, final boolean usePassword) {
269 final StringBuilder buffer = new StringBuilder();
270 appendRootUri(buffer, usePassword);
271 buffer.append(handleURISpecialCharacters(useAbsolutePath ? absPath : getPath()));
272 return buffer.toString();
273 }
274
275 private String handleURISpecialCharacters(String uri) {
276 if (!StringUtils.isEmpty(uri)) {
277 try {
278
279
280 uri = UriParser.decode(uri);
281
282 return UriParser.encode(uri, RESERVED_URI_CHARS);
283 } catch (final FileSystemException e) {
284
285 }
286 }
287
288 return uri;
289 }
290
291
292
293
294
295
296
297
298 @Override
299 public String getRelativeName(final FileName name) throws FileSystemException {
300 final String path = name.getPath();
301
302
303 final int basePathLen = getPath().length();
304 final int pathLen = path.length();
305
306
307 if (basePathLen == 1 && pathLen == 1) {
308 return ".";
309 }
310 if (basePathLen == 1) {
311 return path.substring(1);
312 }
313
314 final int maxlen = Math.min(basePathLen, pathLen);
315 int pos = 0;
316 for (; pos < maxlen && getPath().charAt(pos) == path.charAt(pos); pos++) {
317
318 }
319
320 if (pos == basePathLen && pos == pathLen) {
321
322 return ".";
323 }
324 if (pos == basePathLen && pos < pathLen && path.charAt(pos) == SEPARATOR_CHAR) {
325
326 return path.substring(pos + 1);
327 }
328
329
330 final StringBuilder buffer = new StringBuilder();
331 if (pathLen > 1 && (pos < pathLen || getPath().charAt(pos) != SEPARATOR_CHAR)) {
332
333 pos = getPath().lastIndexOf(SEPARATOR_CHAR, pos);
334 buffer.append(path.substring(pos));
335 }
336
337
338
339 buffer.insert(0, "..");
340 pos = getPath().indexOf(SEPARATOR_CHAR, pos + 1);
341 while (pos != -1) {
342 buffer.insert(0, "../");
343 pos = getPath().indexOf(SEPARATOR_CHAR, pos + 1);
344 }
345
346 return buffer.toString();
347 }
348
349
350
351
352
353
354 @Override
355 public String getRootURI() {
356 if (rootUri == null) {
357 final StringBuilder buffer = new StringBuilder();
358 appendRootUri(buffer, true);
359 buffer.append(SEPARATOR_CHAR);
360 rootUri = buffer.toString().intern();
361 }
362 return rootUri;
363 }
364
365
366
367
368
369
370 @Override
371 public int getDepth() {
372 final int len = getPath().length();
373 if (len == 0 || len == 1 && getPath().charAt(0) == SEPARATOR_CHAR) {
374 return 0;
375 }
376 int depth = 1;
377 for (int pos = 0; pos > -1 && pos < len; depth++) {
378 pos = getPath().indexOf(SEPARATOR_CHAR, pos + 1);
379 }
380 return depth;
381 }
382
383
384
385
386
387
388 @Override
389 public String getExtension() {
390 if (extension == null) {
391 getBaseName();
392 final int pos = baseName.lastIndexOf('.');
393
394
395
396
397
398 if (pos < 1 || pos == baseName.length() - 1) {
399
400 extension = "";
401 } else {
402 extension = baseName.substring(pos + 1).intern();
403 }
404 }
405 return extension;
406 }
407
408
409
410
411
412
413
414 @Override
415 public boolean isAncestor(final FileName ancestor) {
416 if (!ancestor.getRootURI().equals(getRootURI())) {
417 return false;
418 }
419 return checkName(ancestor.getPath(), getPath(), NameScope.DESCENDENT);
420 }
421
422
423
424
425
426
427
428 @Override
429 public boolean isDescendent(final FileName descendent) {
430 return isDescendent(descendent, NameScope.DESCENDENT);
431 }
432
433
434
435
436
437
438
439
440 @Override
441 public boolean isDescendent(final FileName descendent, final NameScope scope) {
442 if (!descendent.getRootURI().equals(getRootURI())) {
443 return false;
444 }
445 return checkName(getPath(), descendent.getPath(), scope);
446 }
447
448
449
450
451
452
453
454
455
456 @Override
457 public boolean isFile() throws FileSystemException {
458
459 return FileType.FILE.equals(this.getType());
460 }
461
462
463
464
465
466
467
468
469
470
471
472
473
474 @Override
475 public FileType getType() {
476 return type;
477 }
478
479
480
481
482
483
484
485 void setType(final FileType type) throws FileSystemException {
486 if (type != FileType.FOLDER && type != FileType.FILE && type != FileType.FILE_OR_FOLDER) {
487 throw new FileSystemException("vfs.provider/filename-type.error");
488 }
489
490 this.type = type;
491 }
492
493
494
495
496
497
498
499
500
501 public static boolean checkName(final String basePath, final String path, final NameScope scope) {
502 if (scope == NameScope.FILE_SYSTEM) {
503
504 return true;
505 }
506
507 if (!path.startsWith(basePath)) {
508 return false;
509 }
510
511 int baseLen = basePath.length();
512 if (VFS.isUriStyle()) {
513
514 baseLen--;
515 }
516
517 if (scope == NameScope.CHILD) {
518 return path.length() != baseLen && (baseLen <= 1 || path.charAt(baseLen) == SEPARATOR_CHAR)
519 && path.indexOf(SEPARATOR_CHAR, baseLen + 1) == -1;
520 }
521 if (scope == NameScope.DESCENDENT) {
522 return path.length() != baseLen && (baseLen <= 1 || path.charAt(baseLen) == SEPARATOR_CHAR);
523 }
524 if (scope == NameScope.DESCENDENT_OR_SELF) {
525 return baseLen <= 1 || path.length() <= baseLen || path.charAt(baseLen) == SEPARATOR_CHAR;
526 }
527 throw new IllegalArgumentException();
528
529 }
530 }