1 23 24 package org.gjt.sp.jedit; 25 26 import java.io.InputStream ; 28 import java.io.IOException ; 29 import java.net.URL ; 30 import java.util.*; 31 import java.util.zip.ZipEntry ; 32 import java.util.zip.ZipFile ; 33 import org.gjt.sp.util.Log; 34 35 import java.util.jar.Manifest ; 36 import java.util.jar.JarFile ; 37 import java.net.MalformedURLException ; 38 import java.util.jar.Attributes ; 39 import java.util.jar.Attributes.Name; 40 42 48 public class JARClassLoader extends ClassLoader 49 { 50 56 public JARClassLoader() 57 { 58 this(true); 59 } 60 61 67 public JARClassLoader(boolean delegateFirst) { 68 this.delegateFirst = delegateFirst; 69 id = INDEX++; 71 live++; 72 } 74 78 public Class loadClass(String clazz, boolean resolveIt) 79 throws ClassNotFoundException 80 { 81 ClassNotFoundException pending = null; 82 if (delegateFirst) 83 { 84 try 85 { 86 return loadFromParent(clazz); 87 } 88 catch (ClassNotFoundException cnf) 89 { 90 pending = cnf; 92 } 93 } 94 95 Object obj = classHash.get(clazz); 96 if(obj == NO_CLASS) 97 { 98 throw new ClassNotFoundException (clazz); 102 } 103 else if(obj instanceof JARClassLoader) 104 { 105 JARClassLoader classLoader = (JARClassLoader)obj; 106 try 107 { 108 return classLoader._loadClass(clazz,resolveIt); 109 } catch (ClassNotFoundException cnf2) 110 { 111 classHash.put(clazz,NO_CLASS); 112 throw cnf2; 113 } 114 } 115 else if (delegateFirst) 116 { 117 throw pending; 121 } 122 123 return loadFromParent(clazz); 124 } 126 public InputStream getResourceAsStream(String name) 128 { 129 if(jar == null) 130 return null; 131 132 try 133 { 134 ZipFile zipFile = jar.getZipFile(); 135 ZipEntry entry = zipFile.getEntry(name); 136 if(entry == null) 137 return getSystemResourceAsStream(name); 138 else 139 return zipFile.getInputStream(entry); 140 } 141 catch(IOException io) 142 { 143 Log.log(Log.ERROR,this,io); 144 145 return null; 146 } 147 } 149 public URL getResource(String name) 151 { 152 if(jar == null) 153 return null; 154 155 try 156 { 157 ZipFile zipFile = jar.getZipFile(); 158 ZipEntry entry = zipFile.getEntry(name); 159 if(entry == null) 160 return getSystemResource(name); 161 else 162 return new URL (getResourceAsPath(name)); 163 } 164 catch(IOException io) 165 { 166 Log.log(Log.ERROR,this,io); 167 return null; 168 } 169 } 171 public String getResourceAsPath(String name) 173 { 174 if(jar == null) 175 return null; 176 177 if(!name.startsWith("/")) 178 name = "/" + name; 179 180 return "jeditresource:/" + MiscUtilities.getFileName( 181 jar.getPath()) + "!" + name; 182 } 184 188 public ZipFile getZipFile() 189 { 190 try 191 { 192 return jar.getZipFile(); 193 } 194 catch(IOException io) 195 { 196 Log.log(Log.ERROR,this,io); 197 return null; 198 } 199 } 201 205 public static void dump() 206 { 207 Log.log(Log.DEBUG,JARClassLoader.class, 208 "Total instances created: " + INDEX); 209 Log.log(Log.DEBUG,JARClassLoader.class, 210 "Live instances: " + live); 211 synchronized(classHash) 212 { 213 Iterator entries = classHash.entrySet().iterator(); 214 while(entries.hasNext()) 215 { 216 Map.Entry entry = (Map.Entry)entries.next(); 217 if(entry.getValue() != NO_CLASS) 218 { 219 Log.log(Log.DEBUG,JARClassLoader.class, 220 entry.getKey() + " ==> " 221 + entry.getValue()); 222 } 223 } 224 } 225 } 227 public String toString() 229 { 230 if(jar == null) 231 return "<anonymous>(" + id + ")"; 232 else 233 return jar.getPath() + " (" + id + ")"; 234 } 236 protected Enumeration findResources(String name) throws IOException 238 { 239 class SingleElementEnumeration implements Enumeration 240 { 241 private Object element; 242 243 public SingleElementEnumeration(Object element) 244 { 245 this.element = element; 246 } 247 248 public boolean hasMoreElements() 249 { 250 return (element != null); 251 } 252 253 public Object nextElement() 254 { 255 if(element != null) 256 { 257 Object retval = element; 258 element = null; 259 return retval; 260 } 261 else 262 throw new NoSuchElementException(); 263 } 264 } 265 266 URL resource = getResource(name); 267 return new SingleElementEnumeration(resource); 268 } 270 protected void finalize() 272 { 273 live--; 274 } 276 278 282 JARClassLoader(PluginJAR jar) 283 { 284 this(); 285 this.jar = jar; 286 } 288 void activate() 290 { 291 if (jar.getPlugin() != null) 292 { 293 String _delegate = jEdit.getProperty( 294 "plugin." + jar.getPlugin().getClassName() + ".class_loader_delegate"); 295 delegateFirst = (_delegate == null || "true".equals(_delegate)); 296 } 297 298 String [] classes = jar.getClasses(); 299 if(classes != null) 300 { 301 for(int i = 0; i < classes.length; i++) 302 { 303 classHash.put(classes[i],this); 304 } 305 } 306 } 308 void deactivate() 310 { 311 String [] classes = jar.getClasses(); 312 if(classes == null) 313 return; 314 315 for(int i = 0; i < classes.length; i++) 316 { 317 Object loader = classHash.get(classes[i]); 318 if(loader == this) 319 classHash.remove(classes[i]); 320 else 321 ; 322 } 323 } 325 327 329 private static final Object NO_CLASS = new Object (); 331 332 private static int INDEX; 333 private static int live; 334 private static Hashtable classHash = new Hashtable(); 335 336 private int id; 337 private boolean delegateFirst; 338 private PluginJAR jar; 339 340 344 private synchronized Class _loadClass(String clazz, boolean resolveIt) 345 throws ClassNotFoundException 346 { 347 jar.activatePlugin(); 348 349 synchronized(this) 350 { 351 Class cls = findLoadedClass(clazz); 352 if(cls != null) 353 { 354 if(resolveIt) 355 resolveClass(cls); 356 return cls; 357 } 358 359 String name = MiscUtilities.classToFile(clazz); 360 361 try 362 { 363 definePackage(clazz); 364 ZipFile zipFile = jar.getZipFile(); 365 ZipEntry entry = zipFile.getEntry(name); 366 367 if(entry == null) 368 throw new ClassNotFoundException (clazz); 369 370 InputStream in = zipFile.getInputStream(entry); 371 372 int len = (int)entry.getSize(); 373 byte[] data = new byte[len]; 374 int success = 0; 375 int offset = 0; 376 while(success < len) 377 { 378 len -= success; 379 offset += success; 380 success = in.read(data,offset,len); 381 if(success == -1) 382 { 383 Log.log(Log.ERROR,this,"Failed to load class " 384 + clazz + " from " + zipFile.getName()); 385 throw new ClassNotFoundException (clazz); 386 } 387 } 388 389 cls = defineClass(clazz,data,0,data.length); 390 391 if(resolveIt) 392 resolveClass(cls); 393 394 return cls; 395 } 396 catch(IOException io) 397 { 398 Log.log(Log.ERROR,this,io); 399 400 throw new ClassNotFoundException (clazz); 401 } 402 } 403 } 405 private void definePackage(String clazz) throws IOException 407 { 408 int idx = clazz.lastIndexOf('.'); 409 if (idx != -1) { 410 String name = clazz.substring(0, idx); 411 if (getPackage(name) == null) definePackage(name, new JarFile (jar.getFile()).getManifest()); 412 } 413 } 415 private String getMfValue(Attributes sectionAttrs, Attributes mainAttrs, Attributes.Name name) 417 { 418 String value=null; 419 if (sectionAttrs != null) 420 value = sectionAttrs.getValue(name); 421 else if (mainAttrs != null) { 422 value = mainAttrs.getValue(name); 423 } 424 return value; 425 } 426 428 private void definePackage(String name, Manifest mf) 430 { 431 if (mf==null) 432 { 433 definePackage(name, null, null, null, null, null, 434 null, null); 435 return; 436 } 437 438 Attributes sa = mf.getAttributes(name.replace('.', '/') + "/"); 439 Attributes ma = mf.getMainAttributes(); 440 441 URL sealBase = null; 442 if (Boolean.valueOf(getMfValue(sa, ma, Name.SEALED)).booleanValue()) 443 { 444 try 445 { 446 sealBase = jar.getFile().toURL(); 447 } catch (MalformedURLException e) { } 448 } 449 450 Package pkg=definePackage( 451 name, 452 getMfValue(sa, ma, Name.SPECIFICATION_TITLE), 453 getMfValue(sa, ma, Name.SPECIFICATION_VERSION), 454 getMfValue(sa, ma, Name.SPECIFICATION_VENDOR), 455 getMfValue(sa, ma, Name.IMPLEMENTATION_TITLE), 456 getMfValue(sa, ma, Name.IMPLEMENTATION_VERSION), 457 getMfValue(sa, ma, Name.IMPLEMENTATION_VENDOR), 458 sealBase); 459 } 461 private Class loadFromParent(String clazz) 463 throws ClassNotFoundException 464 { 465 Class cls; 466 467 ClassLoader parentLoader = getClass().getClassLoader(); 468 if (parentLoader != null) 469 cls = parentLoader.loadClass(clazz); 470 else 471 cls = findSystemClass(clazz); 472 473 return cls; 474 } 476 } 478 | Popular Tags |