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