1 19 20 package jode.bytecode; 21 import java.io.ByteArrayInputStream ; 22 import java.io.File ; 23 import java.io.FileInputStream ; 24 import java.io.FileNotFoundException ; 25 import java.io.FilterInputStream ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.net.MalformedURLException ; 29 import java.net.URL ; 30 import java.net.URLConnection ; 31 import java.util.Enumeration ; 32 import java.util.Hashtable ; 33 import java.util.StringTokenizer ; 34 import java.util.Vector ; 35 import java.util.zip.ZipEntry ; 36 import java.util.zip.ZipFile ; 37 import java.util.zip.ZipInputStream ; 38 import jode.GlobalOptions; 39 40 46 public class SearchPath { 47 48 56 public static final char altPathSeparatorChar = ','; 57 URL [] bases; 58 byte[][] urlzips; 59 File [] dirs; 60 ZipFile [] zips; 61 String [] zipDirs; 62 Hashtable [] zipEntries; 63 64 private static void addEntry(Hashtable entries, String name) { 65 String dir = ""; 66 int pathsep = name.lastIndexOf("/"); 67 if (pathsep != -1) { 68 dir = name.substring(0, pathsep); 69 name = name.substring(pathsep+1); 70 } 71 72 Vector dirContent = (Vector ) entries.get(dir); 73 if (dirContent == null) { 74 dirContent = new Vector (); 75 entries.put(dir, dirContent); 76 if (dir != "") 77 addEntry(entries, dir); 78 } 79 dirContent.addElement(name); 80 } 81 82 private void fillZipEntries(int nr) { 83 Enumeration zipEnum = zips[nr].entries(); 84 zipEntries[nr] = new Hashtable (); 85 while (zipEnum.hasMoreElements()) { 86 ZipEntry ze = (ZipEntry ) zipEnum.nextElement(); 87 String name = ze.getName(); 88 if (zipDirs[nr] != null) { 91 if (!name.startsWith(zipDirs[nr])) 92 continue; 93 name = name.substring(zipDirs[nr].length()); 94 } 95 if (!ze.isDirectory() && name.endsWith(".class")) 96 addEntry(zipEntries[nr], name); 97 } 98 } 99 100 private void readURLZip(int nr, URLConnection conn) { 101 int length = conn.getContentLength(); 102 if (length <= 0) 103 length = 10240; 105 else 106 length++; 110 111 urlzips[nr] = new byte[length]; 112 try { 113 InputStream is = conn.getInputStream(); 114 int pos = 0; 115 for (;;) { 116 int avail = Math.max(is.available(), 1); 119 if (pos + is.available() > urlzips[nr].length) { 120 byte[] newarr = new byte 122 [Math.max(2*urlzips[nr].length, pos + is.available())]; 123 System.arraycopy(urlzips[nr], 0, newarr, 0, pos); 124 urlzips[nr] = newarr; 125 } 126 int count = is.read(urlzips[nr], pos, urlzips[nr].length-pos); 127 if (count == -1) 128 break; 129 pos += count; 130 } 131 if (pos < urlzips[nr].length) { 132 byte[] newarr = new byte[pos]; 134 System.arraycopy(urlzips[nr], 0, newarr, 0, pos); 135 urlzips[nr] = newarr; 136 } 137 } catch (IOException ex) { 138 GlobalOptions.err.println("IOException while reading " 139 +"remote zip file "+bases[nr]); 140 bases[nr] = null; 142 urlzips[nr] = null; 143 return; 144 } 145 try { 146 ZipInputStream zis = new ZipInputStream 148 (new ByteArrayInputStream (urlzips[nr])); 149 zipEntries[nr] = new Hashtable (); 150 ZipEntry ze; 151 while ((ze = zis.getNextEntry()) != null) { 152 String name = ze.getName(); 153 if (zipDirs[nr] != null) { 156 if (!name.startsWith(zipDirs[nr])) 157 continue; 158 name = name.substring(zipDirs[nr].length()); 159 } 160 if (!ze.isDirectory() && name.endsWith(".class")) 161 addEntry(zipEntries[nr], name); 162 zis.closeEntry(); 163 } 164 zis.close(); 165 } catch (IOException ex) { 166 GlobalOptions.err.println("Remote zip file "+bases[nr] 167 +" is corrupted."); 168 bases[nr] = null; 170 urlzips[nr] = null; 171 zipEntries[nr] = null; 172 return; 173 } 174 } 175 176 182 public SearchPath(String path) { 183 int length = 1; 186 for (int index=path.indexOf(File.pathSeparatorChar); 187 index != -1; length++) 188 index = path.indexOf(File.pathSeparatorChar, index+1); 189 if (File.pathSeparatorChar != altPathSeparatorChar) { 190 for (int index=path.indexOf(altPathSeparatorChar); 191 index != -1; length++) 192 index = path.indexOf(altPathSeparatorChar, index+1); 193 } 194 bases = new URL [length]; 195 urlzips = new byte[length][]; 196 dirs = new File [length]; 197 zips = new ZipFile [length]; 198 zipEntries = new Hashtable [length]; 199 zipDirs = new String [length]; 200 int i = 0; 201 for (int ptr=0; ptr < path.length(); ptr++, i++) { 202 int next = ptr; 203 while (next < path.length() 204 && path.charAt(next) != File.pathSeparatorChar 205 && path.charAt(next) != altPathSeparatorChar) 206 next++; 207 208 int index = ptr; 209 colon_separator: 210 while (next > ptr 211 && next < path.length() 212 && path.charAt(next) == ':') { 213 217 while (index < next) { 218 char c = path.charAt(index); 219 if ((c < 'A' || c > 'Z') 225 && (c < 'a' || c > 'z') 226 && (c < '0' || c > '9') 227 && "+-".indexOf(c) == -1) { 228 break colon_separator; 229 } 230 index++; 231 } 232 next++; 233 index++; 234 while (next < path.length() 235 && path.charAt(next) != File.pathSeparatorChar 236 && path.charAt(next) != altPathSeparatorChar) 237 next++; 238 } 239 String token = path.substring(ptr, next); 240 ptr = next; 241 242 boolean mustBeJar = false; 243 if (token.startsWith("jar:")) { 245 index = 0; 246 do { 247 index = token.indexOf('!', index); 248 } while (index != -1 && index != token.length()-1 249 && token.charAt(index+1) != '/'); 250 251 if (index == -1 || index == token.length()-1) { 252 GlobalOptions.err.println("Warning: Illegal jar url " 253 + token + "."); 254 continue; 255 } 256 zipDirs[i] = token.substring(index+2); 257 if (!zipDirs[i].endsWith("/")) 258 zipDirs[i] = zipDirs[i] + "/"; 259 token = token.substring(4, index); 260 mustBeJar = true; 261 } 262 index = token.indexOf(':'); 263 if (index != -1 && index < token.length()-2 264 && token.charAt(index+1) == '/' 265 && token.charAt(index+2) == '/') { 266 try { 268 bases[i] = new URL (token); 269 try { 270 URLConnection connection = bases[i].openConnection(); 271 if (mustBeJar 272 || token.endsWith(".zip") || token.endsWith(".jar") 273 || connection.getContentType().endsWith("/zip")) { 274 readURLZip(i, connection); 276 } 277 } catch (IOException ex) { 278 } catch (SecurityException ex) { 280 GlobalOptions.err.println 281 ("Warning: Security exception while accessing " 282 + bases[i] + "."); 283 } 284 } catch (MalformedURLException ex) { 285 286 bases[i] = null; 287 dirs[i] = null; 288 } 289 } else { 290 try { 291 dirs[i] = new File (token); 292 if (mustBeJar || !dirs[i].isDirectory()) { 293 try { 294 zips[i] = new ZipFile (dirs[i]); 295 } catch (java.io.IOException ex) { 296 297 dirs[i] = null; 298 } 299 } 300 } catch (SecurityException ex) { 301 302 GlobalOptions.err.println 303 ("Warning: SecurityException while accessing " 304 + token + "."); 305 dirs[i] = null; 306 } 307 } 308 } 309 } 310 311 public boolean exists(String filename) { 312 String localFileName = 313 (java.io.File.separatorChar != '/') 314 ? filename.replace('/', java.io.File.separatorChar) 315 : filename; 316 for (int i=0; i<dirs.length; i++) { 317 if (zipEntries[i] != null) { 318 if (zipEntries[i].get(filename) != null) 319 return true; 320 321 String dir = ""; 322 String name = filename; 323 int index = filename.lastIndexOf('/'); 324 if (index >= 0) { 325 dir = filename.substring(0, index); 326 name = filename.substring(index+1); 327 } 328 Vector directory = (Vector )zipEntries[i].get(dir); 329 if (directory != null && directory.contains(name)) 330 return true; 331 continue; 332 } 333 if (bases[i] != null) { 334 try { 335 URL url = new URL (bases[i], filename); 336 URLConnection conn = url.openConnection(); 337 conn.connect(); 338 conn.getInputStream().close(); 339 return true; 340 } catch (IOException ex) { 341 342 } 343 continue; 344 } 345 if (dirs[i] == null) 346 continue; 347 if (zips[i] != null) { 348 String fullname = zipDirs[i] != null 349 ? zipDirs[i] + filename : filename; 350 ZipEntry ze = zips[i].getEntry(fullname); 351 if (ze != null) 352 return true; 353 } else { 354 try { 355 File f = new File (dirs[i], localFileName); 356 if (f.exists()) 357 return true; 358 } catch (SecurityException ex) { 359 360 } 361 } 362 } 363 return false; 364 } 365 366 372 public InputStream getFile(String filename) throws IOException { 373 String localFileName = 374 (java.io.File.separatorChar != '/') 375 ? filename.replace('/', java.io.File.separatorChar) 376 : filename; 377 for (int i=0; i<dirs.length; i++) { 378 if (urlzips[i] != null) { 379 ZipInputStream zis = new ZipInputStream 380 (new ByteArrayInputStream (urlzips[i])); 381 ZipEntry ze; 382 String fullname = zipDirs[i] != null 383 ? zipDirs[i] + filename : filename; 384 while ((ze = zis.getNextEntry()) != null) { 385 if (ze.getName().equals(fullname)) { 386 return zis; 407 } 409 zis.closeEntry(); 410 } 411 continue; 412 } 413 if (bases[i] != null) { 414 try { 415 URL url = new URL (bases[i], filename); 416 URLConnection conn = url.openConnection(); 417 conn.setAllowUserInteraction(true); 418 return conn.getInputStream(); 419 } catch (SecurityException ex) { 420 GlobalOptions.err.println("Warning: SecurityException" 421 + " while accessing " 422 + bases[i] + filename); 423 ex.printStackTrace(GlobalOptions.err); 424 425 } catch (FileNotFoundException ex) { 426 427 } 428 continue; 429 } 430 if (dirs[i] == null) 431 continue; 432 if (zips[i] != null) { 433 String fullname = zipDirs[i] != null 434 ? zipDirs[i] + filename : filename; 435 ZipEntry ze = zips[i].getEntry(fullname); 436 if (ze != null) 437 return zips[i].getInputStream(ze); 438 } else { 439 try { 440 File f = new File (dirs[i], localFileName); 441 if (f.exists()) 442 return new FileInputStream (f); 443 } catch (SecurityException ex) { 444 GlobalOptions.err.println("Warning: SecurityException" 445 + " while accessing " 446 + dirs[i] + localFileName); 447 448 } 449 } 450 } 451 throw new FileNotFoundException (filename); 452 } 453 454 461 public boolean isDirectory(String filename) { 462 String localFileName = 463 (java.io.File.separatorChar != '/') 464 ? filename.replace('/', java.io.File.separatorChar) 465 : filename; 466 for (int i=0; i<dirs.length; i++) { 467 if (dirs[i] == null) 468 continue; 469 if (zips[i] != null && zipEntries[i] == null) 470 fillZipEntries(i); 471 472 if (zipEntries[i] != null) { 473 if (zipEntries[i].containsKey(filename)) 474 return true; 475 } else { 476 try { 477 File f = new File (dirs[i], localFileName); 478 if (f.exists()) 479 return f.isDirectory(); 480 } catch (SecurityException ex) { 481 GlobalOptions.err.println("Warning: SecurityException" 482 + " while accessing " 483 + dirs[i] + localFileName); 484 } 485 } 486 } 487 return false; 488 } 489 490 496 public Enumeration listFiles(final String dirName) { 497 return new Enumeration () { 498 int pathNr; 499 Enumeration zipEnum; 500 int fileNr; 501 String localDirName = 502 (java.io.File.separatorChar != '/') 503 ? dirName.replace('/', java.io.File.separatorChar) 504 : dirName; 505 File currentDir; 506 String [] files; 507 508 public String findNextFile() { 509 while (true) { 510 if (zipEnum != null) { 511 while (zipEnum.hasMoreElements()) { 512 return (String ) zipEnum.nextElement(); 513 } 514 zipEnum = null; 515 } 516 if (files != null) { 517 while (fileNr < files.length) { 518 String name = files[fileNr++]; 519 if (name.endsWith(".class")) { 520 return name; 521 } else if (name.indexOf(".") == -1) { 522 525 File f = new File (currentDir, name); 526 if (f.exists() && f.isDirectory()) 527 return name; 528 } 529 } 530 files = null; 531 } 532 if (pathNr == dirs.length) 533 return null; 534 535 if (zips[pathNr] != null && zipEntries[pathNr] == null) 536 fillZipEntries(pathNr); 537 538 if (zipEntries[pathNr] != null) { 539 Vector entries = 540 (Vector ) zipEntries[pathNr].get(dirName); 541 if (entries != null) 542 zipEnum = entries.elements(); 543 } else if (dirs[pathNr] != null) { 544 try { 545 File f = new File (dirs[pathNr], localDirName); 546 if (f.exists() && f.isDirectory()) { 547 currentDir = f; 548 files = f.list(); 549 fileNr = 0; 550 } 551 } catch (SecurityException ex) { 552 GlobalOptions.err.println 553 ("Warning: SecurityException" 554 + " while accessing " 555 + dirs[pathNr] + localDirName); 556 557 } 558 } 559 pathNr++; 560 } 561 } 562 563 String nextName; 564 565 public boolean hasMoreElements() { 566 return (nextName != null 567 || (nextName = findNextFile()) != null); 568 } 569 570 public Object nextElement() { 571 if (nextName == null) 572 return findNextFile(); 573 else { 574 String result = nextName; 575 nextName = null; 576 return result; 577 } 578 } 579 }; 580 } 581 } 582 | Popular Tags |