1 17 package org.apache.geronimo.kernel.classloader; 18 19 import java.io.IOException ; 20 import java.io.File ; 21 import java.net.URL ; 22 import java.net.URI ; 23 import java.net.URLClassLoader ; 24 import java.security.AccessControlContext ; 25 import java.security.AccessController ; 26 import java.security.CodeSource ; 27 import java.security.PrivilegedAction ; 28 import java.security.PrivilegedExceptionAction ; 29 import java.security.PrivilegedActionException ; 30 import java.security.cert.Certificate ; 31 import java.util.Collection ; 32 import java.util.Enumeration ; 33 import java.util.jar.Attributes ; 34 import java.util.jar.Manifest ; 35 36 import org.apache.geronimo.kernel.config.MultiParentClassLoader; 37 import org.apache.geronimo.kernel.repository.Artifact; 38 39 52 public class JarFileClassLoader extends MultiParentClassLoader { 53 private static final URL [] EMPTY_URLS = new URL [0]; 54 55 private final UrlResourceFinder resourceFinder = new UrlResourceFinder(); 56 private final AccessControlContext acc; 57 58 63 public JarFileClassLoader(Artifact id, URL [] urls) { 64 super(id, EMPTY_URLS); 65 this.acc = AccessController.getContext(); 66 addURLs(urls); 67 } 68 69 75 public JarFileClassLoader(Artifact id, URL [] urls, ClassLoader parent) { 76 super(id, EMPTY_URLS, parent); 77 this.acc = AccessController.getContext(); 78 addURLs(urls); 79 } 80 81 public JarFileClassLoader(Artifact id, URL [] urls, ClassLoader parent, boolean inverseClassLoading, String [] hiddenClasses, String [] nonOverridableClasses) { 82 super(id, EMPTY_URLS, parent, inverseClassLoading, hiddenClasses, nonOverridableClasses); 83 this.acc = AccessController.getContext(); 84 addURLs(urls); 85 } 86 87 93 public JarFileClassLoader(Artifact id, URL [] urls, ClassLoader [] parents) { 94 super(id, EMPTY_URLS, parents); 95 this.acc = AccessController.getContext(); 96 addURLs(urls); 97 } 98 99 public JarFileClassLoader(Artifact id, URL [] urls, ClassLoader [] parents, boolean inverseClassLoading, Collection hiddenClasses, Collection nonOverridableClasses) { 100 super(id, EMPTY_URLS, parents, inverseClassLoading, hiddenClasses, nonOverridableClasses); 101 this.acc = AccessController.getContext(); 102 addURLs(urls); 103 } 104 105 public JarFileClassLoader(Artifact id, URL [] urls, ClassLoader [] parents, boolean inverseClassLoading, String [] hiddenClasses, String [] nonOverridableClasses) { 106 super(id, EMPTY_URLS, parents, inverseClassLoading, hiddenClasses, nonOverridableClasses); 107 this.acc = AccessController.getContext(); 108 addURLs(urls); 109 } 110 111 public JarFileClassLoader(JarFileClassLoader source) { 112 super(source); 113 this.acc = AccessController.getContext(); 114 addURLs(source.getURLs()); 115 } 116 117 public static ClassLoader copy(ClassLoader source) { 118 if (source instanceof JarFileClassLoader) { 119 return new JarFileClassLoader((JarFileClassLoader) source); 120 } else if (source instanceof MultiParentClassLoader) { 121 return new MultiParentClassLoader((MultiParentClassLoader) source); 122 } else if (source instanceof URLClassLoader ) { 123 return new URLClassLoader (((URLClassLoader )source).getURLs(), source.getParent()); 124 } else { 125 return new URLClassLoader (new URL [0], source); 126 } 127 } 128 129 ClassLoader copy() { 130 return JarFileClassLoader.copy(this); 131 } 132 133 136 public URL [] getURLs() { 137 return resourceFinder.getUrls(); 138 } 139 140 143 public void addURL(final URL url) { 144 AccessController.doPrivileged(new PrivilegedAction () { 145 public Object run() { 146 resourceFinder.addUrl(url); 147 return null; 148 } 149 }, acc); 150 } 151 152 156 protected void addURLs(final URL [] urls) { 157 AccessController.doPrivileged(new PrivilegedAction () { 158 public Object run() { 159 resourceFinder.addUrls(urls); 160 return null; 161 } 162 }, acc); 163 } 164 165 168 public void destroy() { 169 resourceFinder.destroy(); 170 super.destroy(); 171 } 172 173 176 public URL findResource(final String resourceName) { 177 return (URL ) AccessController.doPrivileged(new PrivilegedAction () { 178 public Object run() { 179 return resourceFinder.findResource(resourceName); 180 } 181 }, acc); 182 } 183 184 187 public Enumeration findResources(final String resourceName) throws IOException { 188 Enumeration parentResources = super.findResources(resourceName); 191 192 Enumeration myResources = (Enumeration ) AccessController.doPrivileged(new PrivilegedAction () { 194 public Object run() { 195 return resourceFinder.findResources(resourceName); 196 } 197 }, acc); 198 199 Enumeration resources = new UnionEnumeration(parentResources, myResources); 201 return resources; 202 } 203 204 207 protected String findLibrary(String libraryName) { 208 int pathEnd = libraryName.lastIndexOf('/'); 210 if (pathEnd == libraryName.length() - 1) { 211 throw new IllegalArgumentException ("libraryName ends with a '/' character: " + libraryName); 212 } 213 214 final String resourceName; 216 if (pathEnd < 0) { 217 resourceName = System.mapLibraryName(libraryName); 218 } else { 219 String path = libraryName.substring(0, pathEnd + 1); 220 String file = libraryName.substring(pathEnd + 1); 221 resourceName = path + System.mapLibraryName(file); 222 } 223 224 ResourceHandle resourceHandle = (ResourceHandle) AccessController.doPrivileged(new PrivilegedAction () { 226 public Object run() { 227 return resourceFinder.getResource(resourceName); 228 } 229 }, acc); 230 231 if (resourceHandle == null) { 232 return null; 233 } 234 235 URL url = resourceHandle.getUrl(); 237 if (!"file".equals(url.getProtocol())) { 238 return null; 239 } 240 241 String path = new File (URI.create(url.toString())).getPath(); 242 return path; 243 } 244 245 248 protected Class findClass(final String className) throws ClassNotFoundException { 249 try { 250 return (Class ) AccessController.doPrivileged(new PrivilegedExceptionAction () { 251 public Object run() throws ClassNotFoundException { 252 SecurityManager securityManager = System.getSecurityManager(); 254 if (securityManager != null) { 255 String packageName; 256 int packageEnd = className.lastIndexOf('.'); 257 if (packageEnd >= 0) { 258 packageName = className.substring(0, packageEnd); 259 securityManager.checkPackageDefinition(packageName); 260 } 261 } 262 263 264 String resourceName = className.replace('.', '/') + ".class"; 266 267 ResourceHandle resourceHandle = resourceFinder.getResource(resourceName); 269 if (resourceHandle == null) { 270 throw new ClassNotFoundException (className); 271 } 272 273 byte[] bytes; 274 Manifest manifest; 275 try { 276 bytes = resourceHandle.getBytes(); 278 279 manifest = resourceHandle.getManifest(); 281 } catch (IOException e) { 282 throw new ClassNotFoundException (className, e); 283 } 284 285 Certificate [] certificates = resourceHandle.getCertificates(); 287 288 URL codeSourceUrl = resourceHandle.getCodeSourceUrl(); 290 291 definePackage(className, codeSourceUrl, manifest); 293 294 CodeSource codeSource = new CodeSource (codeSourceUrl, certificates); 296 297 Class clazz = defineClass(className, bytes, 0, bytes.length, codeSource); 299 return clazz; 300 } 301 }, acc); 302 } catch (PrivilegedActionException e) { 303 throw (ClassNotFoundException ) e.getException(); 304 } 305 } 306 307 private void definePackage(String className, URL jarUrl, Manifest manifest) { 308 int packageEnd = className.lastIndexOf('.'); 309 if (packageEnd < 0) { 310 return; 311 } 312 313 String packageName = className.substring(0, packageEnd); 314 String packagePath = packageName.replace('.', '/') + "/"; 315 316 Attributes packageAttributes = null; 317 Attributes mainAttributes = null; 318 if (manifest != null) { 319 packageAttributes = manifest.getAttributes(packagePath); 320 mainAttributes = manifest.getMainAttributes(); 321 } 322 Package pkg = getPackage(packageName); 323 if (pkg != null) { 324 if (pkg.isSealed()) { 325 if (!pkg.isSealed(jarUrl)) { 326 throw new SecurityException ("Package was already sealed with another URL: package=" + packageName + ", url=" + jarUrl); 327 } 328 } else { 329 if (isSealed(packageAttributes, mainAttributes)) { 330 throw new SecurityException ("Package was already been loaded and not sealed: package=" + packageName + ", url=" + jarUrl); 331 } 332 } 333 } else { 334 String specTitle = getAttribute(Attributes.Name.SPECIFICATION_TITLE, packageAttributes, mainAttributes); 335 String specVendor = getAttribute(Attributes.Name.SPECIFICATION_VENDOR, packageAttributes, mainAttributes); 336 String specVersion = getAttribute(Attributes.Name.SPECIFICATION_VERSION, packageAttributes, mainAttributes); 337 String implTitle = getAttribute(Attributes.Name.IMPLEMENTATION_TITLE, packageAttributes, mainAttributes); 338 String implVendor = getAttribute(Attributes.Name.IMPLEMENTATION_VENDOR, packageAttributes, mainAttributes); 339 String implVersion = getAttribute(Attributes.Name.IMPLEMENTATION_VERSION, packageAttributes, mainAttributes); 340 341 URL sealBase = null; 342 if (isSealed(packageAttributes, mainAttributes)) { 343 sealBase = jarUrl; 344 } 345 346 definePackage(packageName, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase); 347 } 348 } 349 350 private String getAttribute(Attributes.Name name, Attributes packageAttributes, Attributes mainAttributes) { 351 if (packageAttributes != null) { 352 String value = packageAttributes.getValue(name); 353 if (value != null) { 354 return value; 355 } 356 } 357 if (mainAttributes != null) { 358 return mainAttributes.getValue(name); 359 } 360 return null; 361 } 362 363 private boolean isSealed(Attributes packageAttributes, Attributes mainAttributes) { 364 String sealed = getAttribute(Attributes.Name.SEALED, packageAttributes, mainAttributes); 365 if (sealed == null) { 366 return false; 367 } 368 return "true".equalsIgnoreCase(sealed); 369 } 370 } | Popular Tags |