1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2.provider.ram;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.Serializable;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.Objects;
27
28 import org.apache.commons.vfs2.Capability;
29 import org.apache.commons.vfs2.FileContent;
30 import org.apache.commons.vfs2.FileName;
31 import org.apache.commons.vfs2.FileObject;
32 import org.apache.commons.vfs2.FileSystemException;
33 import org.apache.commons.vfs2.FileSystemOptions;
34 import org.apache.commons.vfs2.FileType;
35 import org.apache.commons.vfs2.provider.AbstractFileName;
36 import org.apache.commons.vfs2.provider.AbstractFileSystem;
37
38
39
40
41 public class RamFileSystem extends AbstractFileSystem implements Serializable {
42
43
44
45
46 private static final long serialVersionUID = 20101208L;
47
48
49
50
51 private final Map<FileName, RamFileData> cache;
52
53
54
55
56
57
58
59 protected RamFileSystem(final FileName rootName, final FileSystemOptions fileSystemOptions) {
60 super(rootName, null, fileSystemOptions);
61 cache = Collections.synchronizedMap(new HashMap<>());
62
63 final RamFileData rootData = new RamFileData(rootName);
64 rootData.setType(FileType.FOLDER);
65 rootData.setLastModified(System.currentTimeMillis());
66 cache.put(rootName, rootData);
67 }
68
69
70
71
72
73
74 @Override
75 protected void addCapabilities(final Collection<Capability> caps) {
76 caps.addAll(RamFileProvider.capabilities);
77 }
78
79
80
81
82
83
84 public void attach(final RamFileObject ramFileObject) {
85 if (ramFileObject.getName() == null) {
86 throw new IllegalArgumentException("Null argument");
87 }
88 RamFileData data = cache.get(ramFileObject.getName());
89 if (data == null) {
90 data = new RamFileData(ramFileObject.getName());
91 }
92 ramFileObject.setData(data);
93 }
94
95
96
97
98 @Override
99 public void close() {
100 cache.clear();
101 super.close();
102 }
103
104
105
106
107
108
109 @Override
110 protected FileObject createFile(final AbstractFileName name) throws Exception {
111 return new RamFileObject(name, this);
112 }
113
114
115
116
117
118
119
120 void delete(final RamFileObject file) throws FileSystemException {
121
122 FileSystemException.requireNonNull(file.getParent(), "unable to delete root");
123
124
125 cache.remove(file.getName());
126
127 final RamFileObject parent = (RamFileObject) this.resolveFile(file.getParent().getName());
128 parent.getData().removeChild(file.getData());
129 parent.close();
130
131 file.getData().clear();
132 file.close();
133 }
134
135
136
137
138
139
140
141 public void importTree(final File file) throws FileSystemException {
142 final FileObject fileFo = getFileSystemManager().toFileObject(file);
143 toRamFileObject(fileFo, fileFo);
144 }
145
146
147
148
149
150 String[] listChildren(final FileName name) {
151 final RamFileData data = cache.get(name);
152 if (data == null || !data.getType().hasChildren()) {
153 return null;
154 }
155 final Collection<RamFileData> children = data.getChildren();
156
157 synchronized (children) {
158 return children.stream().filter(Objects::nonNull).map(childData -> childData.getName().getBaseName()).toArray(String[]::new);
159 }
160 }
161
162
163
164
165
166
167 void rename(final RamFileObject from, final RamFileObject to) throws FileSystemException {
168 if (!cache.containsKey(from.getName())) {
169 throw new FileSystemException("File does not exist: " + from.getName());
170 }
171
172
173 to.getData().setContent(from.getData().getContent());
174 to.getData().setLastModified(from.getData().getLastModified());
175 to.getData().setType(from.getData().getType());
176
177 save(to);
178 delete(from);
179 }
180
181
182
183
184
185
186
187 void save(final RamFileObject file) throws FileSystemException {
188
189
190 if (file.getData().getName() == null) {
191 throw new FileSystemException(new IllegalStateException("The data has no name. " + file));
192 }
193
194
195 if (file.getName().getDepth() > 0) {
196 final RamFileData parentData = cache.get(file.getParent().getName());
197
198 if (!parentData.hasChildren(file.getData())) {
199 final RamFileObject parent = (RamFileObject) file.getParent();
200 parent.getData().addChild(file.getData());
201 parent.close();
202 }
203 }
204
205 cache.put(file.getName(), file.getData());
206 file.getData().updateLastModified();
207 file.close();
208 }
209
210
211
212
213 long size() {
214 synchronized (cache) {
215 return cache.values().stream().mapToLong(RamFileData::size).sum();
216 }
217 }
218
219
220
221
222
223
224
225
226 private void toRamFileObject(final FileObject fo, final FileObject root) throws FileSystemException {
227 final RamFileObject memFo = (RamFileObject) this
228 .resolveFile(fo.getName().getPath().substring(root.getName().getPath().length()));
229 if (fo.getType().hasChildren()) {
230
231 memFo.createFolder();
232
233 final FileObject[] fos = fo.getChildren();
234 for (final FileObject child : fos) {
235 toRamFileObject(child, root);
236 }
237 } else if (fo.isFile()) {
238
239 try (FileContent content = fo.getContent()) {
240 content.write(memFo);
241 } catch (final IOException e) {
242 throw new FileSystemException(e.getClass().getName() + " " + e.getMessage());
243 }
244 } else {
245 throw new FileSystemException("File is not a folder nor a file " + memFo);
246 }
247 }
248 }