1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs.impl;
18
19 import org.apache.commons.vfs.Capability;
20 import org.apache.commons.vfs.FileName;
21 import org.apache.commons.vfs.FileObject;
22 import org.apache.commons.vfs.FileSystemException;
23 import org.apache.commons.vfs.FileSystemOptions;
24 import org.apache.commons.vfs.FileType;
25 import org.apache.commons.vfs.NameScope;
26 import org.apache.commons.vfs.provider.AbstractFileSystem;
27 import org.apache.commons.vfs.provider.DelegateFileObject;
28
29 import java.util.Collection;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.Map;
33
34 /***
35 * A logical file system, made up of set of junctions, or links, to files from
36 * other file systems.
37 *
38 * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
39 * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
40 * @todo Handle nested junctions.
41 */
42 public class VirtualFileSystem
43 extends AbstractFileSystem
44 {
45 private final Map junctions = new HashMap();
46
47 public VirtualFileSystem(final FileName rootName, final FileSystemOptions fileSystemOptions)
48 {
49 super(rootName, null, fileSystemOptions);
50 }
51
52 /***
53 * Adds the capabilities of this file system.
54 */
55 protected void addCapabilities(final Collection caps)
56 {
57
58 caps.add(Capability.ATTRIBUTES);
59 caps.add(Capability.CREATE);
60 caps.add(Capability.DELETE);
61 caps.add(Capability.GET_TYPE);
62 caps.add(Capability.JUNCTIONS);
63 caps.add(Capability.GET_LAST_MODIFIED);
64 caps.add(Capability.SET_LAST_MODIFIED_FILE);
65 caps.add(Capability.SET_LAST_MODIFIED_FOLDER);
66 caps.add(Capability.LIST_CHILDREN);
67 caps.add(Capability.READ_CONTENT);
68 caps.add(Capability.SIGNING);
69 caps.add(Capability.WRITE_CONTENT);
70 caps.add(Capability.APPEND_CONTENT);
71 }
72
73 /***
74 * Creates a file object. This method is called only if the requested
75 * file is not cached.
76 */
77 protected FileObject createFile(final FileName name)
78 throws Exception
79 {
80
81 final FileName junctionPoint = getJunctionForFile(name);
82 final FileObject file;
83 if (junctionPoint != null)
84 {
85
86 final FileObject junctionFile = (FileObject) junctions.get(junctionPoint);
87 final String relName = junctionPoint.getRelativeName(name);
88 file = junctionFile.resolveFile(relName, NameScope.DESCENDENT_OR_SELF);
89 }
90 else
91 {
92 file = null;
93 }
94
95
96 return new DelegateFileObject(name, this, file);
97 }
98
99 /***
100 * Adds a junction to this file system.
101 */
102 public void addJunction(final String junctionPoint,
103 final FileObject targetFile)
104 throws FileSystemException
105 {
106 final FileName junctionName = getFileSystemManager().resolveName(getRootName(), junctionPoint);
107
108
109 if (getJunctionForFile(junctionName) != null)
110 {
111 throw new FileSystemException("vfs.impl/nested-junction.error", junctionName);
112 }
113
114 try
115 {
116
117 junctions.put(junctionName, targetFile);
118
119
120 final DelegateFileObject junctionFile = (DelegateFileObject) getFileFromCache(junctionName);
121 if (junctionFile != null)
122 {
123 junctionFile.setFile(targetFile);
124 }
125
126
127 FileName childName = junctionName;
128 boolean done = false;
129 for (FileName parentName = childName.getParent();
130 !done && parentName != null;
131 childName = parentName, parentName = parentName.getParent())
132 {
133 DelegateFileObject file = (DelegateFileObject) getFileFromCache(parentName);
134 if (file == null)
135 {
136 file = new DelegateFileObject(parentName, this, null);
137 putFileToCache(file);
138 }
139 else
140 {
141 done = file.exists();
142 }
143
144
145 file.attachChild(childName, FileType.FOLDER);
146 }
147
148
149 }
150 catch (final Exception e)
151 {
152 throw new FileSystemException("vfs.impl/create-junction.error", junctionName, e);
153 }
154 }
155
156 /***
157 * Removes a junction from this file system.
158 */
159 public void removeJunction(final String junctionPoint)
160 throws FileSystemException
161 {
162 final FileName junctionName = getFileSystemManager().resolveName(getRootName(), junctionPoint);
163 junctions.remove(junctionName);
164
165
166
167 }
168
169 /***
170 * Locates the junction point for the junction containing the given file.
171 */
172 private FileName getJunctionForFile(final FileName name)
173 {
174 if (junctions.containsKey(name))
175 {
176
177 return name;
178 }
179
180
181 for (Iterator iterator = junctions.keySet().iterator(); iterator.hasNext();)
182 {
183 final FileName junctionPoint = (FileName) iterator.next();
184 if (junctionPoint.isDescendent(name))
185 {
186 return junctionPoint;
187 }
188 }
189
190
191 return null;
192 }
193 }