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 }