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 final String msg = "Cannot access content of " + file.getName().getFriendlyURI();
111 throw new ConfigurationException(msg);
112 }
113 return content.getInputStream();
114 } catch (final FileSystemException fse) {
115 final String msg = "Unable to access " + url.toString();
116 throw new ConfigurationException(msg, fse);
117 }
118 }
119
120 private FileSystemManager getManager() throws FileSystemException {
121 return VFS.getManager();
122 }
123
124 private FileSystemOptions getOptions(final String scheme) {
125 if (scheme == null) {
126 return null;
127 }
128 final FileSystemOptions opts = new FileSystemOptions();
129 final FileSystemConfigBuilder builder;
130 try {
131 builder = getManager().getFileSystemConfigBuilder(scheme);
132 } catch (final Exception ex) {
133 return null;
134 }
135 final FileOptionsProvider provider = getFileOptionsProvider();
136 if (provider != null) {
137 final Map<String, Object> map = provider.getOptions();
138 if (map == null) {
139 return null;
140 }
141 int count = 0;
142 for (final Map.Entry<String, Object> entry : map.entrySet()) {
143 try {
144 String key = entry.getKey();
145 if (FileOptionsProvider.CURRENT_USER.equals(key)) {
146 key = "creatorName";
147 }
148 setProperty(builder, opts, key, entry.getValue());
149 ++count;
150 } catch (final Exception ex) {
151
152 continue;
153 }
154 }
155 if (count > 0) {
156 return opts;
157 }
158 }
159 return null;
160
161 }
162
163 @Override
164 public OutputStream getOutputStream(final URL url) throws ConfigurationException {
165 try {
166 final FileSystemOptions opts = getOptions(url.getProtocol());
167 final FileObject file = getManager().resolveFile(url.toString(), opts);
168
169 if (file == null || file.isFolder()) {
170 throw new ConfigurationException("Cannot save a configuration to a directory");
171 }
172 final FileContent content = file.getContent();
173
174 if (content == null) {
175 throw new ConfigurationException("Cannot access content of " + url);
176 }
177 return content.getOutputStream();
178 } catch (final FileSystemException fse) {
179 throw new ConfigurationException("Unable to access " + url, fse);
180 }
181 }
182
183 @Override
184 public String getPath(final File file, final URL url, final String basePath, final String fileName) {
185 if (file != null) {
186 return super.getPath(file, url, basePath, fileName);
187 }
188 try {
189 if (url != null) {
190 final FileName name = resolveURI(url.toString());
191 if (name != null) {
192 return name.toString();
193 }
194 }
195 if (UriParser.extractScheme(fileName) != null) {
196 return fileName;
197 }
198 if (basePath != null) {
199 final FileName base = resolveURI(basePath);
200 return getManager().resolveName(base, fileName).getURI();
201 }
202 final FileName name = resolveURI(fileName);
203 final FileName base = name.getParent();
204 return getManager().resolveName(base, name.getBaseName()).getURI();
205 } catch (final FileSystemException fse) {
206 fse.printStackTrace();
207 return null;
208 }
209 }
210
211 @Override
212 public URL getURL(final String basePath, final String file) throws MalformedURLException {
213 if (basePath != null && UriParser.extractScheme(basePath) == null || basePath == null && UriParser.extractScheme(file) == null) {
214 return super.getURL(basePath, file);
215 }
216 try {
217 final FileName path;
218 if (basePath != null && UriParser.extractScheme(file) == null) {
219 final FileName base = resolveURI(basePath);
220 path = getManager().resolveName(base, file);
221 } else {
222 path = resolveURI(file);
223 }
224
225 final URLStreamHandler handler = new VFSURLStreamHandler();
226 return new URL(null, path.getURI(), handler);
227 } catch (final FileSystemException fse) {
228 throw new ConfigurationRuntimeException("Could not parse basePath: " + basePath + " and fileName: " + file, fse);
229 }
230 }
231
232 @Override
233 public URL locateFromURL(final String basePath, final String fileName) {
234 final String fileScheme = UriParser.extractScheme(fileName);
235
236 if ((basePath == null || UriParser.extractScheme(basePath) == null) && fileScheme == null) {
237 return super.locateFromURL(basePath, fileName);
238 }
239 try {
240 final FileObject file;
241
242 if (basePath != null && fileScheme == null) {
243 final String scheme = UriParser.extractScheme(basePath);
244 final FileSystemOptions opts = getOptions(scheme);
245 FileObject base = getManager().resolveFile(basePath, opts);
246 if (base.isFile()) {
247 base = base.getParent();
248 }
249
250 file = getManager().resolveFile(base, fileName);
251 } else {
252 final FileSystemOptions opts = getOptions(fileScheme);
253 file = getManager().resolveFile(fileName, opts);
254 }
255
256 if (!file.exists()) {
257 return null;
258 }
259 final FileName path = file.getName();
260 final URLStreamHandler handler = new VFSURLStreamHandler();
261 return new URL(null, path.getURI(), handler);
262 } catch (final FileSystemException | MalformedURLException fse) {
263 return null;
264 }
265 }
266
267 private FileName resolveURI(final String path) throws FileSystemException {
268 return getManager().resolveURI(path);
269 }
270
271 private void setProperty(final FileSystemConfigBuilder builder, final FileSystemOptions options, final String key, final Object value) {
272 final String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
273 final Class<?>[] paramTypes = new Class<?>[2];
274 paramTypes[0] = FileSystemOptions.class;
275 paramTypes[1] = value.getClass();
276 try {
277 final Method method = builder.getClass().getMethod(methodName, paramTypes);
278 final Object[] params = new Object[2];
279 params[0] = options;
280 params[1] = value;
281 method.invoke(builder, params);
282 } catch (final Exception ex) {
283 log.warn("Cannot access property '" + key + "'! Ignoring.", ex);
284 }
285 }
286 }