1 22 package org.jboss.virtual.classloading; 23 24 import java.io.ByteArrayOutputStream ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.net.MalformedURLException ; 28 import java.net.URL ; 29 import java.security.CodeSource ; 30 import java.security.PermissionCollection ; 31 import java.security.ProtectionDomain ; 32 import java.security.SecureClassLoader ; 33 import java.security.cert.Certificate ; 34 import java.util.ArrayList ; 35 import java.util.Arrays ; 36 import java.util.Enumeration ; 37 import java.util.List ; 38 import java.util.Vector ; 39 40 import org.jboss.classloading.spi.ClassLoadingDomain; 41 import org.jboss.classloading.spi.DomainClassLoader; 42 import org.jboss.logging.Logger; 43 import org.jboss.virtual.VFS; 44 import org.jboss.virtual.VirtualFile; 45 46 51 public class VFSClassLoader extends SecureClassLoader 52 implements DomainClassLoader 53 { 54 private static Logger log = Logger.getLogger(VFSClassLoader.class); 55 56 protected static class ClassPathVFS 57 { 58 private ArrayList <String > searchCtxs = new ArrayList <String >(); 59 private VFS vfs; 60 protected ClassPathVFS(String [] searchCtxs, VFS vfs) 61 { 62 this.searchCtxs.addAll(Arrays.asList(searchCtxs)); 63 this.vfs = vfs; 64 } 65 } 66 protected ArrayList <ClassPathVFS> classpath = new ArrayList <ClassPathVFS>(); 67 68 74 public VFSClassLoader(String [] searchCtxs, VFS vfs) 75 { 76 String [] resolvedCtxs = searchCtxs; 77 try 78 { 79 resolvedCtxs = resolveSearchCtxs(searchCtxs, vfs); 80 } 81 catch(IOException e) 82 { 83 log.warn("Failed to resolve searchCtxs", e); 84 } 85 ClassPathVFS cp = new ClassPathVFS(resolvedCtxs, vfs); 86 classpath.add(cp); 87 } 88 95 public VFSClassLoader(String [] searchCtxs, VFS vfs, ClassLoader parent) 96 { 97 super(parent); 98 String [] resolvedCtxs = searchCtxs; 99 try 100 { 101 resolvedCtxs = resolveSearchCtxs(searchCtxs, vfs); 102 } 103 catch(IOException e) 104 { 105 log.warn("Failed to resolve searchCtxs", e); 106 } 107 ClassPathVFS cp = new ClassPathVFS(resolvedCtxs, vfs); 108 classpath.add(cp); 109 } 110 111 112 115 public URL [] getClasspath() 116 { 117 ArrayList <URL > cp = new ArrayList <URL >(classpath.size()); 118 for(ClassPathVFS entry : classpath) 119 { 120 try 121 { 122 URL baseURL = entry.vfs.getRoot().toURL(); 123 for(String path : entry.searchCtxs) 124 { 125 try 126 { 127 URL entryURL = new URL (baseURL, path); 128 cp.add(entryURL); 129 } 130 catch(MalformedURLException e) 131 { 132 log.debug("Failed to parse path: "+path, e); 133 } 134 } 135 } 136 catch(Exception e) 137 { 138 log.debug("Failed to parse entry: "+entry, e); 139 } 140 } 141 URL [] theClasspath = new URL [cp.size()]; 142 cp.toArray(theClasspath); 143 return theClasspath; 144 } 145 146 151 public String [] getPackageNames() 152 { 153 return null; 155 } 156 157 165 protected Class <?> findClass(String name) throws ClassNotFoundException 166 { 167 String resName = name.replace('.', '/'); 168 VirtualFile classFile = findResourceFile(resName+".class"); 169 if( classFile == null ) 170 throw new ClassNotFoundException (name); 171 try 172 { 173 byte[] tmp = new byte[128]; 174 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 175 InputStream is = classFile.openStream(); 176 int length; 177 while ((length = is.read(tmp)) > 0) 178 { 179 baos.write(tmp, 0, length); 180 } 181 is.close(); 182 tmp = baos.toByteArray(); 183 ProtectionDomain pd = getProtectionDomain(classFile); 184 return super.defineClass(name, tmp, 0, tmp.length, pd); 185 } 186 catch (Exception e) 187 { 188 throw new ClassNotFoundException (name, e); 189 } 190 } 191 192 198 public URL findResource(String name) 199 { 200 URL res = null; 201 VirtualFile vf = findResourceFile(name); 202 if( vf != null ) 203 { 204 try 205 { 206 res = vf.toURL(); 207 } 208 catch(Exception e) 209 { 210 if( log.isTraceEnabled() ) 211 log.trace("Failed to obtain vf URL: "+vf, e); 212 } 213 } 214 return res; 215 } 216 217 223 public Enumeration <URL > findResources(String name) throws IOException 224 { 225 Vector <URL > resources = new Vector <URL >(); 226 235 return resources.elements(); 236 } 237 public Enumeration <URL > findResourcesLocally(String name) throws IOException 238 { 239 return findResources(name); 240 } 241 242 public ClassLoadingDomain getDomain() 243 { 244 return null; 245 } 246 public void setDomain(ClassLoadingDomain domain) 247 { 248 } 249 250 public Class loadClassLocally(String name, boolean resolve) 251 throws ClassNotFoundException 252 { 253 return findClass(name); 254 } 255 256 public URL loadResourceLocally(String name) 257 { 258 return this.findResource(name); 259 } 260 261 266 public Package [] getPackages() 267 { 268 return super.getPackages(); 269 } 270 271 277 public Package getPackage(String name) 278 { 279 return super.getPackage(name); 280 } 281 282 protected VirtualFile findResourceFile(String name) 283 { 284 VirtualFile vf = null; 285 try 286 { 287 outer: 288 for(ClassPathVFS cp : classpath) 289 { 290 for(String ctx : cp.searchCtxs) 291 { 292 String path = ctx + '/' + name; 293 vf = cp.vfs.findChild(path); 294 if( vf != null ) 295 { 296 break outer; 297 } 298 } 299 } 300 } 301 catch (IOException e) 302 { 303 if( log.isTraceEnabled() ) 304 log.trace("Failed to find resource: "+name, e); 305 } 306 return vf; 307 } 308 309 318 protected ProtectionDomain getProtectionDomain(VirtualFile classFile) throws Exception 319 { 320 Certificate certs[] = null; 321 URL codesourceUrl = classFile.toURL(); 322 CodeSource cs = new CodeSource (codesourceUrl, certs); 323 PermissionCollection permissions = SecurityActions.getPolicy().getPermissions(cs); 324 if (log.isTraceEnabled()) 325 log.trace("getProtectionDomain, url=" + codesourceUrl + 326 " codeSource=" + cs + " permissions=" + permissions); 327 return new ProtectionDomain (cs, permissions); 328 } 329 330 339 protected String [] resolveSearchCtxs(String [] searchCtxs, VFS vfs) throws IOException 340 { 341 ArrayList <String > tmp = new ArrayList <String >(searchCtxs.length); 342 for(String ctx : searchCtxs) 343 { 344 if( ctx.endsWith("*.jar") ) 345 { 346 int slash = ctx.lastIndexOf('/'); 348 String dir = ""; 349 if( slash > 0 ) 350 dir = ctx.substring(0, slash); 351 VirtualFile dirFile = vfs.findChild(dir); 352 List <VirtualFile> children = dirFile.getChildren(); 353 StringBuilder sb = new StringBuilder (dir); 354 sb.append('/'); 355 int dirLength = sb.length(); 356 for(VirtualFile child : children) 357 { 358 String name = child.getName(); 359 if( name.endsWith(".jar") ) 360 { 361 sb.append(name); 362 String path = sb.toString(); 363 tmp.add(path); 364 sb.setLength(dirLength); 365 } 366 } 367 } 368 else 369 { 370 tmp.add(ctx); 371 } 372 } 373 log.debug("Resolved searchCtxs to: "+tmp); 374 String [] newCtxs = new String [tmp.size()]; 375 tmp.toArray(newCtxs); 376 return newCtxs; 377 } 378 } 379 | Popular Tags |