1 4 package org.python.core; 5 6 import java.util.Hashtable ; 7 import java.util.Vector ; 8 import java.util.Enumeration ; 9 import java.util.zip.ZipInputStream ; 10 import java.util.zip.ZipEntry ; 11 import java.io.*; 12 import java.net.URL ; 13 import java.net.URLConnection ; 14 import java.lang.reflect.Modifier ; 16 17 21 public abstract class CachedJarsPackageManager extends PackageManager { 22 23 26 protected void message(String msg) { 27 } 28 31 protected void warning(String warn) { 32 } 33 36 protected void comment(String msg) { 37 } 38 41 protected void debug(String msg) { 42 } 43 44 53 protected boolean filterByName(String name,boolean pkg) { 54 return name.indexOf('$') != -1; 55 } 56 57 67 protected boolean filterByAccess(String name,int acc) { 68 return (acc & Modifier.PUBLIC) != Modifier.PUBLIC; 69 } 70 71 private boolean indexModified; 72 private Hashtable jarfiles; 73 74 private static String vectorToString(Vector vec) { 75 int n = vec.size(); 76 StringBuffer ret = new StringBuffer (); 77 for(int i=0; i<n; i++) { 78 ret.append((String )vec.elementAt(i)); 79 if (i<n-1) ret.append(","); 80 } 81 return ret.toString(); 82 } 83 84 private void addZipEntry(Hashtable zipPackages, 87 ZipEntry entry, 88 ZipInputStream zip) throws IOException 89 { 90 String name = entry.getName(); 91 if (!name.endsWith(".class")) return; 93 94 char sep = '/'; 95 int breakPoint = name.lastIndexOf(sep); 96 if (breakPoint == -1) { 97 breakPoint = name.lastIndexOf('\\'); 98 sep = '\\'; 99 } 100 101 String packageName; 102 if (breakPoint == -1) { 103 packageName = ""; 104 } else { 105 packageName = name.substring(0,breakPoint).replace(sep, '.'); 106 } 107 108 String className = name.substring(breakPoint+1, name.length()-6); 109 110 if (filterByName(className,false)) return; 111 112 Vector [] vec = (Vector [])zipPackages.get(packageName); 113 if (vec == null) { 114 vec = new Vector [] { new Vector (), new Vector () }; 115 zipPackages.put(packageName, vec); 116 } 117 int access = checkAccess(zip); 118 if ((access != -1) && !filterByAccess(name,access)) { 119 vec[0].addElement(className); 120 } else { 121 vec[1].addElement(className); 122 } 123 } 124 125 private Hashtable getZipPackages(InputStream jarin) throws IOException { 127 Hashtable zipPackages = new Hashtable (); 128 129 ZipInputStream zip=new ZipInputStream (jarin); 130 131 ZipEntry entry; 132 while ((entry = zip.getNextEntry()) != null) { 133 addZipEntry(zipPackages, entry, zip); 134 zip.closeEntry(); 135 } 136 137 for (Enumeration e = zipPackages.keys() ; e.hasMoreElements() ;) { 139 Object key = e.nextElement(); 140 Vector [] vec = (Vector [])zipPackages.get(key); 141 String classes = vectorToString(vec[0]); 142 if (vec[1].size() > 0) { 143 classes += '@' + vectorToString(vec[1]); 144 } 145 zipPackages.put(key, classes); 146 } 147 148 return zipPackages; 149 } 150 151 157 public void addJarToPackages(java.net.URL jarurl) { 158 addJarToPackages(jarurl,null,false); 159 } 160 161 167 public void addJarToPackages(URL jarurl,boolean cache) { 168 addJarToPackages(jarurl,null,cache); 169 } 170 171 177 public void addJarToPackages(File jarfile) { 178 addJarToPackages(null,jarfile,false); 179 } 180 181 187 public void addJarToPackages(File jarfile,boolean cache) { 188 addJarToPackages(null,jarfile,cache); 189 } 190 191 private void addJarToPackages(URL jarurl,File jarfile,boolean cache) { 192 try { 193 boolean caching = jarfiles!=null; 194 195 URLConnection jarconn = null; 196 boolean localfile = true; 197 198 if (jarfile == null) { 199 jarconn = jarurl.openConnection(); 200 if(jarconn.getURL().getProtocol().equals("file")) { 205 String jarfilename = jarurl.getFile(); 208 jarfilename = jarfilename.replace('/',File.separatorChar); 209 jarfile = new File(jarfilename); 210 } 211 else localfile = false; 212 } 213 214 if (localfile && !jarfile.exists()) return; 215 216 Hashtable zipPackages = null; 217 218 long mtime = 0; 219 String jarcanon = null; 220 JarXEntry entry = null; 221 boolean brandNew = false; 222 223 if(caching) { 224 225 if(localfile) { 226 mtime = jarfile.lastModified(); 227 jarcanon = jarfile.getCanonicalPath(); 228 } else { 229 mtime = jarconn.getLastModified(); 230 jarcanon = jarurl.toString(); 231 } 232 233 entry = (JarXEntry)jarfiles.get(jarcanon); 234 235 if ((entry == null || !(new File(entry.cachefile).exists())) && cache) { 236 message("processing new jar, '"+ 237 jarcanon+"'"); 238 239 String jarname; 240 if(localfile) { 241 jarname = jarfile.getName(); 242 } else { 243 jarname = jarurl.getFile(); 244 int slash = jarname.lastIndexOf('/'); 245 if (slash != -1) 246 jarname=jarname.substring(slash+1); 247 } 248 jarname=jarname.substring(0,jarname.length()-4); 249 250 entry = new JarXEntry(jarname); 251 jarfiles.put(jarcanon, entry); 252 253 brandNew = true; 254 } 255 256 257 if (mtime != 0 && entry != null && entry.mtime == mtime) { 258 zipPackages = readCacheFile(entry, jarcanon); 259 } 260 261 } 262 263 if (zipPackages == null) { 264 caching = caching && cache; 265 266 if(caching) { 267 indexModified = true; 268 if (entry.mtime != 0) { 269 message("processing modified jar, '"+ 270 jarcanon+"'"); 271 } 272 entry.mtime = mtime; 273 } 274 275 InputStream jarin; 276 if (jarconn == null) 277 jarin = new BufferedInputStream( 278 new FileInputStream(jarfile)); 279 else 280 jarin = jarconn.getInputStream(); 281 282 zipPackages = getZipPackages(jarin); 283 284 if (caching) 285 writeCacheFile(entry, jarcanon, zipPackages, brandNew); 286 } 287 288 addPackages(zipPackages, jarcanon); 289 } catch (IOException ioe) { 290 warning("skipping bad jar, '" + 292 (jarfile != null ? 293 jarfile.toString() : 294 jarurl.toString()) + 295 "'"); 296 } 297 298 } 299 300 private void addPackages(Hashtable zipPackages, String jarfile) { 301 for (Enumeration e = zipPackages.keys() ; e.hasMoreElements() ;) { 302 String pkg = (String )e.nextElement(); 303 String classes = (String )zipPackages.get(pkg); 304 305 int idx = classes.indexOf('@'); 306 if (idx >= 0 && Options.respectJavaAccessibility) { 307 classes = classes.substring(0, idx); 308 } 309 310 makeJavaPackage(pkg, classes, jarfile); 311 } 312 } 313 314 private Hashtable readCacheFile(JarXEntry entry,String jarcanon) 317 { 318 String cachefile = entry.cachefile; 319 long mtime = entry.mtime; 320 321 debug("reading cache, '"+jarcanon+"'"); 322 323 try { 324 DataInputStream istream = inOpenCacheFile(cachefile); 325 String old_jarcanon = istream.readUTF(); 326 long old_mtime = istream.readLong(); 327 if ((!old_jarcanon.equals(jarcanon)) || 328 (old_mtime != mtime)) 329 { 330 comment("invalid cache file: "+ 331 cachefile+", "+jarcanon+":"+ 332 old_jarcanon+", "+mtime+":"+old_mtime); 333 deleteCacheFile(cachefile); 334 return null; 335 } 336 Hashtable packs = new Hashtable (); 337 try { 338 while (true) { 339 String packageName = istream.readUTF(); 340 String classes = istream.readUTF(); 341 packs.put(packageName, classes); 342 } 343 } catch (EOFException eof) { 344 ; 345 } 346 istream.close(); 347 348 return packs; 349 } catch (IOException ioe) { 350 return null; 352 } 353 } 354 355 private void writeCacheFile(JarXEntry entry,String jarcanon, 357 Hashtable zipPackages,boolean brandNew) 358 { 359 try { 360 DataOutputStream ostream = outCreateCacheFile(entry, brandNew); 361 ostream.writeUTF(jarcanon); 362 ostream.writeLong(entry.mtime); 363 comment("rewriting cachefile for '"+jarcanon+"'"); 364 365 for (Enumeration e = zipPackages.keys() ; e.hasMoreElements() ;) { 366 String packageName = (String )e.nextElement(); 367 String classes = (String )zipPackages.get(packageName); 368 ostream.writeUTF(packageName); 369 ostream.writeUTF(classes); 370 } 371 ostream.close(); 372 } catch (IOException ioe) { 373 warning("can't write cache file for '"+jarcanon+"'"); 374 } 375 } 376 377 380 protected void initCache() { 381 indexModified = false; 382 jarfiles = new Hashtable (); 383 384 try { 385 DataInputStream istream = inOpenIndex(); 386 if (istream == null) return; 387 388 try { 389 while (true) { 390 String jarcanon = istream.readUTF(); 391 String cachefile = istream.readUTF(); 392 long mtime = istream.readLong(); 393 jarfiles.put(jarcanon, new JarXEntry(cachefile,mtime)); 394 } 395 } catch (EOFException eof) { 396 ; 397 } 398 istream.close(); 399 } catch (IOException ioe) { 400 warning("invalid index file"); 401 } 402 403 } 404 405 408 public void saveCache() { 409 if(jarfiles == null || !indexModified ) return; 410 411 indexModified = false; 412 413 comment("writing modified index file"); 414 415 try { 416 DataOutputStream ostream = outOpenIndex(); 417 for (Enumeration e = jarfiles.keys(); e.hasMoreElements();) { 418 String jarcanon = (String )e.nextElement(); 419 JarXEntry entry = (JarXEntry)jarfiles.get(jarcanon); 420 ostream.writeUTF(jarcanon); 421 ostream.writeUTF(entry.cachefile); 422 ostream.writeLong(entry.mtime); 423 } 424 ostream.close(); 425 } catch (IOException ioe) { 426 warning("can't write index file"); 427 } 428 } 429 430 432 435 public static class JarXEntry extends Object { 436 437 public String cachefile; 438 439 public long mtime; 440 441 public JarXEntry(String cachefile) { 442 this.cachefile = cachefile; 443 } 444 445 public JarXEntry(String cachefile,long mtime) { 446 this.cachefile = cachefile; 447 this.mtime = mtime; 448 } 449 450 451 } 452 453 459 protected DataInputStream inOpenIndex() throws IOException { 460 File indexFile = new File(cachedir, "packages.idx"); 461 462 if (!indexFile.exists()) return null; 463 464 DataInputStream istream = new DataInputStream( 465 new BufferedInputStream(new FileInputStream(indexFile))); 466 467 return istream; 468 } 469 470 475 protected DataOutputStream outOpenIndex() throws IOException { 476 File indexFile = new File(cachedir, "packages.idx"); 477 478 return new DataOutputStream( 479 new BufferedOutputStream(new FileOutputStream(indexFile))); 480 } 481 482 487 protected DataInputStream inOpenCacheFile(String cachefile) 488 throws IOException 489 { 490 return new DataInputStream( 491 new BufferedInputStream( 492 new FileInputStream(cachefile))); 493 } 494 495 500 protected void deleteCacheFile(String cachefile) { 501 new File(cachefile).delete(); 502 } 503 504 515 protected DataOutputStream outCreateCacheFile(JarXEntry entry, 516 boolean create) 517 throws IOException 518 { 519 File cachefile = null; 520 521 if(create) { 522 int index = 1; 523 String suffix = ""; 524 String jarname = entry.cachefile; 525 while (true) { 526 cachefile = new File(cachedir, jarname+suffix+".pkc"); 527 if (!cachefile.exists()) break; 529 suffix = "$"+index; 530 index += 1; 531 } 532 entry.cachefile = cachefile.getCanonicalPath(); 533 } else cachefile = new File(entry.cachefile); 534 535 return new DataOutputStream( 536 new BufferedOutputStream( 537 new FileOutputStream(cachefile))); 538 } 539 540 542 private File cachedir; 543 544 549 protected boolean useCacheDir(File cachedir) { 550 if(cachedir == null) return false; 551 if (!cachedir.isDirectory() && cachedir.mkdirs() == false) { 552 warning("can't create package cache dir, '"+cachedir+"'"); 553 return false; 554 } 555 556 this.cachedir = cachedir; 557 558 return true; 559 } 560 561 } 562 | Popular Tags |