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 }