1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration2.io;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.lang.reflect.Method;
24 import java.net.MalformedURLException;
25 import java.net.URL;
26 import java.net.URLConnection;
27 import java.net.URLStreamHandler;
28 import java.util.Map;
29
30 import org.apache.commons.configuration2.ex.ConfigurationException;
31 import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.commons.vfs2.FileContent;
35 import org.apache.commons.vfs2.FileName;
36 import org.apache.commons.vfs2.FileObject;
37 import org.apache.commons.vfs2.FileSystemConfigBuilder;
38 import org.apache.commons.vfs2.FileSystemException;
39 import org.apache.commons.vfs2.FileSystemManager;
40 import org.apache.commons.vfs2.FileSystemOptions;
41 import org.apache.commons.vfs2.VFS;
42 import org.apache.commons.vfs2.provider.UriParser;
43
44
45
46
47
48
49 public class VFSFileSystem extends DefaultFileSystem {
50
51
52
53 private static final class VFSURLStreamHandler extends URLStreamHandler {
54
55 private final String protocol;
56
57 public VFSURLStreamHandler(final FileName file) {
58 this.protocol = file.getScheme();
59 }
60
61 @Override
62 protected URLConnection openConnection(final URL url) throws IOException {
63 throw new IOException("VFS URLs can only be used with VFS APIs");
64 }
65 }
66
67
68 private final Log log = LogFactory.getLog(getClass());
69
70 public VFSFileSystem() {
71
72 }
73
74 @Override
75 public String getBasePath(final String path) {
76 if (UriParser.extractScheme(path) == null) {
77 return super.getBasePath(path);
78 }
79 try {
80 final FileName parent = resolveURI(path).getParent();
81 return parent != null ? parent.getURI() : null;
82 } catch (final FileSystemException fse) {
83 fse.printStackTrace();
84 return null;
85 }
86 }
87
88 @Override
89 public String getFileName(final String path) {
90 if (UriParser.extractScheme(path) == null) {
91 return super.getFileName(path);
92 }
93 try {
94 return resolveURI(path).getBaseName();
95 } catch (final FileSystemException fse) {
96 fse.printStackTrace();
97 return null;
98 }
99 }
100
101 @Override
102 public InputStream getInputStream(final URL url) throws ConfigurationException {
103 final FileObject file;
104 try {
105 final FileSystemOptions opts = getOptions(url.getProtocol());
106 file = getManager().resolveFile(url.toString(), opts);
107 if (!file.exists()) {
108 throw new ConfigurationException("File not found");
109 }
110 if (!file.isFile()) {
111 throw new ConfigurationException("Cannot load a configuration from a directory");
112 }
113 final FileContent content = file.getContent();
114 if (content == null) {
115 final String msg = "Cannot access content of " + file.getName().getFriendlyURI();
116 throw new ConfigurationException(msg);
117 }
118 return content.getInputStream();
119 } catch (final FileSystemException fse) {
120 final String msg = "Unable to access " + url.toString();
121 throw new ConfigurationException(msg, fse);
122 }
123 }
124
125 private FileSystemManager getManager() throws FileSystemException {
126 return VFS.getManager();
127 }
128
129 private FileSystemOptions getOptions(final String scheme) {
130 if (scheme == null) {
131 return null;
132 }
133 final FileSystemOptions opts = new FileSystemOptions();
134 final FileSystemConfigBuilder builder;
135 try {
136 builder = getManager().getFileSystemConfigBuilder(scheme);
137 } catch (final Exception ex) {
138 return null;
139 }
140 final FileOptionsProvider provider = getFileOptionsProvider();
141 if (provider != null) {
142 final Map<String, Object> map = provider.getOptions();
143 if (map == null) {
144 return null;
145 }
146 int count = 0;
147 for (final Map.Entry<String, Object> entry : map.entrySet()) {
148 try {
149 String key = entry.getKey();
150 if (FileOptionsProvider.CURRENT_USER.equals(key)) {
151 key = "creatorName";
152 }
153 setProperty(builder, opts, key, entry.getValue());
154 ++count;
155 } catch (final Exception ex) {
156
157 continue;
158 }
159 }
160 if (count > 0) {
161 return opts;
162 }
163 }
164 return null;
165
166 }
167
168 @Override
169 public OutputStream getOutputStream(final URL url) throws ConfigurationException {
170 try {
171 final FileSystemOptions opts = getOptions(url.getProtocol());
172 final FileObject file = getManager().resolveFile(url.toString(), opts);
173
174 if (file == null || file.isFolder()) {
175 throw new ConfigurationException("Cannot save a configuration to a directory");
176 }
177 final FileContent content = file.getContent();
178
179 if (content == null) {
180 throw new ConfigurationException("Cannot access content of " + url);
181 }
182 return content.getOutputStream();
183 } catch (final FileSystemException fse) {
184 throw new ConfigurationException("Unable to access " + url, fse);
185 }
186 }
187
188 @Override
189 public String getPath(final File file, final URL url, final String basePath, final String fileName) {
190 if (file != null) {
191 return super.getPath(file, url, basePath, fileName);
192 }
193 try {
194 if (url != null) {
195 final FileName name = resolveURI(url.toString());
196 if (name != null) {
197 return name.toString();
198 }
199 }
200
201 if (UriParser.extractScheme(fileName) != null) {
202 return fileName;
203 }
204 if (basePath != null) {
205 final FileName base = resolveURI(basePath);
206 return getManager().resolveName(base, fileName).getURI();
207 }
208 final FileName name = resolveURI(fileName);
209 final FileName base = name.getParent();
210 return getManager().resolveName(base, name.getBaseName()).getURI();
211 } catch (final FileSystemException fse) {
212 fse.printStackTrace();
213 return null;
214 }
215 }
216
217 @Override
218 public URL getURL(final String basePath, final String file) throws MalformedURLException {
219 if (basePath != null && UriParser.extractScheme(basePath) == null || basePath == null && UriParser.extractScheme(file) == null) {
220 return super.getURL(basePath, file);
221 }
222 try {
223 final FileName path;
224 if (basePath != null && UriParser.extractScheme(file) == null) {
225 final FileName base = resolveURI(basePath);
226 path = getManager().resolveName(base, file);
227 } else {
228 path = resolveURI(file);
229 }
230
231 final URLStreamHandler handler = new VFSURLStreamHandler(path);
232 return new URL(null, path.getURI(), handler);
233 } catch (final FileSystemException fse) {
234 throw new ConfigurationRuntimeException("Could not parse basePath: " + basePath + " and fileName: " + file, fse);
235 }
236 }
237
238 @Override
239 public URL locateFromURL(final String basePath, final String fileName) {
240 final String fileScheme = UriParser.extractScheme(fileName);
241
242
243 if ((basePath == null || UriParser.extractScheme(basePath) == null) && fileScheme == null) {
244 return super.locateFromURL(basePath, fileName);
245 }
246 try {
247 final FileObject file;
248
249 if (basePath != null && fileScheme == null) {
250 final String scheme = UriParser.extractScheme(basePath);
251 final FileSystemOptions opts = getOptions(scheme);
252 FileObject base = getManager().resolveFile(basePath, opts);
253 if (base.isFile()) {
254 base = base.getParent();
255 }
256
257 file = getManager().resolveFile(base, fileName);
258 } else {
259 final FileSystemOptions opts = getOptions(fileScheme);
260 file = getManager().resolveFile(fileName, opts);
261 }
262
263 if (!file.exists()) {
264 return null;
265 }
266 final FileName path = file.getName();
267 final URLStreamHandler handler = new VFSURLStreamHandler(path);
268 return new URL(null, path.getURI(), handler);
269 } catch (final FileSystemException | MalformedURLException fse) {
270 return null;
271 }
272 }
273
274 private FileName resolveURI(final String path) throws FileSystemException {
275 return getManager().resolveURI(path);
276 }
277
278 private void setProperty(final FileSystemConfigBuilder builder, final FileSystemOptions options, final String key, final Object value) {
279 final String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
280 final Class<?>[] paramTypes = new Class<?>[2];
281 paramTypes[0] = FileSystemOptions.class;
282 paramTypes[1] = value.getClass();
283
284 try {
285 final Method method = builder.getClass().getMethod(methodName, paramTypes);
286 final Object[] params = new Object[2];
287 params[0] = options;
288 params[1] = value;
289 method.invoke(builder, params);
290 } catch (final Exception ex) {
291 log.warn("Cannot access property '" + key + "'! Ignoring.", ex);
292 }
293
294 }
295 }