1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2.impl;
18
19 import java.io.IOException;
20 import java.net.URL;
21 import java.security.CodeSource;
22 import java.security.Permission;
23 import java.security.PermissionCollection;
24 import java.security.Permissions;
25 import java.security.SecureClassLoader;
26 import java.security.cert.Certificate;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.Enumeration;
30 import java.util.List;
31 import java.util.jar.Attributes;
32 import java.util.jar.Attributes.Name;
33
34 import org.apache.commons.vfs2.FileObject;
35 import org.apache.commons.vfs2.FileSystemException;
36 import org.apache.commons.vfs2.FileSystemManager;
37 import org.apache.commons.vfs2.NameScope;
38 import org.apache.commons.vfs2.util.FileObjectUtils;
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class VFSClassLoader extends SecureClassLoader {
53 private final ArrayList<FileObject> resources = new ArrayList<>();
54
55
56
57
58
59
60
61
62 public VFSClassLoader(final FileObject file, final FileSystemManager manager) throws FileSystemException {
63 this(new FileObject[] {file}, manager, null);
64 }
65
66
67
68
69
70
71
72
73
74 public VFSClassLoader(final FileObject file, final FileSystemManager manager, final ClassLoader parent)
75 throws FileSystemException {
76 this(new FileObject[] {file}, manager, parent);
77 }
78
79
80
81
82
83
84
85
86 public VFSClassLoader(final FileObject[] files, final FileSystemManager manager) throws FileSystemException {
87 this(files, manager, null);
88 }
89
90
91
92
93
94
95
96
97
98
99 public VFSClassLoader(final FileObject[] files, final FileSystemManager manager, final ClassLoader parent)
100 throws FileSystemException {
101 super(parent);
102 addFileObjects(manager, files);
103 }
104
105
106
107
108
109
110
111
112 private void addFileObjects(final FileSystemManager manager, final FileObject[] files) throws FileSystemException {
113 for (FileObject file : files) {
114 if (!FileObjectUtils.exists(file)) {
115
116 continue;
117 }
118
119
120 if (manager.canCreateFileSystem(file)) {
121
122 file = manager.createFileSystem(file);
123 }
124
125 resources.add(file);
126 }
127 }
128
129
130
131
132
133
134
135 protected void copyPermissions(final PermissionCollection src, final PermissionCollection dest) {
136 for (final Enumeration<Permission> elem = src.elements(); elem.hasMoreElements();) {
137 dest.add(elem.nextElement());
138 }
139 }
140
141
142
143
144 private Class<?> defineClass(final String name, final Resource res) throws IOException {
145 final URL url = res.getCodeSourceURL();
146 final String pkgName = res.getPackageName();
147 if (pkgName != null) {
148 final Package pkg = getPackage(pkgName);
149 if (pkg != null) {
150 if (pkg.isSealed()) {
151 if (!pkg.isSealed(url)) {
152 throw new FileSystemException("vfs.impl/pkg-sealed-other-url", pkgName);
153 }
154 } else if (isSealed(res)) {
155 throw new FileSystemException("vfs.impl/pkg-sealing-unsealed", pkgName);
156 }
157 } else {
158 definePackage(pkgName, res);
159 }
160 }
161
162 final byte[] bytes = res.getBytes();
163 final Certificate[] certs = res.getFileObject().getContent().getCertificates();
164 final CodeSource cs = new CodeSource(url, certs);
165 return defineClass(name, bytes, 0, bytes.length, cs);
166 }
167
168
169
170
171 private Package definePackage(final String name, final Resource res) throws FileSystemException {
172
173 final String specTitle = res.getPackageAttribute(Name.SPECIFICATION_TITLE);
174 final String specVendor = res.getPackageAttribute(Attributes.Name.SPECIFICATION_VENDOR);
175 final String specVersion = res.getPackageAttribute(Name.SPECIFICATION_VERSION);
176 final String implTitle = res.getPackageAttribute(Name.IMPLEMENTATION_TITLE);
177 final String implVendor = res.getPackageAttribute(Name.IMPLEMENTATION_VENDOR);
178 final String implVersion = res.getPackageAttribute(Name.IMPLEMENTATION_VERSION);
179
180 final URL sealBase;
181 if (isSealed(res)) {
182 sealBase = res.getCodeSourceURL();
183 } else {
184 sealBase = null;
185 }
186
187 return definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
188 }
189
190
191
192
193
194
195 @Override
196 protected Class<?> findClass(final String name) throws ClassNotFoundException {
197 try {
198 final String path = name.replace('.', '/').concat(".class");
199 final Resource res = loadResource(path);
200 if (res == null) {
201 throw new ClassNotFoundException(name);
202 }
203 return defineClass(name, res);
204 } catch (final IOException ioe) {
205 throw new ClassNotFoundException(name, ioe);
206 }
207 }
208
209
210
211
212
213
214
215 @Override
216 protected URL findResource(final String name) {
217 try {
218 final Resource res = loadResource(name);
219 if (res != null) {
220 return res.getURL();
221 }
222 return null;
223 } catch (final Exception ignored) {
224 return null;
225 }
226 }
227
228
229
230
231
232
233
234
235
236
237 @Override
238 protected Enumeration<URL> findResources(final String name) throws IOException {
239 final List<URL> result = new ArrayList<>(2);
240
241 for (final FileObject baseFile : resources) {
242 try (FileObject file = baseFile.resolveFile(name, NameScope.DESCENDENT_OR_SELF)) {
243 if (FileObjectUtils.exists(file)) {
244 result.add(new Resource(name, baseFile, file).getURL());
245 }
246 }
247 }
248
249 return Collections.enumeration(result);
250 }
251
252
253
254
255
256
257
258 public FileObject[] getFileObjects() {
259 return resources.toArray(FileObject.EMPTY_ARRAY);
260 }
261
262
263
264
265
266
267
268 @Override
269 protected PermissionCollection getPermissions(final CodeSource cs) {
270 try {
271 final String url = cs.getLocation().toString();
272 final FileObject file = lookupFileObject(url);
273 if (file == null) {
274 return super.getPermissions(cs);
275 }
276
277 final FileObject parentLayer = file.getFileSystem().getParentLayer();
278 if (parentLayer == null) {
279 return super.getPermissions(cs);
280 }
281
282 final Permissions combi = new Permissions();
283 PermissionCollection permCollect = super.getPermissions(cs);
284 copyPermissions(permCollect, combi);
285
286 for (FileObject parent = parentLayer; parent != null; parent = parent.getFileSystem().getParentLayer()) {
287 final CodeSource parentcs = new CodeSource(parent.getURL(), parent.getContent().getCertificates());
288 permCollect = super.getPermissions(parentcs);
289 copyPermissions(permCollect, combi);
290 }
291
292 return combi;
293 } catch (final FileSystemException fse) {
294 throw new SecurityException(fse.getMessage());
295 }
296 }
297
298
299
300
301 private boolean isSealed(final Resource res) throws FileSystemException {
302 return Boolean.parseBoolean(res.getPackageAttribute(Attributes.Name.SEALED));
303 }
304
305
306
307
308
309
310
311
312 private Resource loadResource(final String name) throws FileSystemException {
313 for (final FileObject baseFile : resources) {
314 try (FileObject file = baseFile.resolveFile(name, NameScope.DESCENDENT_OR_SELF)) {
315 if (FileObjectUtils.exists(file)) {
316 return new Resource(name, baseFile, file);
317 }
318 }
319 }
320 return null;
321 }
322
323
324
325
326 private FileObject lookupFileObject(final String name) {
327 for (final FileObject object : resources) {
328 if (name.equals(object.getName().getURI())) {
329 return object;
330 }
331 }
332 return null;
333 }
334 }