1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2.impl;
18
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import org.apache.commons.vfs2.Capability;
24 import org.apache.commons.vfs2.FileName;
25 import org.apache.commons.vfs2.FileObject;
26 import org.apache.commons.vfs2.FileSystemException;
27 import org.apache.commons.vfs2.FileSystemOptions;
28 import org.apache.commons.vfs2.FileType;
29 import org.apache.commons.vfs2.NameScope;
30 import org.apache.commons.vfs2.provider.AbstractFileName;
31 import org.apache.commons.vfs2.provider.AbstractFileSystem;
32 import org.apache.commons.vfs2.provider.DelegateFileObject;
33
34
35
36
37
38
39
40 public class VirtualFileSystem extends AbstractFileSystem {
41
42 private final Map<FileName, FileObject> junctions = new HashMap<>();
43
44
45
46
47
48
49
50 public VirtualFileSystem(final AbstractFileName rootFileName, final FileSystemOptions fileSystemOptions) {
51 super(rootFileName, null, fileSystemOptions);
52 }
53
54
55
56
57 @Override
58 protected void addCapabilities(final Collection<Capability> caps) {
59
60 caps.add(Capability.ATTRIBUTES);
61 caps.add(Capability.CREATE);
62 caps.add(Capability.DELETE);
63 caps.add(Capability.GET_TYPE);
64 caps.add(Capability.JUNCTIONS);
65 caps.add(Capability.GET_LAST_MODIFIED);
66 caps.add(Capability.SET_LAST_MODIFIED_FILE);
67 caps.add(Capability.SET_LAST_MODIFIED_FOLDER);
68 caps.add(Capability.LIST_CHILDREN);
69 caps.add(Capability.READ_CONTENT);
70 caps.add(Capability.SIGNING);
71 caps.add(Capability.WRITE_CONTENT);
72 caps.add(Capability.APPEND_CONTENT);
73 }
74
75
76
77
78
79
80
81
82 @Override
83 public void addJunction(final String junctionPoint, final FileObject targetFile) throws FileSystemException {
84 final FileName junctionName = getFileSystemManager().resolveName(getRootName(), junctionPoint);
85
86
87 if (getJunctionForFile(junctionName) != null) {
88 throw new FileSystemException("vfs.impl/nested-junction.error", junctionName);
89 }
90
91 try {
92
93 junctions.put(junctionName, targetFile);
94
95
96 final DelegateFileObject junctionFile = (DelegateFileObject) getFileFromCache(junctionName);
97 if (junctionFile != null) {
98 junctionFile.setFile(targetFile);
99 }
100
101
102 FileName childName = junctionName;
103 boolean done = false;
104 for (AbstractFileName parentName = (AbstractFileName) childName.getParent(); !done
105 && parentName != null; childName = parentName, parentName = (AbstractFileName) parentName
106 .getParent()) {
107 DelegateFileObject file = (DelegateFileObject) getFileFromCache(parentName);
108 if (file == null) {
109 file = new DelegateFileObject(parentName, this, null);
110 putFileToCache(file);
111 } else {
112 done = file.exists();
113 }
114
115
116 file.attachChild(childName, FileType.FOLDER);
117 }
118
119
120 } catch (final Exception e) {
121 throw new FileSystemException("vfs.impl/create-junction.error", junctionName, e);
122 }
123 }
124
125 @Override
126 public void close() {
127 super.close();
128 junctions.clear();
129 }
130
131
132
133
134 @Override
135 protected FileObject createFile(final AbstractFileName name) throws Exception {
136
137 final FileName junctionPoint = getJunctionForFile(name);
138 final FileObject file;
139 if (junctionPoint != null) {
140
141 final FileObject junctionFile = junctions.get(junctionPoint);
142 final String relName = junctionPoint.getRelativeName(name);
143 file = junctionFile.resolveFile(relName, NameScope.DESCENDENT_OR_SELF);
144 } else {
145 file = null;
146 }
147
148
149 return new DelegateFileObject(name, this, file);
150 }
151
152
153
154
155
156
157
158 private FileName getJunctionForFile(final FileName name) {
159 if (junctions.containsKey(name)) {
160
161 return name;
162 }
163
164 return junctions.keySet().stream().filter(fileName -> fileName.isDescendent(name)).findFirst().orElse(null);
165 }
166
167
168
169
170
171
172
173 @Override
174 public void removeJunction(final String junctionPoint) throws FileSystemException {
175 final FileName junctionName = getFileSystemManager().resolveName(getRootName(), junctionPoint);
176 junctions.remove(junctionName);
177
178
179
180 }
181 }