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