Changeset 15395
- Timestamp:
- 10/10/20 21:43:28 (3 years ago)
- Location:
- trunk/abcl
- Files:
-
- 1 added
- 1 deleted
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/abcl/src/org/armedbear/lisp/Autoload.java
r14997 r15395 150 150 thread.resetSpecialBindings(mark); 151 151 } 152 if (debug) { 153 if (symbol != null) { 154 if (symbol.getSymbolFunction() instanceof Autoload) { 155 Debug.trace("Unable to autoload " + symbol.princToString()); 156 throw new IntegrityError(); 157 } 158 } 159 } 152 // if (debug) { 153 if (symbol != null) { 154 if (symbol.getSymbolFunction() instanceof Autoload) { 155 simple_error("Unable to autoload " + symbol.princToString(), symbol, fileName, className); 156 } 157 } // end if (debug) 160 158 } 161 159 -
trunk/abcl/src/org/armedbear/lisp/FaslClassLoader.java
r15393 r15395 111 111 112 112 if (truenameFasl instanceof Pathname) { 113 return Pathname.mergePathnames(name, (Pathname)truenameFasl, Keyword.NEWEST)113 return ((Pathname)Pathname.mergePathnames(name, (Pathname)truenameFasl, Keyword.NEWEST)) 114 114 .getInputStream(); 115 115 } else if (truename instanceof Pathname) { 116 return Pathname.mergePathnames(name, (Pathname) truename, Keyword.NEWEST)116 return ((Pathname)Pathname.mergePathnames(name, (Pathname) truename, Keyword.NEWEST)) 117 117 .getInputStream(); 118 } else if (! Pathname.truename(name).equals(NIL)) {119 118 } else if (!Symbol.PROBE_FILE.execute(name).equals(NIL)) { 119 return name.getInputStream(); 120 120 } 121 121 -
trunk/abcl/src/org/armedbear/lisp/Interpreter.java
r15393 r15395 331 331 if (i + 1 < args.length) { 332 332 if (arg.equals("--load")) 333 Load.load( Pathname.mergePathnames((Pathname)Pathname.create(args[i + 1]),333 Load.load((Pathname)Pathname.mergePathnames((Pathname)Pathname.create(args[i + 1]), 334 334 checkPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.getSymbolValue())), 335 335 false, false, true); -
trunk/abcl/src/org/armedbear/lisp/Lisp.java
r15394 r15395 1373 1373 LispObject truename = Symbol.LOAD_TRUENAME.symbolValue(thread); 1374 1374 if (truenameFasl instanceof Pathname) { 1375 load = Pathname.mergePathnames(name, (Pathname)truenameFasl, Keyword.NEWEST);1375 load = (Pathname)Pathname.mergePathnames(name, (Pathname)truenameFasl, Keyword.NEWEST); 1376 1376 } else if (truename instanceof Pathname) { 1377 load = Pathname.mergePathnames(name, (Pathname) truename, Keyword.NEWEST);1377 load = (Pathname)Pathname.mergePathnames(name, (Pathname) truename, Keyword.NEWEST); 1378 1378 } else { 1379 if (!Pathname.truename(name).equals(NIL)) {1380 1381 1382 1383 1379 if (!Symbol.PROBE_FILE.execute(name).equals(NIL)) { 1380 load = name; 1381 } else { 1382 load = null; 1383 } 1384 1384 } 1385 1385 InputStream input = null; … … 1914 1914 return (Pathname) arg; 1915 1915 if (arg instanceof AbstractString) 1916 return (Pathname)Pathname. parseNamestring((AbstractString)arg);1916 return (Pathname)Pathname.create(((AbstractString)arg).toString()); 1917 1917 if (arg instanceof FileStream) 1918 1918 return ((FileStream)arg).getPathname(); … … 1921 1921 if (arg instanceof URLStream) 1922 1922 return ((URLStream)arg).getPathname(); 1923 type_error(arg, list(Symbol.OR, Symbol.PATHNAME, 1924 Symbol.STRING, Symbol.FILE_STREAM, 1925 Symbol.JAR_STREAM, Symbol.URL_STREAM)); 1923 type_error(arg, list(Symbol.OR, 1924 Symbol.STRING, 1925 Symbol.PATHNAME, Symbol.JAR_PATHNAME, Symbol.URL_PATHNAME, 1926 Symbol.FILE_STREAM, Symbol.JAR_STREAM, Symbol.URL_STREAM)); 1926 1927 // Not reached. 1927 1928 return null; -
trunk/abcl/src/org/armedbear/lisp/Load.java
r15393 r15395 67 67 * none can be determined. */ 68 68 private static final Pathname findLoadableFile(Pathname name) { 69 LispObject truename = Pathname.truename(name, false); 70 if (truename instanceof Pathname) { 71 Pathname t = (Pathname)truename; 72 if (t.getName() != NIL 73 && t.getName() != null) { 74 return t; 75 } 76 } 77 final String COMPILE_FILE_TYPE = Lisp._COMPILE_FILE_TYPE_.symbolValue().getStringValue(); 78 if (name.getType() == NIL 79 && (name.getName() != NIL || name.getName() != null)) { 80 Pathname lispPathname = Pathname.create(name); 81 lispPathname.setType(new SimpleString("lisp")); 82 lispPathname.invalidateNamestring(); 83 LispObject lisp = Pathname.truename(lispPathname, false); 84 Pathname abclPathname = Pathname.create(name); 85 abclPathname.setType(new SimpleString(COMPILE_FILE_TYPE)); 86 abclPathname.invalidateNamestring(); 87 LispObject abcl = Pathname.truename(abclPathname, false); 88 if (lisp instanceof Pathname && abcl instanceof Pathname) { 89 lispPathname = (Pathname)lisp; 90 abclPathname = (Pathname)abcl; 91 long lispLastModified = lispPathname.getLastModified(); 92 long abclLastModified = abclPathname.getLastModified(); 93 if (abclLastModified > lispLastModified) { 94 return abclPathname; // fasl file is newer 95 } else { 96 return lispPathname; 97 } 98 } else if (abcl instanceof Pathname) { 99 return (Pathname) abcl; 100 } else if (lisp instanceof Pathname) { 101 return (Pathname) lisp; 102 } 103 } 104 if (name.isJar()) { 105 if (name.getType().equals(NIL)) { 106 name.setType(COMPILE_FILE_INIT_FASL_TYPE); 107 name.invalidateNamestring(); 108 Pathname result = findLoadableFile(name); 109 if (result != null) { 110 return result; 111 } 112 name.setType(new SimpleString(COMPILE_FILE_TYPE)); 113 name.invalidateNamestring(); 114 result = findLoadableFile(name); 115 if (result != null) { 116 return result; 117 } 118 } 119 } 120 return null; 69 LispObject truename = Symbol.PROBE_FILE.execute(name); 70 if (truename instanceof Pathname) { 71 Pathname t = (Pathname)truename; 72 if (t.getName() != NIL 73 && t.getName() != null) { 74 return t; 75 } 76 } 77 final String COMPILE_FILE_TYPE = Lisp._COMPILE_FILE_TYPE_.symbolValue().getStringValue(); 78 if (name.getType() == NIL 79 && (name.getName() != NIL || name.getName() != null)) { 80 Pathname lispPathname = Pathname.create(name); 81 lispPathname.setType(new SimpleString("lisp")); 82 LispObject lisp = Symbol.PROBE_FILE.execute(lispPathname); 83 Pathname abclPathname = Pathname.create(name); 84 abclPathname.setType(new SimpleString(COMPILE_FILE_TYPE)); 85 LispObject abcl = Symbol.PROBE_FILE.execute(abclPathname); 86 if (lisp instanceof Pathname && abcl instanceof Pathname) { 87 lispPathname = (Pathname)lisp; 88 abclPathname = (Pathname)abcl; 89 long lispLastModified = lispPathname.getLastModified(); 90 long abclLastModified = abclPathname.getLastModified(); 91 if (abclLastModified > lispLastModified) { 92 return abclPathname; // fasl file is newer 93 } else { 94 return lispPathname; 95 } 96 } else if (abcl instanceof Pathname) { 97 return (Pathname) abcl; 98 } else if (lisp instanceof Pathname) { 99 return (Pathname) lisp; 100 } 101 } 102 if (name.isJar()) { 103 if (name.getType().equals(NIL)) { 104 name.setType(COMPILE_FILE_INIT_FASL_TYPE); 105 Pathname result = findLoadableFile(name); 106 if (result != null) { 107 return result; 108 } 109 name.setType(new SimpleString(COMPILE_FILE_TYPE)); 110 name.invalidateNamestring(); 111 result = findLoadableFile(name); 112 if (result != null) { 113 return result; 114 } 115 } 116 } 117 return null; 121 118 } 122 119 … … 158 155 Pathname pathnameDefaults 159 156 = coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()); 160 mergedPathname = Pathname.mergePathnames(pathname, pathnameDefaults);157 mergedPathname = (Pathname)Pathname.mergePathnames(pathname, pathnameDefaults); 161 158 } 162 159 Pathname loadableFile = findLoadableFile(mergedPathname != null ? mergedPathname : pathname); 163 Pathname truename = coercePathnameOrNull(Pathname.truename(loadableFile)); 164 165 if (truename == null || truename.equals(NIL)) { 166 if (ifDoesNotExist) { 167 return error(new FileError("File not found: " + pathname.princToString(), pathname)); 168 } else { 169 Debug.warn("Failed to load " + pathname.getNamestring()); 170 return NIL; 171 } 172 } 173 174 if (Utilities.checkZipFile(truename)) { 175 String n = truename.getNamestring(); 176 String name = Pathname.uriEncode(truename.getName().getStringValue()); 177 if (n.startsWith("jar:")) { 178 n = "jar:" + n + "!/" + name + "." 179 + COMPILE_FILE_INIT_FASL_TYPE; 180 } else if (n.startsWith("zip:")) { 181 n = "zip:" + n + "!/" + name + "." 182 + COMPILE_FILE_INIT_FASL_TYPE; 183 } else { 184 n = "jar:file:" + Pathname.uriEncode(n) + "!/" + name + "." 185 + COMPILE_FILE_INIT_FASL_TYPE; 186 } 187 if (!((mergedPathname = (Pathname)Pathname.create(n)) instanceof Pathname)) { 188 return error(new FileError((MessageFormat.format("Failed to address JAR-PATHNAME truename {0} for name {1}", truename.princToString(), name)), truename)); 189 } 190 191 LispObject initTruename = coercePathnameOrNull(Pathname.truename(mergedPathname)); 192 if (initTruename == null || initTruename.equals(NIL)) { 160 Pathname truename = (Pathname)Symbol.PROBE_FILE.execute(loadableFile); 161 162 if (truename.equals(NIL)) { 163 if (ifDoesNotExist) { 164 return error(new FileError("File not found: " + pathname.princToString(), pathname)); 165 } else { 166 Debug.warn("Failed to load " + pathname.getNamestring()); 167 return NIL; 168 } 169 } 170 171 if (ZipCache.checkZipFile(truename)) { 172 // String n = truename.getNamestring(); 173 // String name = Pathname.uriEncode(truename.getName().getStringValue()); 174 // if (n.startsWith("jar:")) { 175 // n = "jar:" + n + "!/" + name + "." 176 // + COMPILE_FILE_INIT_FASL_TYPE; 177 // } else if (n.startsWith("zip:")) { 178 // n = "zip:" + n + "!/" + name + "." 179 // + COMPILE_FILE_INIT_FASL_TYPE; 180 // } else { 181 // n = "jar:file:" + Pathname.uriEncode(n) + "!/" + name + "." 182 // + COMPILE_FILE_INIT_FASL_TYPE; 183 // } 184 // if (!((mergedPathname = (Pathname)Pathname.create(n)) instanceof Pathname)) { 185 // return error(new FileError((MessageFormat.format("Failed to address JAR-PATHNAME truename {0} for name {1}", truename.princToString(), name)), truename)); 186 // } 187 truename = (Pathname) PathnameJar.createFromPathname(truename); 188 Pathname loader = (Pathname)Pathname.create("__loader__._"); // FIXME use constants 189 mergedPathname = (Pathname)Symbol.MERGE_PATHNAMES.execute(loader, truename); 190 191 LispObject initTruename = Symbol.PROBE_FILE.execute(mergedPathname); 192 if (initTruename.equals(NIL)) { 193 193 // Maybe the enclosing JAR has been renamed? 194 194 Pathname p = Pathname.create(mergedPathname); 195 195 p.setName(Keyword.WILD); 196 p.invalidateNamestring(); 197 LispObject result = Pathname.MATCH_WILD_JAR_PATHNAME.execute(p); 198 199 if (result instanceof Cons 196 LispObject result = Symbol.MATCH_WILD_JAR_PATHNAME.execute(p); 197 198 if (result instanceof Cons 200 199 && ((Cons)result).length() == 1 201 200 && ((Cons)result).car() instanceof Pathname) { … … 298 297 Pathname mergedPathname; 299 298 if (bootPath instanceof Pathname) { 300 mergedPathname = Pathname.mergePathnames(pathname, (Pathname)bootPath);299 mergedPathname = (Pathname)Symbol.MERGE_PATHNAMES.execute(pathname, bootPath); 301 300 } else { 302 301 mergedPathname = pathname; 303 302 } 304 303 URL url = null; 305 304 Pathname loadableFile = findLoadableFile(mergedPathname); 306 truename = coercePathnameOrNull(Pathname.truename(loadableFile));305 truename = (Pathname)Symbol.PROBE_FILE.execute(loadableFile); 307 306 308 307 final String COMPILE_FILE_TYPE … … 326 325 if (!bootPath.equals(NIL)) { 327 326 Pathname urlPathname = (Pathname)Pathname.create(url); 328 329 truename = (Pathname)Pathname.truename(loadableFile);330 if (truename == null) {331 332 333 327 loadableFile = findLoadableFile(urlPathname); 328 truename = (Pathname)Symbol.PROBE_FILE.execute(loadableFile); 329 if (truename.equals(NIL)) { 330 return error(new LispError("Failed to find loadable system file in boot classpath " 331 + "'" + url + "'")); 332 } 334 333 } else { 335 334 truename = null; // We can't represent the FASL in a Pathname (q.v. OSGi) … … 339 338 // Look for a init FASL inside a packed FASL 340 339 if (truename != null 341 && truename.getType().princToString().equals(COMPILE_FILE_TYPE) && Utilities.checkZipFile(truename)) {340 && truename.getType().princToString().equals(COMPILE_FILE_TYPE) && ZipCache.checkZipFile(truename)) { 342 341 Pathname init = (Pathname)Pathname.create(truename.getNamestring()); 343 342 init.setType(COMPILE_FILE_INIT_FASL_TYPE); 344 343 init.setName(new SimpleString("__loader__")); 345 LispObject t = Pathname.truename(init);344 LispObject t = Symbol.PROBE_FILE.execute(init); 346 345 if (t instanceof Pathname) { 347 346 truename = (Pathname)t; -
trunk/abcl/src/org/armedbear/lisp/Pathname.java
r15394 r15395 78 78 } 79 79 } 80 Pathname result = new Pathname();81 result.init(s); 80 Pathname result = Pathname.init(s); 81 82 82 return result; 83 83 } … … 88 88 89 89 public static LispObject create(URL url) { 90 return new Pathname(url);90 return Pathname.create(url.toString()); 91 91 } 92 92 93 93 public static LispObject create(URI uri) { 94 return new Pathname(uri);94 return Pathname.create(uri.toString()); 95 95 } 96 96 protected LispObject host = NIL; … … 98 98 return host; 99 99 } 100 public LispObjectsetHost(LispObject host) {100 public Pathname setHost(LispObject host) { 101 101 this.host = host; 102 102 return this; … … 107 107 return device; 108 108 } 109 public LispObjectsetDevice(LispObject device) {109 public Pathname setDevice(LispObject device) { 110 110 this.device = device; 111 111 return this; … … 116 116 return directory; 117 117 } 118 public LispObjectsetDirectory(LispObject directory) {118 public Pathname setDirectory(LispObject directory) { 119 119 this.directory = directory; 120 120 return this; … … 125 125 return name; 126 126 } 127 public LispObjectsetName(LispObject name) {127 public Pathname setName(LispObject name) { 128 128 this.name = name; 129 129 return this; … … 135 135 return type; 136 136 } 137 public LispObjectsetType(LispObject type) {137 public Pathname setType(LispObject type) { 138 138 this.type = type; 139 139 return this; … … 146 146 } 147 147 148 public LispObjectsetVersion(LispObject version) {148 public Pathname setVersion(LispObject version) { 149 149 this.version = version; 150 150 return this; … … 217 217 if (p.host != NIL) { 218 218 if (p.host instanceof SimpleString) { 219 host = new SimpleString(((SimpleString)p.getHost()).getStringValue());219 setHost(new SimpleString(((SimpleString)p.getHost()).getStringValue())); 220 220 } else if (p.host instanceof Symbol) { 221 host = p.host;221 setHost(p.host); 222 222 } else if (p.host instanceof Cons) { 223 223 host = new Cons((Cons)p.getHost()); 224 224 } else { 225 Debug.assertTrue(false);225 simple_error("Failed to copy host in pathname ~a", p); 226 226 } 227 227 } … … 229 229 if (p.device instanceof SimpleString) { 230 230 device = new SimpleString(((SimpleString)p.getDevice()).getStringValue()); 231 } else if (p.device instanceof Cons) { 232 Cons jars = (Cons)p.device; 233 device = new Cons(NIL, NIL); 234 LispObject first = jars.car(); 235 if (first instanceof Pathname) { 236 ((Cons)device).car = Pathname.create((Pathname)first); 237 } else { 238 Debug.assertTrue(false); 239 } 240 if (!jars.cdr().equals(NIL)) { 241 if (jars.cdr() instanceof Cons) { 242 ((Cons)device).cdr = new Cons(Pathname.create((Pathname)jars.cdr().car()), NIL); 243 } else { 244 Debug.assertTrue(false); 245 } 246 } 247 } else if (p.device instanceof Symbol) { 231 } else if (p.getDevice() instanceof Cons) { 232 LispObject jars = p.getDevice(); 233 jars = jars.nreverse(); 234 device = NIL; 235 while (jars.car() != NIL) { 236 Pathname jar = (Pathname) Pathname.create(((Pathname)jars.car()).getNamestring()); 237 device = device.push(jar); 238 jars = jars.cdr(); 239 } 240 } else if (p.device instanceof Symbol) { // When is this the case? 248 241 device = p.device; 249 242 } else { 250 Debug.assertTrue(false);243 simple_error("Failed to copy device in pathname ~a", p); 251 244 } 252 245 } … … 266 259 directory.nreverse(); 267 260 } else { 268 Debug.assertTrue(false);261 simple_error("Failed to copy directory in pathname ~a", p); 269 262 } 270 263 } … … 275 268 name = p.name; 276 269 } else { 277 Debug.assertTrue(false);270 simple_error("Failed to copy name in pathname ~a", p); 278 271 } 279 272 } … … 284 277 type = p.type; 285 278 } else { 286 Debug.assertTrue(false);279 simple_error("Failed to copy type in pathname ~a", p); 287 280 } 288 281 } … … 293 286 version = p.version; 294 287 } else { 295 Debug.assertTrue(false); 296 } 297 } 298 } 299 300 private Pathname(String s) { 301 init(s); 302 } 288 simple_error("Failed to copy version in pathname ~a", p); 289 } 290 } 291 } 303 292 304 293 public static boolean isSupportedProtocol(String protocol) { … … 321 310 } 322 311 323 private Pathname(URL url) {324 // URL handling is now buried in init(String), as the URI325 // escaping mechanism didn't interact well with '+' and other326 // characters.327 init(url.toString());328 }329 330 private Pathname(URI uri) {331 init(uri.toString());332 }333 334 312 static final Symbol SCHEME = internKeyword("SCHEME"); 335 313 static final Symbol AUTHORITY = internKeyword("AUTHORITY"); … … 338 316 339 317 static final private String jarSeparator = "!/"; 340 private final void init(String s) { 318 319 private static final Pathname init(String s) { 320 Pathname result = new Pathname(); 341 321 if (s == null) { 342 return;322 return (Pathname)simple_error("Refusing to create a PATHNAME for the null reference."); 343 323 } 344 324 if (s.equals(".") || s.equals("./") 345 325 || (Utilities.isPlatformWindows && s.equals(".\\"))) { 346 setDirectory(new Cons(Keyword.RELATIVE));347 return ;348 } 326 result.setDirectory(new Cons(Keyword.RELATIVE)); 327 return result; 328 } 349 329 if (s.equals("..") || s.equals("../")) { 350 setDirectory(list(Keyword.RELATIVE, Keyword.UP)); 351 return; 352 } 330 result.setDirectory(list(Keyword.RELATIVE, Keyword.UP)); 331 return result; 332 } 333 // UNC Windows shares 353 334 if (Utilities.isPlatformWindows) { 354 335 if (s.startsWith("\\\\") || s.startsWith("//")) { … … 366 347 } 367 348 if (shareIndex == -1 || dirIndex == -1) { 368 error(new LispError("Unsupported UNC path format: \"" + s + '"')); 369 } 370 371 setHost(new SimpleString(s.substring(2, shareIndex))); 372 setDevice(new SimpleString(s.substring(shareIndex + 1, dirIndex))); 349 return Pathname_simple_error("Unsupported UNC path format: \"" + s + '"'); 350 } 351 352 result 353 .setHost(new SimpleString(s.substring(2, shareIndex))) 354 .setDevice(new SimpleString(s.substring(shareIndex + 1, dirIndex))); 373 355 374 356 Pathname p = (Pathname)Pathname.create(s.substring(dirIndex)); 375 setDirectory(p.getDirectory());376 setName(p.getName());377 setType(p.getType());378 setVersion(p.getVersion());379 invalidateNamestring();380 return ;357 result 358 .setDirectory(p.getDirectory()) 359 .setName(p.getName()) 360 .setType(p.getType()) 361 .setVersion(p.getVersion()); 362 return result; 381 363 } 382 364 } … … 384 366 // A JAR file 385 367 if (s.startsWith("jar:") && s.endsWith(jarSeparator)) { 386 LispObject jars = NIL; 387 int i = s.lastIndexOf(jarSeparator, s.length() - jarSeparator.length() - 1); 388 String jar = null; 389 if (i == -1) { 390 jar = s; 391 } else { 392 // There can be no more than two jar references and the 393 // inner one must be a file reference within the outer. 394 jar = "jar:file:" + s.substring(i + jarSeparator.length()); 395 s = s.substring("jar:".length(), i + jarSeparator.length()); 396 Pathname p = (Pathname)Pathname.create(s); 397 jars = jars.push(p.getDevice().car()); 398 } 399 if (jar.startsWith("jar:file:")) { 400 String file 401 = jar.substring("jar:file:".length(), 402 jar.length() - jarSeparator.length()); 403 Pathname jarPathname; 404 if (file.length() > 0) { 405 URL url = null; 406 URI uri = null; 407 try { 408 url = new URL("file:" + file); 409 uri = url.toURI(); 410 } catch (MalformedURLException e1) { 411 error(new SimpleError("Failed to create URI from " 412 + "'" + file + "'" 413 + ": " + e1.getMessage())); 414 } catch (URISyntaxException e2) { 415 error(new SimpleError("Failed to create URI from " 416 + "'" + file + "'" 417 + ": " + e2.getMessage())); 418 } 419 String path = uri.getPath(); 420 if (path == null) { 421 // We allow "jar:file:baz.jar!/" to construct a relative 422 // path for jar files, so MERGE-PATHNAMES means something. 423 jarPathname = (Pathname)Pathname.create(uri.getSchemeSpecificPart()); 424 } else { 425 jarPathname = (Pathname)Pathname.create((new File(path)).getPath()); 426 } 427 } else { 428 jarPathname = (Pathname)Pathname.create(""); 429 } 430 jars = jars.push(jarPathname); 431 } else { 432 URL url = null; 433 try { 434 url = new URL(jar.substring("jar:".length(), jar.length() - 2)); 435 Pathname p = (Pathname)Pathname.create(url); 436 jars = jars.push(p); 437 } catch (MalformedURLException e) { 438 error(new LispError("Failed to parse URL " 439 + "'" + url + "'" 440 + e.getMessage())); 441 } 442 } 443 jars = jars.nreverse(); 444 setDevice(jars); 445 invalidateNamestring(); 446 return; 368 return (PathnameJar)PathnameJar.create(s); 447 369 } 448 370 … … 450 372 final int separatorIndex = s.lastIndexOf(jarSeparator); 451 373 if (separatorIndex > 0 && s.startsWith("jar:")) { 452 final String jarURL = s.substring(0, separatorIndex + jarSeparator.length()); 453 URL url = null; 454 try { 455 url = new URL(jarURL); 456 } catch (MalformedURLException ex) { 457 error(new LispError("Failed to parse URL " 458 + "'" + jarURL + "'" 459 + ex.getMessage())); 460 } 461 Pathname d = (Pathname)Pathname.create(url); 462 if (getDevice() instanceof Cons) { 463 LispObject[] jars = d.copyToArray(); 464 // XXX Is this ever reached? If so, need to append lists 465 Debug.assertTrue(false); 466 } else { 467 setDevice(d.getDevice()); 468 } 469 s = "/" + s.substring(separatorIndex + jarSeparator.length()); 470 Pathname p = (Pathname)Pathname.create("file:" + s); // Use URI escaping rules 471 setDirectory(p.getDirectory()); 472 setName(p.getName()); 473 setType(p.getType()); 474 setVersion(p.getVersion()); 475 return; 476 } 477 478 // A URL 374 return (PathnameJar)PathnameJar.create(s); 375 } 376 377 // A URL (anything with a scheme that is not a logical 378 // pathname, and not a JAR file or an entry in a JAR file) 479 379 if (isValidURL(s)) { 480 URL url = null; 481 try { 482 url = new URL(s); 483 } catch (MalformedURLException e) { 484 Debug.assertTrue(false); 485 } 486 String scheme = url.getProtocol(); 487 if (scheme.equals("file")) { 488 URI uri = null; 489 try { 490 uri = new URI(s); 491 } catch (URISyntaxException ex) { 492 error(new SimpleError("Improper URI syntax for " 493 + "'" + url.toString() + "'" 494 + ": " + ex.toString())); 495 } 496 497 String uriPath = uri.getPath(); 498 if (null == uriPath) { 499 // Under Windows, deal with pathnames containing 500 // devices expressed as "file:z:/foo/path" 501 uriPath = uri.getSchemeSpecificPart(); 502 if (uriPath == null || uriPath.equals("")) { 503 error(new LispError("The URI has no path: " + uri)); 504 } 505 } 506 final File file = new File(uriPath); 507 String path = file.getPath(); 508 if (uri.toString().endsWith("/") && !path.endsWith("/")) { 509 path += "/"; 510 } 511 final Pathname p = (Pathname)Pathname.create(path); 512 this.setHost(p.getHost()); 513 this.setDevice(p.getDevice()); 514 this.setDirectory(p.getDirectory()); 515 this.setName(p.getName()); 516 this.setType(p.getType()); 517 this.setVersion(p.getVersion()); 518 return; 519 } 520 Debug.assertTrue(scheme != null); 521 URI uri = null; 522 try { 523 uri = url.toURI().normalize(); 524 } catch (URISyntaxException e) { 525 error(new LispError("Couldn't form URI from " 526 + "'" + url + "'" 527 + " because: " + e)); 528 } 529 String authority = uri.getAuthority(); 530 if (authority == null) { 531 authority = url.getAuthority(); 532 if (authority == null) { 533 Debug.trace(MessageFormat.format("{0} has a null authority.", url)); 534 } 535 } 536 537 setHost(NIL); 538 setHost(getHost().push(SCHEME)); 539 setHost(getHost().push(new SimpleString(scheme))); 540 541 if (authority != null) { 542 setHost(getHost().push(AUTHORITY)); 543 setHost(getHost().push(new SimpleString(authority))); 544 } 545 546 setDevice(NIL); 547 548 // URI encode necessary characters 549 String path = uri.getRawPath(); 550 if (path == null) { 551 path = ""; 552 } 553 String query = uri.getRawQuery(); 554 if (query != null) { 555 setHost(getHost().push(QUERY)); 556 setHost(getHost().push(new SimpleString(query))); 557 } 558 String fragment = uri.getRawFragment(); 559 if (fragment != null) { 560 setHost(getHost().push(FRAGMENT)); 561 setHost(getHost().push(new SimpleString(fragment))); 562 } 563 Pathname p = (Pathname)Pathname.create(path != null ? path : ""); 564 565 setDirectory(p.getDirectory()); 566 setName(p.getName()); 567 setType(p.getType()); 568 569 setHost(getHost().nreverse()); 570 invalidateNamestring(); 571 return; 380 return (PathnameURL)PathnameURL.create(s); 572 381 } 573 382 … … 586 395 } 587 396 } 588 namestring = s;397 // namestring = s; 589 398 if (Utilities.isPlatformWindows) { 590 399 if (s.length() >= 2 && s.charAt(1) == ':') { 591 setDevice(new SimpleString(s.charAt(0)));400 result.setDevice(new SimpleString(s.charAt(0))); 592 401 s = s.substring(2); 593 402 } … … 607 416 s = ""; 608 417 } 609 setDirectory(parseDirectory(d));418 result.setDirectory(parseDirectory(d)); 610 419 } 611 420 if (s.startsWith(".") … … 613 422 && (s.indexOf(".", 1) == -1 614 423 || s.substring(s.length() -1).equals("."))) { 615 setName(new SimpleString(s));616 return ;424 result.setName(new SimpleString(s)); 425 return result; 617 426 } 618 427 int index = s.lastIndexOf('.'); … … 627 436 if (n != null) { 628 437 if (n.equals("*")) { 629 setName(Keyword.WILD);438 result.setName(Keyword.WILD); 630 439 } else { 631 setName(new SimpleString(n));440 result.setName(new SimpleString(n)); 632 441 } 633 442 } 634 443 if (t != null) { 635 444 if (t.equals("*")) { 636 setType(Keyword.WILD);445 result.setType(Keyword.WILD); 637 446 } else { 638 setType(new SimpleString(t)); 639 } 640 } 641 } 447 result.setType(new SimpleString(t)); 448 } 449 } 450 return result; 451 } 642 452 643 453 private static final LispObject parseDirectory(String d) { … … 772 582 if (getDevice() == NIL) { 773 583 } else if (getDevice() == Keyword.UNSPECIFIC) { 774 } else if (isJar()) {775 LispObject[] jars = ((Cons) getDevice()).copyToArray();776 StringBuilder prefix = new StringBuilder();777 for (int i = 0; i < jars.length; i++) {778 prefix.append("jar:");779 LispObject component = jars[i];780 if (!(component instanceof Pathname)) {781 return null; // If DEVICE is a CONS, it should only contain Pathname782 }783 if (! ((Pathname)component).isURL() && i == 0) {784 sb.append("file:");785 uriEncoded = true;786 }787 Pathname jar = (Pathname) component;788 String encodedNamestring;789 if (uriEncoded) {790 encodedNamestring = uriEncode(jar.getNamestring());791 } else {792 encodedNamestring = jar.getNamestring();793 }794 sb.append(encodedNamestring);795 sb.append("!/");796 }797 sb = prefix.append(sb);584 // } else if (isJar()) { 585 // LispObject[] jars = ((Cons) getDevice()).copyToArray(); 586 // StringBuilder prefix = new StringBuilder(); 587 // for (int i = 0; i < jars.length; i++) { 588 // prefix.append("jar:"); 589 // LispObject component = jars[i]; 590 // if (!(component instanceof Pathname)) { 591 // return null; // If DEVICE is a CONS, it should only contain Pathname 592 // } 593 // if (! ((Pathname)component).isURL() && i == 0) { 594 // sb.append("file:"); 595 // uriEncoded = true; 596 // } 597 // Pathname jar = (Pathname) component; 598 // String encodedNamestring; 599 // if (uriEncoded) { 600 // encodedNamestring = uriEncode(jar.getNamestring()); 601 // } else { 602 // encodedNamestring = jar.getNamestring(); 603 // } 604 // sb.append(encodedNamestring); 605 // sb.append("!/"); 606 // } 607 // sb = prefix.append(sb); 798 608 } else if (getDevice() instanceof AbstractString) { 799 609 sb.append(getDevice().getStringValue()); … … 809 619 directoryNamestring = uriEncode(directoryNamestring); 810 620 } 811 if (isJar()) {812 if (directoryNamestring.startsWith("/")) {813 sb.append(directoryNamestring.substring(1));814 } else {815 sb.append(directoryNamestring);816 }817 } else {621 // if (isJar()) { 622 // if (directoryNamestring.startsWith("/")) { 623 // sb.append(directoryNamestring.substring(1)); 624 // } else { 625 // sb.append(directoryNamestring); 626 // } 627 // } else { 818 628 sb.append(directoryNamestring); 819 }629 // } 820 630 if (getName() instanceof AbstractString) { 821 631 String n = getName().getStringValue(); … … 855 665 } 856 666 857 if (isURL()) {858 LispObject o = Symbol.GETF.execute(getHost(), QUERY, NIL);859 if (o != NIL) {860 sb.append("?");861 sb.append(o.getStringValue());862 }863 o = Symbol.GETF.execute(getHost(), FRAGMENT, NIL);864 if (o != NIL) {865 sb.append("#");866 sb.append(o.getStringValue());867 }868 }667 // if (isURL()) { 668 // LispObject o = Symbol.GETF.execute(getHost(), QUERY, NIL); 669 // if (o != NIL) { 670 // sb.append("?"); 671 // sb.append(o.getStringValue()); 672 // } 673 // o = Symbol.GETF.execute(getHost(), FRAGMENT, NIL); 674 // if (o != NIL) { 675 // sb.append("#"); 676 // sb.append(o.getStringValue()); 677 // } 678 // } 869 679 870 680 if (this instanceof LogicalPathname) { … … 935 745 } 936 746 937 /** @return The representation of this pathname suitable for938 * referencing an entry in a Zip/JAR file939 */940 protected String asEntryPath() {941 Pathname p = Pathname.create();942 p.setDirectory(getDirectory());943 p.setName(getName());944 p.setType(getType());945 p.invalidateNamestring();946 String path = p.getNamestring();947 StringBuilder result = new StringBuilder();948 result.append(path);949 950 // Entries in jar files are always relative, but Pathname951 // directories are :ABSOLUTE.952 if (result.length() > 1953 && result.substring(0, 1).equals("/")) {954 return result.substring(1);955 }956 return result.toString();957 }958 747 959 748 @Override … … 1012 801 public boolean equalp(LispObject obj) { 1013 802 return equal(obj); 803 } 804 805 public boolean equals(Object o) { 806 if (!(this.getClass().isAssignableFrom(o.getClass()))) { 807 return super.equals(o); 808 } 809 return equal((Pathname)o); 810 } 811 812 public int hashCode() { 813 return sxhash(); 1014 814 } 1015 815 … … 1686 1486 @Override 1687 1487 public LispObject execute(LispObject arg, LispObject resolveSymlinks) { 1688 Pathname pathname = coerceToPathname(arg); 1689 if (pathname instanceof LogicalPathname) { 1690 pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname); 1691 } 1692 1693 LispObject result = NIL; 1694 if (pathname.isJar()) { 1695 String directory = pathname.asEntryPath(); 1696 Debug.assertTrue(directory != null); // We should only be listing directories 1697 1698 if (pathname.getDevice().cdr() instanceof Cons) { 1699 return error(new FileError("Unimplemented directory listing of JAR within JAR.", pathname)); 1700 } 1701 1702 if (directory.length() == 0) { 1703 directory = "/*"; 1704 } else { 1705 if (directory.endsWith("/")) { 1706 directory = "/" + directory + "*"; 1707 } else { 1708 directory = "/" + directory + "/*"; 1709 } 1710 } 1711 SimpleString wildcard = new SimpleString(directory); 1712 SimpleString wildcardDirectory = new SimpleString(directory + "/"); 1713 1714 ZipFile jar = ZipCache.get((Pathname)pathname.getDevice().car()); 1715 LispObject matches; 1716 for (Enumeration<? extends ZipEntry> entries = jar.entries(); 1717 entries.hasMoreElements();) { 1718 ZipEntry entry = entries.nextElement(); 1719 String entryName = "/" + entry.getName(); 1720 1721 if (entryName.endsWith("/")) { 1722 matches = Symbol.PATHNAME_MATCH_P 1723 .execute(new SimpleString(entryName), wildcardDirectory); 1724 } else { 1725 matches = Symbol.PATHNAME_MATCH_P. 1726 execute(new SimpleString(entryName), wildcard); 1727 } 1728 if (!matches.equals(NIL)) { 1729 String namestring = new String(pathname.getNamestring()); 1730 namestring = namestring.substring(0, namestring.lastIndexOf("!/") + 2) 1731 + entry.getName(); 1732 Pathname p = (Pathname)Pathname.create(namestring); 1733 result = new Cons(p, result); 1734 } 1735 } 1736 return result; 1737 } 1738 1739 if (pathname.isURL()) { 1740 return error(new LispError("Unimplemented.")); // XXX 1741 } 1742 1743 String s = pathname.getNamestring(); 1744 if (s != null) { 1745 File f = new File(s); 1746 if (f.isDirectory()) { 1747 try { 1748 File[] files = f.listFiles(); 1749 if (files == null) { 1750 return error(new FileError("Unable to list directory " 1751 + pathname.princToString() + ".", 1752 pathname)); 1753 } 1754 for (int i = files.length; i-- > 0;) { 1755 File file = files[i]; 1756 Pathname p; 1757 String path; 1758 if (resolveSymlinks == NIL) { 1759 path = file.getAbsolutePath(); 1760 } else { 1761 path = file.getCanonicalPath(); 1762 } 1763 URI pathURI = (new File(path)).toURI(); 1764 p = (Pathname)Pathname.create(pathURI); 1765 result = new Cons(p, result); 1766 } 1767 } catch (IOException e) { 1768 return error(new FileError("Unable to list directory " 1769 + pathname.princToString() + ".", 1770 pathname)); 1771 } catch (SecurityException e) { 1772 Debug.trace(e); 1773 } catch (NullPointerException e) { 1774 Debug.trace(e); 1775 } 1776 } 1777 } 1778 return result; 1779 } 1780 } 1781 1782 @DocString(name="match-wild-jar-pathname", 1783 args="wild-jar-pathname", 1784 returns="pathnames", 1785 doc="Returns the pathnames matching WILD-JAR-PATHNAME which is both wild and a jar-pathname.") 1786 static final Primitive MATCH_WILD_JAR_PATHNAME = new pf_match_wild_jar_pathname(); 1787 private static class pf_match_wild_jar_pathname extends Primitive { 1788 pf_match_wild_jar_pathname() { 1789 super("match-wild-jar-pathname", PACKAGE_SYS, false, "wild-jar-pathname"); 1790 } 1791 @Override 1792 public LispObject execute(LispObject arg) { 1793 Pathname pathname = coerceToPathname(arg); 1794 if (pathname instanceof LogicalPathname) { 1795 pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname); 1796 } 1797 if (!pathname.isJar()) { 1798 return new FileError("Not a jar pathname.", pathname); 1799 } 1800 if (!pathname.isWild()) { 1801 return new FileError("Not a wild pathname.", pathname); 1802 } 1803 Pathname jarPathname = Pathname.create(pathname); 1804 jarPathname.setDirectory(NIL); 1805 jarPathname.setName(NIL); 1806 jarPathname.setType(NIL); 1807 jarPathname.invalidateNamestring(); 1808 LispObject jarTruename = truename(jarPathname, false); 1809 1810 // We can't match anything in a non-existent jar 1811 if (jarTruename == NIL) { 1812 return NIL; 1813 } 1814 1815 LispObject result = NIL; 1816 String wild = "/" + pathname.asEntryPath(); 1817 final SimpleString wildcard = new SimpleString(wild); 1818 1819 if (pathname.getDevice().cdr() instanceof Cons) { 1820 ZipFile outerJar = ZipCache.get((Pathname)pathname.getDevice().car()); 1821 String entryPath = ((Pathname)pathname.getDevice().cdr().car()).getNamestring(); //??? 1822 if (entryPath.startsWith("/")) { 1823 entryPath = entryPath.substring(1); 1824 } 1825 ZipEntry entry = outerJar.getEntry(entryPath); 1826 InputStream inputStream = null; 1827 try { 1828 inputStream = outerJar.getInputStream(entry); 1829 } catch (IOException e) { 1830 return new FileError("Failed to read zip input stream inside zip.", 1831 pathname); 1832 } 1833 ZipInputStream zipInputStream 1834 = new ZipInputStream(inputStream); 1835 1836 try { 1837 while ((entry = zipInputStream.getNextEntry()) != null) { 1838 String entryName = "/" + entry.getName(); 1839 LispObject matches = Symbol.PATHNAME_MATCH_P 1840 .execute(new SimpleString(entryName), wildcard); 1841 1842 if (!matches.equals(NIL)) { 1843 String namestring = new String(pathname.getNamestring()); 1844 namestring = namestring.substring(0, namestring.lastIndexOf("!/") + 2) 1845 + entry.getName(); 1846 Pathname p = (Pathname)Pathname.create(namestring); 1847 result = new Cons(p, result); 1848 } 1849 } 1850 } catch (IOException e) { 1851 return new FileError("Failed to seek through zip inputstream inside zip.", 1852 pathname); 1853 } 1854 } else { 1855 ZipFile jar = ZipCache.get((Pathname)pathname.getDevice().car()); 1856 for (Enumeration<? extends ZipEntry> entries = jar.entries(); 1857 entries.hasMoreElements();) 1858 { 1859 ZipEntry entry = entries.nextElement(); 1860 String entryName = "/" + entry.getName(); 1861 LispObject matches = Symbol.PATHNAME_MATCH_P 1862 .execute(new SimpleString(entryName), wildcard); 1863 1864 if (!matches.equals(NIL)) { 1865 String namestring = new String(pathname.getNamestring()); 1866 namestring = namestring.substring(0, namestring.lastIndexOf("!/") + 2) 1867 + entry.getName(); 1868 Pathname p = (Pathname)Pathname.create(namestring); 1869 result = new Cons(p, result); 1870 } 1871 } 1872 } 1873 return result; 1874 } 1875 } 1488 Pathname pathname = coerceToPathname(arg); 1489 if (pathname instanceof LogicalPathname) { 1490 pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname); 1491 } 1492 1493 LispObject result = NIL; 1494 if (pathname.isJar()) { 1495 return PathnameJar.listDirectory((PathnameJar)pathname); 1496 } 1497 1498 // "All" pathnames are PathnameURLs now, so this condition needs to be tightened 1499 // should be all remote URLs can't have directory listings? 1500 // if (pathname.isURL()) { 1501 // return error(new LispError("Unimplemented.")); // XXX 1502 // } 1503 1504 String s = pathname.getNamestring(); 1505 if (s != null) { 1506 File f = new File(s); 1507 if (f.isDirectory()) { 1508 try { 1509 File[] files = f.listFiles(); 1510 if (files == null) { 1511 return error(new FileError("Unable to list directory " 1512 + pathname.princToString() + ".", 1513 pathname)); 1514 } 1515 for (int i = files.length; i-- > 0;) { 1516 File file = files[i]; 1517 Pathname p; 1518 String path; 1519 if (resolveSymlinks == NIL) { 1520 path = file.getAbsolutePath(); 1521 } else { 1522 path = file.getCanonicalPath(); 1523 } 1524 URI pathURI = (new File(path)).toURI(); 1525 p = (Pathname)Pathname.create(pathURI); 1526 result = new Cons(p, result); 1527 } 1528 } catch (IOException e) { 1529 return error(new FileError("Unable to list directory " 1530 + pathname.princToString() + ".", 1531 pathname)); 1532 } catch (SecurityException e) { 1533 Debug.trace(e); 1534 } catch (NullPointerException e) { 1535 Debug.trace(e); 1536 } 1537 } 1538 } 1539 return result; 1540 } 1541 }; 1876 1542 1877 1543 public boolean isAbsolute() { … … 2028 1694 } 2029 1695 } 2030 1696 2031 1697 static final Primitive MERGE_PATHNAMES = new pf_merge_pathnames(); 2032 1698 @DocString(name="merge-pathnames", … … 2037 1703 static final class pf_merge_pathnames extends Primitive { 2038 1704 pf_merge_pathnames() { 2039 super( "merge-pathnames", "pathname &optional default-pathname default-version");1705 super(Symbol.MERGE_PATHNAMES, "pathname &optional default-pathname default-version"); 2040 1706 } 2041 1707 @Override 2042 1708 public LispObject execute(LispObject arg) { 2043 2044 Pathname defaultPathname =2045 2046 2047 1709 Pathname pathname = coerceToPathname(arg); 1710 Pathname defaultPathname 1711 = coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()); 1712 LispObject defaultVersion = Keyword.NEWEST; 1713 return mergePathnames(pathname, defaultPathname, defaultVersion); 2048 1714 } 2049 1715 @Override 2050 1716 public LispObject execute(LispObject first, LispObject second) { 2051 1717 Pathname pathname = coerceToPathname(first); 2052 Pathname defaultPathname = 2053 coerceToPathname(second); 1718 Pathname defaultPathname = coerceToPathname(second); 2054 1719 LispObject defaultVersion = Keyword.NEWEST; 2055 1720 return mergePathnames(pathname, defaultPathname, defaultVersion); … … 2059 1724 LispObject third) { 2060 1725 Pathname pathname = coerceToPathname(first); 2061 Pathname defaultPathname = 2062 coerceToPathname(second); 1726 Pathname defaultPathname = coerceToPathname(second); 2063 1727 LispObject defaultVersion = third; 2064 1728 return mergePathnames(pathname, defaultPathname, defaultVersion); … … 2066 1730 } 2067 1731 2068 public static final PathnamemergePathnames(Pathname pathname, Pathname defaultPathname) {2069 2070 1732 public static final LispObject mergePathnames(Pathname pathname, Pathname defaultPathname) { 1733 return mergePathnames(pathname, defaultPathname, Keyword.NEWEST); 1734 } 2071 1735 2072 public static final Pathname mergePathnames(final Pathname pathname, 2073 final Pathname defaultPathname, 2074 final LispObject defaultVersion) 2075 { 2076 Pathname result; 2077 Pathname p = Pathname.create(pathname); 2078 Pathname d; 2079 2080 if (pathname instanceof LogicalPathname) { 2081 result = LogicalPathname.create(); 1736 public static final LispObject mergePathnames(final Pathname pathname, 1737 final Pathname defaultPathname, 1738 final LispObject defaultVersion) { 1739 Pathname result; 1740 Pathname p = Pathname.create(pathname); 1741 Pathname d; 1742 1743 if (pathname instanceof LogicalPathname) { 1744 result = LogicalPathname.create(); 1745 d = Pathname.create(defaultPathname); 1746 } else { 1747 if ((pathname instanceof PathnameJar) 1748 || (defaultPathname instanceof PathnameJar)) { 1749 result = PathnameJar.create(); 1750 } else { 1751 result = Pathname.create(); 1752 } 1753 1754 if (defaultPathname instanceof LogicalPathname) { 1755 d = LogicalPathname.translateLogicalPathname((LogicalPathname) defaultPathname); 1756 } else { 1757 if (defaultPathname instanceof PathnameJar) { 1758 d = PathnameJar.create(defaultPathname); 1759 } else { 2082 1760 d = Pathname.create(defaultPathname); 1761 } 1762 } 1763 } 1764 1765 if (pathname.getHost() != NIL) { 1766 result.setHost(p.getHost()); 1767 } else { 1768 result.setHost(d.getHost()); 1769 } 1770 1771 if (pathname.getDevice() != NIL) { 1772 result.setDevice(p.getDevice()); 1773 } else { 1774 if (d instanceof PathnameJar) { 1775 // If the defaults contain a JAR-PATHNAME, and the pathname 1776 // to be be merged does not have a specified DEVICE, a 1777 // specified HOST, and doesn't contain a relative DIRECTORY, 1778 // then on non-MSDOG, set its device to :UNSPECIFIC. 1779 if (pathname.getHost() == NIL 1780 && pathname.getDevice() == NIL 1781 && d.isJar() 1782 && !Utilities.isPlatformWindows) { 1783 if (pathname.getDirectory() != NIL 1784 && pathname.getDirectory().car() == Keyword.ABSOLUTE) { 1785 result.setDevice(Keyword.UNSPECIFIC); 1786 } else { 1787 result.setDevice(d.getDevice()); 1788 } 1789 } else { 1790 result.setDevice(d.getDevice()); 1791 } 1792 } 1793 } 1794 1795 // This part I no longer understand 1796 // if (pathname.isJar()) { 1797 // Cons jars = (Cons)result.getDevice(); 1798 // LispObject jar = jars.car; 1799 // if (jar instanceof Pathname) { 1800 // Pathname defaults = Pathname.create(d); 1801 // if (defaults.isJar()) { 1802 // defaults.setDevice(NIL); 1803 // } 1804 // Pathname o = mergePathnames((Pathname)jar, defaults); 1805 // if (o.getDirectory() instanceof Cons 1806 // && ((Cons)o.getDirectory()).length() == 1) { // i.e. (:ABSOLUTE) or (:RELATIVE) 1807 // o.setDirectory(NIL); 1808 // } 1809 // ((Cons)result.device).car = o; 1810 // } 1811 // result.setDirectory(p.getDirectory()); 1812 // } else { 1813 // result.setDirectory(mergeDirectories(p.getDirectory(), d.getDirectory())); 1814 // } 1815 result.setDirectory(mergeDirectories(p.getDirectory(), d.getDirectory())); 1816 1817 if (pathname.getName() != NIL) { 1818 result.setName(p.getName()); 1819 } else { 1820 result.setName(d.getName()); 1821 } 1822 if (pathname.getType() != NIL) { 1823 result.setType(p.getType()); 1824 } else { 1825 result.setType(d.getType()); 1826 } 1827 // CLtLv2 MERGE-PATHNAMES 1828 1829 // "[T]he missing components in the given pathname are filled 1830 // in from the defaults pathname, except that if no version is 1831 // specified the default version is used." 1832 1833 // "The merging rules for the version are more complicated and 1834 // depend on whether the pathname specifies a name. If the 1835 // pathname doesn't specify a name, then the version, if not 1836 // provided, will come from the defaults, just like the other 1837 // components. However, if the pathname does specify a name, 1838 // then the version is not affected by the defaults. The 1839 // reason is that the version ``belongs to'' some other file 1840 // name and is unlikely to have anything to do with the new 1841 // one. Finally, if this process leaves the 1842 // version missing, the default version is used." 1843 if (p.getVersion() != NIL) { 1844 result.setVersion(p.getVersion()); 1845 } else if (p.getName() == NIL) { 1846 if (defaultPathname.getVersion() == NIL) { 1847 result.setVersion(defaultVersion); 2083 1848 } else { 2084 result = Pathname.create(); 2085 if (defaultPathname instanceof LogicalPathname) { 2086 d = LogicalPathname.translateLogicalPathname((LogicalPathname) defaultPathname); 2087 } else { 2088 d = Pathname.create(defaultPathname); 2089 } 2090 } 2091 if (pathname.getHost() != NIL) { 2092 result.setHost(p.getHost()); 2093 } else { 2094 result.setHost(d.getHost()); 2095 } 2096 2097 if (pathname.getDevice() != NIL) { // XXX if device represent JARs we want to merge 2098 result.setDevice(p.getDevice()); 2099 } else { 2100 if (!p.isURL()) { 2101 // If the defaults contain a JAR-PATHNAME, and the 2102 // pathname to be be merged does not have a specified 2103 // DEVICE, a specified HOST, and doesn't contain a 2104 // relative DIRECTORY, then on non-MSDOG, set its 2105 // device to :UNSPECIFIC. 2106 if (pathname.getHost() == NIL 2107 && pathname.getDevice() == NIL 2108 && d.isJar() 2109 && !Utilities.isPlatformWindows) { 2110 if (pathname.getDirectory() != NIL 2111 && pathname.getDirectory().car() == Keyword.ABSOLUTE) { 2112 result.setDevice(Keyword.UNSPECIFIC); 2113 } else { 2114 result.setDevice(d.getDevice()); 2115 } 2116 } else { 2117 result.setDevice(d.getDevice()); 2118 } 2119 } 2120 } 2121 2122 if (pathname.isJar()) { 2123 Cons jars = (Cons)result.getDevice(); 2124 LispObject jar = jars.car; 2125 if (jar instanceof Pathname) { 2126 Pathname defaults = Pathname.create(d); 2127 if (defaults.isJar()) { 2128 defaults.setDevice(NIL); 2129 } 2130 Pathname o = mergePathnames((Pathname)jar, defaults); 2131 if (o.getDirectory() instanceof Cons 2132 && ((Cons)o.getDirectory()).length() == 1) { // i.e. (:ABSOLUTE) or (:RELATIVE) 2133 o.setDirectory(NIL); 2134 } 2135 ((Cons)result.device).car = o; 2136 } 2137 result.setDirectory(p.getDirectory()); 2138 } else { 2139 result.setDirectory(mergeDirectories(p.getDirectory(), d.getDirectory())); 2140 } 2141 2142 if (pathname.getName() != NIL) { 2143 result.setName(p.getName()); 2144 } else { 2145 result.setName(d.getName()); 2146 } 2147 if (pathname.getType() != NIL) { 2148 result.setType(p.getType()); 2149 } else { 2150 result.setType(d.getType()); 2151 } 2152 // CLtLv2 MERGE-PATHNAMES 2153 2154 // "[T]he missing components in the given pathname are filled 2155 // in from the defaults pathname, except that if no version is 2156 // specified the default version is used." 2157 2158 // "The merging rules for the version are more complicated and 2159 // depend on whether the pathname specifies a name. If the 2160 // pathname doesn't specify a name, then the version, if not 2161 // provided, will come from the defaults, just like the other 2162 // components. However, if the pathname does specify a name, 2163 // then the version is not affected by the defaults. The 2164 // reason is that the version ``belongs to'' some other file 2165 // name and is unlikely to have anything to do with the new 2166 // one. Finally, if this process leaves the 2167 // version missing, the default version is used." 2168 2169 if (p.getVersion() != NIL) { 2170 result.setVersion(p.getVersion()); 2171 } else if (p.getName() == NIL) { 2172 if (defaultPathname.getVersion() == NIL) { 2173 result.setVersion(defaultVersion); 2174 } else { 2175 result.setVersion(defaultPathname.getVersion()); 2176 } 2177 } else if (defaultVersion == NIL) { 2178 result.setVersion(p.getVersion()); 2179 } 2180 if (result.getVersion() == NIL) { 2181 result.setVersion(defaultVersion); 2182 } 2183 2184 if (pathname instanceof LogicalPathname) { 2185 // When we're returning a logical 2186 result.setDevice(Keyword.UNSPECIFIC); 2187 if (result.getDirectory().listp()) { 2188 LispObject original = result.getDirectory(); 2189 LispObject canonical = NIL; 2190 while (original != NIL) { 2191 LispObject component = original.car(); 2192 if (component instanceof AbstractString) { 2193 component = LogicalPathname.canonicalizeStringComponent((AbstractString) component); 2194 } 2195 canonical = canonical.push(component); 2196 original = original.cdr(); 2197 } 2198 result.setDirectory(canonical.nreverse()); 2199 } 2200 if (result.getName() instanceof AbstractString) { 2201 result.setName(LogicalPathname.canonicalizeStringComponent((AbstractString) result.getName())); 2202 } 2203 if (result.getType() instanceof AbstractString) { 2204 result.setType(LogicalPathname.canonicalizeStringComponent((AbstractString) result.getType())); 2205 } 2206 } 2207 result.invalidateNamestring(); 2208 return result; 1849 result.setVersion(defaultPathname.getVersion()); 1850 } 1851 } else if (defaultVersion == NIL) { 1852 result.setVersion(p.getVersion()); 1853 } 1854 if (result.getVersion() == NIL) { 1855 result.setVersion(defaultVersion); 1856 } 1857 1858 if (pathname instanceof LogicalPathname) { 1859 // When we're returning a logical 1860 result.setDevice(Keyword.UNSPECIFIC); 1861 if (result.getDirectory().listp()) { 1862 LispObject original = result.getDirectory(); 1863 LispObject canonical = NIL; 1864 while (original != NIL) { 1865 LispObject component = original.car(); 1866 if (component instanceof AbstractString) { 1867 component = LogicalPathname.canonicalizeStringComponent((AbstractString) component); 1868 } 1869 canonical = canonical.push(component); 1870 original = original.cdr(); 1871 } 1872 result.setDirectory(canonical.nreverse()); 1873 } 1874 if (result.getName() instanceof AbstractString) { 1875 result.setName(LogicalPathname.canonicalizeStringComponent((AbstractString) result.getName())); 1876 } 1877 if (result.getType() instanceof AbstractString) { 1878 result.setType(LogicalPathname.canonicalizeStringComponent((AbstractString) result.getType())); 1879 } 1880 } 1881 return result; 2209 1882 } 2210 1883 … … 2245 1918 } 2246 1919 2247 2248 1920 public static final LispObject truename(Pathname pathname) { 2249 1921 return truename(pathname, false); … … 2264 1936 */ 2265 1937 public static final LispObject truename(Pathname pathname, 2266 boolean errorIfDoesNotExist) 2267 { 2268 if (pathname == null || pathname.equals(NIL)) { 2269 return doTruenameExit(pathname, errorIfDoesNotExist); 2270 } 2271 if (pathname instanceof LogicalPathname) { 2272 pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname); 2273 } 2274 if (pathname.isWild()) { 2275 return error(new FileError("Bad place for a wild pathname.", 2276 pathname)); 2277 } 2278 if (pathname instanceof PathnameJar) { 2279 return truename((PathnameJar)pathname, errorIfDoesNotExist); 2280 } 2281 if (pathname instanceof PathnameURL) { 2282 return truename((PathnameURL)pathname, errorIfDoesNotExist); 2283 } 2284 if (!(pathname.isJar() || pathname.isURL())) { 2285 Pathname result 2286 = mergePathnames(pathname, 2287 coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()), 2288 NIL); 2289 final File file = result.getFile(); 2290 if (file.exists()) { 2291 if (file.isDirectory()) { 2292 result = Pathname.getDirectoryPathname(file); 2293 } else { 2294 try { 2295 result = (Pathname)Pathname.create(file.getCanonicalPath()); 2296 } catch (IOException e) { 2297 return error(new FileError(e.getMessage(), pathname)); 2298 } 2299 } 2300 if (Utilities.isPlatformUnix) { 2301 result.setDevice(Keyword.UNSPECIFIC); 2302 } 2303 return result; 2304 } 2305 } else if (pathname.isURL()) { 2306 if (pathname.getInputStream() != null) { 2307 // If there is no type, query or fragment, we check to 2308 // see if there is URL available "underneath". 2309 if (pathname.getName() != NIL 2310 && pathname.getType() == NIL 2311 && Symbol.GETF.execute(pathname.getHost(), QUERY, NIL) == NIL 2312 && Symbol.GETF.execute(pathname.getHost(), FRAGMENT, NIL) == NIL) { 2313 Pathname p = (Pathname)Pathname.create(pathname.getNamestring() + "/"); 2314 if (p.getInputStream() != null) { 2315 return p; 2316 } 2317 } 2318 return pathname; 2319 } 2320 } else 2321 jarfile: { 2322 // Possibly canonicalize jar file directory 2323 Cons jars = (Cons) pathname.getDevice(); 2324 LispObject o = jars.car(); 2325 if (!(o instanceof Pathname)) { 2326 return doTruenameExit(pathname, errorIfDoesNotExist); 2327 } 2328 if (o instanceof Pathname 2329 && !(((Pathname)o).isURL()) 2330 // XXX Silently fail to call truename() if the default 2331 // pathname defaults exist within a jar, as that will 2332 // (probably) not succeed. The better solution would 2333 // probably be to parametize the value of 2334 // *DEFAULT-PATHNAME-DEFAULTS* on invocations of 2335 // truename(). 2336 && !coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()).isJar()) 2337 { 2338 LispObject truename = Pathname.truename((Pathname)o, errorIfDoesNotExist); 2339 if (truename != null && truename != NIL 2340 && truename instanceof Pathname) { 2341 Pathname truePathname = (Pathname)truename; 2342 // A jar that is a directory makes no sense, so exit 2343 if (truePathname.getNamestring().endsWith("/")) { 2344 break jarfile; 2345 } 2346 jars.car = truePathname; 2347 } else { 2348 break jarfile; 2349 } 2350 } 2351 2352 // Check for existence of a JAR file and/or JarEntry 2353 // 2354 // Cases: 2355 // 1. JAR 2356 // 2. JAR in JAR 2357 // 3. JAR with Entry 2358 // 4. JAR in JAR with Entry 2359 2360 ZipFile jarFile = ZipCache.get((Pathname)jars.car()); 2361 String entryPath = pathname.asEntryPath(); 2362 if (jarFile != null) { 2363 if (jars.cdr() instanceof Cons) { 2364 Pathname inner = (Pathname) jars.cdr().car(); 2365 InputStream inputStream = Utilities.getInputStream(jarFile, inner); 2366 if (inputStream != null) { 2367 if (entryPath.length() == 0) { 2368 return pathname; // Case 2 2369 } else { 2370 ZipInputStream zipInputStream 2371 = new ZipInputStream(inputStream); 2372 ZipEntry entry = Utilities.getEntry(zipInputStream, 2373 entryPath, 2374 false); 2375 if (entry != null) { 2376 // XXX this could possibly be a directory? 2377 return pathname; // Case 4 2378 } 2379 } 2380 } 2381 } else { 2382 if (entryPath.length() == 0) { 2383 return pathname; // Case 1 2384 } else { 2385 ZipEntry entry = jarFile.getEntry(entryPath); 2386 if (entry != null) { 2387 // ensure this isn't a directory 2388 if (entry.isDirectory()) { 2389 break jarfile; 2390 } 2391 try { 2392 InputStream input = jarFile.getInputStream(entry); 2393 if (input != null) { 2394 return pathname; // Case 3 2395 } 2396 } catch (IOException e) { 2397 break jarfile; 2398 } 2399 } 2400 } 2401 } 2402 } 2403 } 2404 error: 1938 boolean errorIfDoesNotExist) { 1939 if (pathname == null || pathname.equals(NIL)) { 1940 return doTruenameExit(pathname, errorIfDoesNotExist); 1941 } 1942 if (pathname instanceof LogicalPathname) { 1943 pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname); 1944 } 1945 if (pathname.isWild()) { 1946 return error(new FileError("Fundamentally unable to find a truename for any wild pathname.", 1947 pathname)); 1948 } 1949 Pathname result 1950 = (Pathname)mergePathnames(pathname, 1951 coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()), 1952 NIL); 1953 final File file = result.getFile(); 1954 if (file.exists()) { 1955 if (file.isDirectory()) { 1956 result = Pathname.getDirectoryPathname(file); 1957 } else { 1958 try { 1959 result = (Pathname)Pathname.create(file.getCanonicalPath()); 1960 } catch (IOException e) { 1961 return error(new FileError(e.getMessage(), pathname)); 1962 } 1963 } 1964 if (Utilities.isPlatformUnix) { 1965 result.setDevice(Keyword.UNSPECIFIC); 1966 } 1967 return result; 1968 } 2405 1969 return doTruenameExit(pathname, errorIfDoesNotExist); 2406 1970 } … … 2452 2016 } 2453 2017 }; 2454 2455 2456 public InputStream getInputStream() { 2457 InputStream result = null; 2458 if (isJar()) { 2459 String entryPath = asEntryPath(); 2460 // XXX We only return the bytes of an entry in a JAR 2461 Debug.assertTrue(entryPath != null); 2462 ZipFile jarFile = ZipCache.get((Pathname)getDevice().car()); 2463 Debug.assertTrue(jarFile != null); 2464 // Is this a JAR within a JAR? 2465 if (getDevice().cdr() instanceof Cons) { 2466 Pathname inner = (Pathname) getDevice().cdr().car(); 2467 InputStream input = Utilities.getInputStream(jarFile, inner); 2468 ZipInputStream zipInputStream = new ZipInputStream(input); 2469 result = Utilities.getEntryAsInputStream(zipInputStream, entryPath); 2470 } else { 2471 ZipEntry entry = jarFile.getEntry(entryPath); 2472 if (entry == null) { 2473 Debug.trace("Failed to get InputStream for " 2474 + "'" + getNamestring() + "'"); 2475 // XXX should this be fatal? 2476 Debug.assertTrue(false); 2477 } 2478 try { 2479 result = jarFile.getInputStream(entry); 2480 } catch (IOException e) { 2481 Debug.warn("Failed to get InputStream from " 2482 + "'" + getNamestring() + "'" 2483 + ": " + e); 2484 } 2485 } 2486 } else if (isURL()) { 2487 URL url = this.toURL(); 2488 try { 2489 result = url.openStream(); 2490 } catch (IOException e) { 2491 Debug.warn("Failed to get InputStream from " 2492 + "'" + getNamestring() + "'" 2493 + ": " + e); 2494 } 2495 } else { 2496 File file = getFile(); 2497 try { 2498 result = new FileInputStream(file); 2499 } catch (IOException e) { 2500 Debug.warn("Failed to get InputStream from " 2501 + "'" + getNamestring() + "'" 2502 + ": " + e); 2503 } 2504 } 2505 return result; 2506 } 2507 2508 /** @return Time in milliseconds since the UNIX epoch at which the 2509 * resource was last modified, or 0 if the time is unknown. 2510 */ 2511 public long getLastModified() { 2512 if (!(isJar() || isURL())) { 2513 File f = getFile(); 2514 return f.lastModified(); 2515 } 2516 2517 if (isJar()) { 2518 // JAR cases 2519 // 0. JAR from URL 2520 // 1. JAR 2521 // 2. JAR in JAR 2522 // 3. Entry in JAR 2523 // 4. Entry in JAR in JAR 2524 String entryPath = asEntryPath(); 2525 Cons d = (Cons)getDevice(); 2526 if (d.cdr().equals(NIL)) { 2527 if (entryPath.length() == 0) { 2528 LispObject o = d.car(); 2529 // 0. JAR from URL 2530 // 1. JAR 2531 return ((Pathname)o).getLastModified(); 2532 } else { 2533 // 3. Entry in JAR 2534 final ZipEntry entry 2535 = ZipCache.get((Pathname)getDevice().car()).getEntry(entryPath); 2536 if (entry == null) { 2537 return 0; 2538 } 2539 final long time = entry.getTime(); 2540 if (time == -1) { 2541 return 0; 2542 } 2543 return time; 2544 } 2545 } else { 2546 ZipFile outerJar = ZipCache.get((Pathname)d.car()); 2547 if (entryPath.length() == 0) { 2548 // 4. JAR in JAR 2549 String jarPath = ((Pathname)d.cdr()).asEntryPath(); 2550 final ZipEntry entry = outerJar.getEntry(jarPath); 2551 final long time = entry.getTime(); 2552 if (time == -1) { 2553 return 0; 2554 } 2555 return time; 2556 } else { 2557 // 5. Entry in JAR in JAR 2558 String innerJarPath = ((Pathname)d.cdr()).asEntryPath(); 2559 ZipEntry entry = outerJar.getEntry(entryPath); 2560 ZipInputStream innerJarInputStream 2561 = Utilities.getZipInputStream(outerJar, innerJarPath); 2562 ZipEntry innerEntry = Utilities.getEntry(innerJarInputStream, 2563 entryPath); 2564 long time = innerEntry.getTime(); 2565 if (time == -1) { 2566 return 0; 2567 } 2568 return time; 2569 } 2570 } 2571 } 2572 if (isURL()) { 2573 return getURLConnection().getLastModified(); 2574 } 2575 return 0; 2576 } 2577 2578 private static final Primitive MKDIR = new pf_mkdir(); 2579 @DocString(name="mkdir", 2580 args="pathname", 2581 returns="generalized-boolean", 2582 doc="Attempts to create directory at PATHNAME returning the success or failure.") 2583 private static class pf_mkdir extends Primitive { 2584 pf_mkdir() { 2585 super("mkdir", PACKAGE_SYS, false, "pathname"); 2586 } 2587 2588 @Override 2589 public LispObject execute(LispObject arg) { 2590 final Pathname pathname = coerceToPathname(arg); 2591 if (pathname.isWild()) { 2592 error(new FileError("Bad place for a wild pathname.", pathname)); 2593 } 2594 Pathname defaultedPathname = 2595 mergePathnames(pathname, 2596 coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()), 2597 NIL); 2598 if (defaultedPathname.isURL() || defaultedPathname.isJar()) { 2599 return new FileError("Cannot mkdir with a " 2600 + (defaultedPathname.isURL() ? "URL" : "jar") 2601 + " Pathname.", 2602 defaultedPathname); 2603 } 2018 2019 2020 public InputStream getInputStream() { 2021 InputStream result = null; 2022 File file = getFile(); 2023 try { 2024 result = new FileInputStream(file); 2025 } catch (IOException e) { 2026 simple_error("Failed to get InputStream from ~a because ~a", this, e); 2027 } 2028 return result; 2029 } 2030 2031 2032 2033 /** @return Time in milliseconds since the UNIX epoch at which the 2034 * resource was last modified, or 0 if the time is unknown. 2035 */ 2036 public long getLastModified() { 2037 File f = getFile(); 2038 return f.lastModified(); 2039 } 2040 2041 2042 private static final Primitive MKDIR = new pf_mkdir(); 2043 @DocString(name="mkdir", 2044 args="pathname", 2045 returns="generalized-boolean", 2046 doc="Attempts to create directory at PATHNAME returning the success or failure.") 2047 private static class pf_mkdir extends Primitive { 2048 pf_mkdir() { 2049 super("mkdir", PACKAGE_SYS, false, "pathname"); 2050 } 2051 2052 @Override 2053 public LispObject execute(LispObject arg) { 2054 final Pathname pathname = coerceToPathname(arg); 2055 if (pathname.isWild()) { 2056 error(new FileError("Bad place for a wild pathname.", pathname)); 2057 } 2058 Pathname defaultedPathname 2059 = (Pathname)mergePathnames(pathname, 2060 coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()), 2061 NIL); 2062 if (defaultedPathname.isURL() || defaultedPathname.isJar()) { 2063 return new FileError("Cannot mkdir with a " 2064 + (defaultedPathname.isURL() ? "URL" : "jar") 2065 + " Pathname.", 2066 defaultedPathname); 2067 } 2604 2068 2605 2606 2607 2608 2609 2610 2611 2069 File file = defaultedPathname.getFile(); 2070 return file.mkdir() ? T : NIL; 2071 } 2072 } 2073 2074 private static final Primitive RENAME_FILE = new pf_rename_file(); 2075 @DocString(name="rename-file", 2612 2076 args="filespec new-name", 2613 2077 returns="defaulted-new-name, old-truename, new-truename", … … 2619 2083 + "value, OLD-TRUENAME, is the truename of the file before it was renamed. The tertiary \n" 2620 2084 + "value, NEW-TRUENAME, is the truename of the file after it was renamed.\n") 2621 private static class pf_rename_file extends Primitive { 2622 pf_rename_file() { 2623 super("rename-file", "filespec new-name"); 2624 } 2625 @Override 2626 public LispObject execute(LispObject first, LispObject second) { 2627 Pathname oldPathname = coerceToPathname(first); 2628 Pathname oldTruename = (Pathname) truename(oldPathname, true); 2629 Pathname newName = coerceToPathname(second); 2630 if (newName.isWild()) { 2631 error(new FileError("Bad place for a wild pathname.", newName)); 2632 } 2633 if (oldTruename.isJar()) { 2634 error(new FileError("Bad place for a jar pathname.", oldTruename)); 2635 } 2636 if (newName.isJar()) { 2637 error(new FileError("Bad place for a jar pathname.", newName)); 2638 } 2639 if (oldTruename.isURL()) { 2640 error(new FileError("Bad place for a URL pathname.", oldTruename)); 2641 } 2642 if (newName.isURL()) { 2643 error(new FileError("Bad place for a jar pathname.", newName)); 2644 } 2645 2646 Pathname defaultedNewName = mergePathnames(newName, oldTruename, NIL); 2647 2648 File source = oldTruename.getFile(); 2649 File destination = null; 2650 if (defaultedNewName instanceof LogicalPathname) { 2651 destination = LogicalPathname.translateLogicalPathname((LogicalPathname)defaultedNewName) 2652 .getFile(); 2653 } else { 2654 destination = defaultedNewName.getFile(); 2655 } 2656 // By default, MSDOG doesn't allow one to remove files that are open. 2657 if (Utilities.isPlatformWindows) { 2658 if (destination.isFile()) { 2659 ZipCache.remove(destination); 2660 destination.delete(); 2661 } 2662 } 2663 if (source.renameTo(destination)) { // Success! 2664 Pathname newTruename = (Pathname)truename(defaultedNewName, true); 2665 return LispThread.currentThread().setValues(defaultedNewName, 2666 oldTruename, 2667 newTruename); 2668 } 2669 return error(new FileError("Unable to rename " 2670 + oldTruename.princToString() 2671 + " to " + newName.princToString() 2672 + ".", 2673 oldTruename)); 2674 } 2675 } 2085 private static class pf_rename_file extends Primitive { 2086 pf_rename_file() { 2087 super("rename-file", "filespec new-name"); 2088 } 2089 @Override 2090 public LispObject execute(LispObject first, LispObject second) { 2091 Pathname oldPathname = coerceToPathname(first); 2092 Pathname oldTruename = (Pathname) Symbol.TRUENAME.execute(oldPathname); 2093 Pathname newName = coerceToPathname(second); 2094 if (newName.isWild()) { 2095 error(new FileError("Bad place for a wild pathname.", newName)); 2096 } 2097 if (oldTruename.isJar()) { 2098 error(new FileError("Bad place for a jar pathname.", oldTruename)); 2099 } 2100 if (newName.isJar()) { 2101 error(new FileError("Bad place for a jar pathname.", newName)); 2102 } 2103 if (oldTruename.isURL()) { 2104 error(new FileError("Bad place for a URL pathname.", oldTruename)); 2105 } 2106 if (newName.isURL()) { 2107 error(new FileError("Bad place for a jar pathname.", newName)); 2108 } 2109 2110 Pathname defaultedNewName = (Pathname)mergePathnames(newName, oldTruename, NIL); 2111 2112 File source = oldTruename.getFile(); 2113 File destination = null; 2114 if (defaultedNewName instanceof LogicalPathname) { 2115 destination = LogicalPathname.translateLogicalPathname((LogicalPathname)defaultedNewName) 2116 .getFile(); 2117 } else { 2118 destination = defaultedNewName.getFile(); 2119 } 2120 if (Utilities.isPlatformWindows) { 2121 if (destination.isFile()) { 2122 //if (destination.isJar()) { 2123 // By default, MSDOG doesn't allow one to remove files that are open, so we need to close 2124 // any open jar references 2125 // FIXME 2126 // ZipCache.remove(destination); 2127 // } 2128 destination.delete(); 2129 } 2130 } 2131 if (source.renameTo(destination)) { // Success! 2132 Pathname newTruename = (Pathname)truename(defaultedNewName, true); 2133 return LispThread.currentThread().setValues(defaultedNewName, 2134 oldTruename, 2135 newTruename); 2136 } 2137 return error(new FileError("Unable to rename " 2138 + oldTruename.princToString() 2139 + " to " + newName.princToString() 2140 + ".", 2141 oldTruename)); 2142 } 2143 } 2676 2144 2677 2678 2679 2680 2681 2682 doc="Returns just the name, type, and version components of PATHNAME.")2683 2684 2685 super("file-namestring", "pathname");2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 doc="Returns the host name of PATHNAME.")2713 2714 2715 2716 2717 2718 2719 2720 2721 2145 // TODO clarify uri encoding cases in implementation and document 2146 private static final Primitive FILE_NAMESTRING = new pf_file_namestring(); 2147 @DocString(name="file-namestring", 2148 args="pathname", 2149 returns="namestring", 2150 doc="Returns just the name, type, and version components of PATHNAME.") 2151 private static class pf_file_namestring extends Primitive { 2152 pf_file_namestring() { 2153 super(Symbol.FILE_NAMESTRING, "pathname"); 2154 } 2155 @Override 2156 public LispObject execute(LispObject arg) { 2157 Pathname p = coerceToPathname(arg); 2158 StringBuilder sb = new StringBuilder(); 2159 if (p.getName() instanceof AbstractString) { 2160 sb.append(p.getName().getStringValue()); 2161 } else if (p.getName() == Keyword.WILD) { 2162 sb.append('*'); 2163 } else { 2164 return NIL; 2165 } 2166 if (p.getType() instanceof AbstractString) { 2167 sb.append('.'); 2168 sb.append(p.getType().getStringValue()); 2169 } else if (p.getType() == Keyword.WILD) { 2170 sb.append(".*"); 2171 } 2172 return new SimpleString(sb); 2173 } 2174 } 2175 2176 private static final Primitive HOST_NAMESTRING = new pf_host_namestring(); 2177 @DocString(name="host-namestring", 2178 args="pathname", 2179 returns="namestring", 2180 doc="Returns the host name of PATHNAME.") 2181 private static class pf_host_namestring extends Primitive { 2182 pf_host_namestring() { 2183 super("host-namestring", "pathname"); 2184 } 2185 @Override 2186 public LispObject execute(LispObject arg) { 2187 return coerceToPathname(arg).getHost(); // XXX URL-PATHNAME 2188 } 2189 } 2722 2190 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2191 public URL toURL() { 2192 try { 2193 if (isURL()) { 2194 return new URL(getNamestring()); 2195 } else { 2196 return toFile().toURI().toURL(); 2197 } 2198 } catch (MalformedURLException e) { 2199 error(new LispError(getNamestring() + " is not a valid URL")); 2200 return null; // not reached 2201 } 2202 } 2203 2204 public File toFile() { 2205 if(!isURL()) { 2206 return new File(getNamestring()); 2207 } else { 2208 throw new RuntimeException(this + " does not represent a file"); 2209 } 2210 } 2211 2212 static { 2213 LispObject obj = Symbol.DEFAULT_PATHNAME_DEFAULTS.getSymbolValue(); 2214 Symbol.DEFAULT_PATHNAME_DEFAULTS.setSymbolValue(coerceToPathname(obj)); 2215 } 2748 2216 2749 2217 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2218 @DocString(name="uri-decode", 2219 args="string", 2220 returns="string", 2221 doc="Decode STRING percent escape sequences in the manner of URI encodings.") 2222 private static final Primitive URI_DECODE = new pf_uri_decode(); 2223 private static final class pf_uri_decode extends Primitive { 2224 pf_uri_decode() { 2225 super("uri-decode", PACKAGE_EXT, true); 2226 } 2227 @Override 2228 public LispObject execute(LispObject arg) { 2229 if (!(arg instanceof AbstractString)) { 2230 return type_error(arg, Symbol.STRING); 2231 } 2232 String result = uriDecode(((AbstractString)arg).toString()); 2233 return new SimpleString(result); 2234 } 2235 }; 2236 2237 static String uriDecode(String s) { 2238 try { 2239 URI uri = new URI("file://foo?" + s); 2240 return uri.getQuery(); 2241 } catch (URISyntaxException e) {} 2242 return null; // Error 2243 } 2776 2244 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2245 @DocString(name="uri-encode", 2246 args="string", 2247 returns="string", 2248 doc="Encode percent escape sequences in the manner of URI encodings.") 2249 private static final Primitive URI_ENCODE = new pf_uri_encode(); 2250 private static final class pf_uri_encode extends Primitive { 2251 pf_uri_encode() { 2252 super("uri-encode", PACKAGE_EXT, true); 2253 } 2254 @Override 2255 public LispObject execute(LispObject arg) { 2256 if (!(arg instanceof AbstractString)) { 2257 return type_error(arg, Symbol.STRING); 2258 } 2259 String result = uriEncode(((AbstractString)arg).toString()); 2260 return new SimpleString(result); 2261 } 2262 }; 2263 2264 static String uriEncode(String s) { 2265 // The constructor we use here only allows absolute paths, so 2266 // we manipulate the input and output correspondingly. 2267 String u; 2268 if (!s.startsWith("/")) { 2269 u = "/" + s; 2270 } else { 2271 u = new String(s); 2272 } 2273 try { 2274 URI uri = new URI("file", "", u, ""); 2275 String result = uri.getRawPath(); 2276 if (!s.startsWith("/")) { 2277 return result.substring(1); 2278 } 2279 return result; 2280 } catch (URISyntaxException e) { 2281 Debug.assertTrue(false); 2282 } 2283 return null; // Error 2284 } 2285 2286 2287 File getFile() { 2288 String namestring = getNamestring(); // XXX UNC pathnames currently have no namestring 2289 if (namestring != null) { 2290 return new File(namestring); 2291 } 2292 error(new FileError("Pathname has no namestring: " + princToString(), 2825 2293 this)); 2826 // Not reached.2827 return null;2828 } 2829 2294 return (File)UNREACHED; 2295 } 2296 2297 public static Pathname getDirectoryPathname(File file) { 2830 2298 try { 2831 2299 String namestring = file.getCanonicalPath(); … … 2842 2310 } 2843 2311 } 2312 2313 // Whether this pathname represents a file on the filesystem, not 2314 // addressed as a JAR-PATHNAME 2315 public boolean isLocalFile() { 2316 if (getHost().equals(NIL) 2317 || Symbol.GETF.execute(getHost(), PathnameURL.SCHEME, NIL).equals("file")) { 2318 return true; 2319 } 2320 return false; 2321 } 2322 2323 /** @return The representation of this pathname suitable for 2324 * referencing an entry in a Zip/JAR file 2325 */ 2326 protected String asEntryPath() { 2327 Pathname p = Pathname.create(); 2328 p.setDirectory(getDirectory()) 2329 .setName(getName()) 2330 .setType(getType()); 2331 String path = p.getNamestring(); 2332 2333 StringBuilder result = new StringBuilder(); 2334 result.append(path); 2335 2336 // Entries in jar files are always relative, but Pathname 2337 // directories are :ABSOLUTE. 2338 if (result.length() > 1 2339 && result.substring(0, 1).equals("/")) { 2340 return result.substring(1); 2341 } 2342 return result.toString(); 2343 } 2344 2844 2345 } -
trunk/abcl/src/org/armedbear/lisp/PathnameJar.java
r15393 r15395 35 35 import static org.armedbear.lisp.Lisp.*; 36 36 37 import java.io.InputStream; 37 38 import java.io.IOException; 38 39 import java.io.File; … … 42 43 import java.net.URISyntaxException; 43 44 import java.util.ArrayList; 45 import java.util.Iterator; 44 46 import java.util.List; 47 import java.util.Map; 48 import java.util.Set; 49 import java.util.zip.ZipEntry; 45 50 import java.util.zip.ZipFile; 46 51 … … 48 53 extends PathnameURL 49 54 { 55 static final public String JAR_URI_SUFFIX = "!/"; 56 static final public String JAR_URI_PREFIX = "jar:"; 57 50 58 protected PathnameJar() {} 51 59 … … 54 62 } 55 63 56 static final public String JAR_URI_SUFFIX = "!/"; 57 static final public String JAR_URI_PREFIX = "jar:"; 58 64 public static LispObject createFromPathname(Pathname p) { 65 if (p instanceof PathnameURL) { 66 return PathnameJar.create(JAR_URI_PREFIX + ((PathnameURL)p).getNamestringAsURI() + JAR_URI_SUFFIX); 67 } else if (p instanceof Pathname) { 68 // FIXME: not going to work with namestrings with characters that need URI escaping 69 return PathnameJar.create(JAR_URI_PREFIX + "file://" + p.getNamestring() + JAR_URI_SUFFIX); 70 } else { 71 return p; 72 } 73 } 74 75 static public LispObject createFromFile(String s) { 76 return PathnameJar.create("jar:file:" + s + JAR_URI_SUFFIX); 77 } 78 79 static public LispObject createEntryFromFile(String jar, String entry) { 80 return PathnameJar.create("jar:file:" + jar + JAR_URI_SUFFIX + entry); 81 } 82 83 static public LispObject createEntryFromJar(PathnameJar jar, String entry) { 84 if (jar.isArchiveEntry()) { 85 return simple_error("Failed to create the entry ~a in ~a", entry, jar); 86 } 87 return PathnameJar.create(jar.getNamestring() + entry); 88 } 59 89 /** 60 90 * Enumerate the components of a jar namestring … … 101 131 } 102 132 103 // the first value is not a jar Pathname, 133 // The root, non-PathnameJar location of this reference 134 // For files, possibly either a relative or absolute directory 104 135 result.add(parts[0]); 105 136 106 // the references to jars, all suffixed with JAR_URI_SUFFIX 137 // The references to the pathnames of archives located within the 138 // root jar. 139 // These will be relative directory paths suffixed with JAR_URI_SUFFIX 107 140 for (int j = 1; j < prefixCount; j++) { 108 141 String ns = parts[j] + JAR_URI_SUFFIX; … … 110 143 } 111 144 112 // possibly return the path inside the last jar 145 // possibly return the path inside the last jar as an absolute path 113 146 if (parts.length == (prefixCount + 1)) { 114 147 result.add("/" + parts[parts.length - 1]); … … 164 197 } 165 198 199 static public Pathname create() { 200 return new PathnameJar(); 201 } 166 202 static public LispObject create(String s) { 167 203 if (!s.startsWith(JAR_URI_PREFIX)) { … … 174 210 return parse_error("Couldn't parse PATHNAME-JAR from namestring: " + s); 175 211 } 212 176 213 PathnameJar result = new PathnameJar(); 177 214 … … 268 305 } 269 306 307 LispObject getRootJar() { 308 return getDevice().car(); 309 } 310 311 LispObject getJars() { 312 return getDevice(); 313 } 270 314 271 315 public static final LispObject truename(PathnameJar pathname, 272 316 boolean errorIfDoesNotExist) { 273 // PathnameJar result274 // = (PathnameJar) mergePathnames(pathname,275 // coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()),276 // NIL);277 278 317 PathnameJar result = pathname; 279 280 LispObject enclosingJars = NIL; 281 LispObject current = pathname.getDevice(); 282 283 while (current instanceof PathnameJar){ 284 enclosingJars = enclosingJars.push(current); 285 current = ((PathnameJar)current).getDevice(); 286 } 287 288 LispObject outerJar = Pathname.truename(current, errorIfDoesNotExist); 289 290 String outerJarNamestring = ((Pathname)outerJar).getNamestring(); 291 try { 292 ZipFile jarFile = new ZipFile(outerJarNamestring); 293 while (enclosingJars.car() != NIL) { 294 LispObject jar = enclosingJars.car(); 295 String ns = ((Pathname)jar).getNamestring(); 296 ZipFile f = new ZipFile(ns); 297 enclosingJars = enclosingJars.cdr(); 298 } 299 } catch (IOException e) { 300 return Pathname.doTruenameExit(result, errorIfDoesNotExist); 301 } 302 303 return result; 318 319 LispObject jars = pathname.getJars(); 320 Pathname rootJar = (Pathname) pathname.getRootJar(); 321 LispObject enclosingJars = jars.cdr(); 322 323 if (!rootJar.isLocalFile()) { 324 // FIXME implement me 325 simple_error("Unimplemented TRUENAME for non-file root jar."); 326 } else { 327 rootJar = (Pathname)Symbol.MERGE_PATHNAMES.execute(rootJar); 328 } 329 330 rootJar = (Pathname)Symbol.TRUENAME.execute(rootJar); 331 332 PathnameJar p = new PathnameJar(); 333 p.copyFrom(pathname); 334 p.setDevice(new Cons(rootJar, enclosingJars)); 335 336 if (!p.isArchiveEntry()) { 337 ZipCache.Archive archive = ZipCache.getArchive(p); 338 if (archive == null) { 339 if (errorIfDoesNotExist) { 340 return simple_error("Accessible TRUENAME can't be determined for: ~a", pathname); //time !? 341 } else { 342 return NIL; 343 } 344 } 345 return p; 346 } 347 348 ZipEntry entry = ZipCache.getZipEntry(p); 349 if (entry == null) { 350 if (errorIfDoesNotExist) { 351 return simple_error("Accessible TRUENAME can't be determined for: ~a", pathname); //time !? 352 } else { 353 return NIL; 354 } 355 } 356 return p; 357 } 358 359 public boolean isLocalFile() { 360 Pathname p = (Pathname) getRootJar(); 361 if (p.isLocalFile()) { 362 return true; 363 } 364 return super.isLocalFile(); 365 } 366 367 public boolean isArchiveEntry() { 368 return !(getDirectory().equals(NIL) 369 && getName().equals(NIL) 370 && getType().equals(NIL)); 371 } 372 373 public PathnameJar getArchive() { 374 if (!isArchiveEntry()) { 375 return (PathnameJar)simple_error("Pathname already represents an archive."); 376 } 377 PathnameJar archive = new PathnameJar(); 378 archive.copyFrom(this); 379 archive 380 .setDirectory(NIL) 381 .setName(NIL) 382 .setType(NIL); 383 return archive; 304 384 } 305 385 … … 313 393 } 314 394 315 // jarfile: { 395 public InputStream getInputStream() { 396 String entryPath = asEntryPath(); 397 // XXX We only return the bytes of an entry in a JAR 398 if (!isArchiveEntry()) { 399 simple_error("Can only get input stream for an entry in a JAR-PATHNAME.", this); 400 } 401 InputStream result = ZipCache.getEntryAsInputStream(this); 402 if (result == null) { 403 error(new FileError("Failed to get InputStream", this)); 404 } 405 return result; 406 } 407 408 /** List the contents of the directory */ 409 static public LispObject listDirectory(PathnameJar pathname) { 410 String directory = pathname.asEntryPath(); 411 // We should only be listing directories 412 if (pathname.getDirectory() == NIL) { 413 return simple_error("Not a directory in a jar ~a", pathname); 414 } 415 416 // if (pathname.getDevice().cdr() instanceof Cons) { 417 // return error(new FileError("Unimplemented directory listing of JAR within JAR.", pathname)); 418 // } 419 420 if (directory.length() == 0) { 421 directory = "/*"; 422 } else { 423 if (directory.endsWith("/")) { 424 directory = "/" + directory + "*"; 425 } else { 426 directory = "/" + directory + "/*"; 427 } 428 } 429 430 Pathname wildcard = (Pathname)Pathname.create(directory); 431 // String wildcard = new SimpleString(directory); 432 // directories in a a jar aren't marked with a suffixed slash 433 // SimpleString wildcardDirectory = new SimpleString(directory + "/"); 434 435 LispObject result = NIL; 436 //LispObject matches; 437 438 Iterator<Map.Entry<PathnameJar,ZipEntry>> iterator = ZipCache.getEntriesIterator(pathname); 439 while (iterator.hasNext()) { 440 Map.Entry<PathnameJar,ZipEntry> e = iterator.next(); 441 PathnameJar entry = e.getKey(); 442 // PathnameJar jarPath = (PathnameJar)PathnameJar.create(e.getKey()); 443 // ZipEntry entry = e.getValue(); 444 445 // if (entryName.endsWith("/")) { 446 // matches = Symbol.PATHNAME_MATCH_P 447 // .execute(new SimpleString(entryName), wildcardDirectory); 448 // } else { 449 // matches = Symbol.PATHNAME_MATCH_P. 450 // execute(new SimpleString(entryName), wildcard); 451 // } 452 if (!Symbol.PATHNAME_MATCH_P.execute(entry, wildcard).equals(NIL)) { 453 result = result.push(entry); 454 } 455 } 456 return result.nreverse(); 457 } 458 459 @DocString(name="match-wild-jar-pathname", 460 args="wild-jar-pathname", 461 returns="pathnames", 462 doc="Returns the pathnames matching WILD-JAR-PATHNAME which must be both wild and a JAR-PATHNAME") 463 static final Primitive MATCH_WILD_JAR_PATHNAME = new pf_match_wild_jar_pathname(); 464 465 private static class pf_match_wild_jar_pathname extends Primitive { 466 pf_match_wild_jar_pathname() { 467 super(Symbol.MATCH_WILD_JAR_PATHNAME, "wild-jar-pathname"); 468 } 469 @Override 470 public LispObject execute(LispObject arg) { 471 Pathname pathname = coerceToPathname(arg); 472 if (pathname instanceof LogicalPathname) { 473 pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname); 474 } 475 if (!pathname.isJar()) { 476 return new FileError("Not a jar pathname.", pathname); 477 } 478 if (!pathname.isWild()) { 479 return new FileError("Not a wild pathname.", pathname); 480 } 481 if (!((PathnameJar)pathname).getJars().cdr().equals(NIL)) { 482 return simple_error("Unimplemented match on contents of inner jars"); // FIXME 483 } 484 485 PathnameJar jarPathname = new PathnameJar(); 486 jarPathname.copyFrom(pathname); 487 jarPathname 488 .setDirectory(NIL) 489 .setName(NIL) 490 .setType(NIL); 491 PathnameJar wildcard = (PathnameJar)Symbol.TRUENAME.execute(jarPathname); 492 Iterator<Map.Entry<PathnameJar,ZipEntry>> iterator 493 = ZipCache.getEntriesIterator(wildcard); 494 wildcard 495 .setDirectory(pathname.getDirectory()) 496 .setName(pathname.getName()) 497 .setType(pathname.getType()); 498 499 LispObject result = NIL; 500 while (iterator.hasNext()) { 501 Map.Entry<PathnameJar,ZipEntry> e = iterator.next(); 502 PathnameJar entry = e.getKey(); 503 LispObject matches 504 = Symbol.PATHNAME_MATCH_P.execute(entry, wildcard); 505 506 if (!matches.equals(NIL)) { 507 result = new Cons(entry, result); 508 } 509 } 510 511 // FIXME implement recursive jars 512 // if (pathname.getDevice().cdr() instanceof Cons) { 513 // ZipFile outerJar = ZipCache.get((Pathname)pathname.getDevice().car()); 514 // String entryPath = ((Pathname)pathname.getDevice().cdr().car()).getNamestring(); //??? 515 // if (entryPath.startsWith("/")) { 516 // entryPath = entryPath.substring(1); 517 // } 518 // ZipEntry entry = outerJar.getEntry(entryPath); 519 // InputStream inputStream = null; 520 // try { 521 // inputStream = outerJar.getInputStream(entry); 522 // } catch (IOException e) { 523 // return new FileError("Failed to read zip input stream inside zip.", 524 // pathname); 525 // } 526 // ZipInputStream zipInputStream 527 // = new ZipInputStream(inputStream); 528 529 // try { 530 // while ((entry = zipInputStream.getNextEntry()) != null) { 531 // String entryName = "/" + entry.getName(); 532 // LispObject matches = Symbol.PATHNAME_MATCH_P 533 // .execute(new SimpleString(entryName), wildcard); 534 535 // if (!matches.equals(NIL)) { 536 // String namestring = new String(pathname.getNamestring()); 537 // namestring = namestring.substring(0, namestring.lastIndexOf("!/") + 2) 538 // + entry.getName(); 539 // Pathname p = (Pathname)Pathname.create(namestring); 540 // result = new Cons(p, result); 541 // } 542 // } 543 // } catch (IOException e) { 544 // return new FileError("Failed to seek through zip inputstream inside zip.", 545 // pathname); 546 // } 547 // } else { 548 // } 549 return result; 550 } 551 } 552 553 public long getLastModified() { 554 if (!isArchiveEntry()) { 555 ZipCache.Archive archive = ZipCache.getArchive(this); 556 if (archive != null) { 557 return archive.lastModified; 558 } 559 } else { 560 ZipEntry entry = ZipCache.getZipEntry(this); 561 if (entry != null) { 562 return entry.getTime(); 563 } 564 } 565 return -1; // shouldn't be reached 566 } 567 } 568 569 570 // String rootJarNamestring = ((Pathname)rootJar).getNamestring(); 571 // try { 572 // ZipFile jarFile = new ZipFile(rootJarNamestring); 573 // ZipFileInputStream inputStream = null; 574 // while (enclosingJars.car() != NIL) { 575 // LispObject jar = enclosingJars.car(); 576 // String ns = ((Pathname)jar).getNamestring(); 577 // ZipEntry entry = currentZip.getEntry(ns); 578 // if (entry == null) { 579 // return simple_error("Failed to find entry ~a in ~a", ns, pathname); 580 // } 581 // InputStream i = entry.getInputStream(); 582 // ZipInputStream zi = new ZipInputStream(i); 583 // enclosingJars = enclosingJars.cdr(); 584 // } 585 // } catch (IOException e) { 586 // return Pathname.doTruenameExit(result, errorIfDoesNotExist); 587 // } 588 589 590 591 592 593 // truename 594 // jarfile: { 316 595 // // Possibly canonicalize jar file directory 317 596 // LispObject o = pathname.getDevice(); … … 396 675 // } 397 676 398 } 399 400 677 678 679 680 // Pathname.init() 681 // A JAR file 682 683 684 // LispObject jars = NIL; 685 // int i = s.lastIndexOf(jarSeparator, s.length() - jarSeparator.length() - 1); 686 // String jar = null; 687 // if (i == -1) { 688 // jar = s; 689 // } else { 690 // // There can be no more than two jar references and the 691 // // inner one must be a file reference within the outer. 692 // jar = "jar:file:" + s.substring(i + jarSeparator.length()); 693 // s = s.substring("jar:".length(), i + jarSeparator.length()); 694 // Pathname p = (Pathname) Pathname.create(s); 695 // jars = jars.push(p.getDevice().car()); 696 // } 697 // if (jar.startsWith("jar:file:")) { // PathnameJar should handle this part⊠698 // String file 699 // = jar.substring("jar:file:".length(), 700 // jar.length() - jarSeparator.length()); 701 // Pathname jarPathname; 702 // if (file.length() > 0) { 703 // URL url = null; 704 // URI uri = null; 705 // try { 706 // url = new URL("file:" + file); 707 // uri = url.toURI(); 708 // } catch (MalformedURLException e1) { 709 // error(new SimpleError("Failed to create URI from " 710 // + "'" + file + "'" 711 // + ": " + e1.getMessage())); 712 // } catch (URISyntaxException e2) { 713 // error(new SimpleError("Failed to create URI from " 714 // + "'" + file + "'" 715 // + ": " + e2.getMessage())); 716 // } 717 // String path = uri.getPath(); 718 // if (path == null) { 719 // // We allow "jar:file:baz.jar!/" to construct a relative 720 // // path for jar files, so MERGE-PATHNAMES means something. 721 // jarPathname = (Pathname)Pathname.create(uri.getSchemeSpecificPart()); 722 // } else { 723 // jarPathname = (Pathname)Pathname.create((new File(path)).getPath()); 724 // } 725 // } else { 726 // jarPathname = (Pathname)Pathname.create(""); 727 // } 728 // jars = jars.push(jarPathname); 729 // } else { 730 // URL url = null; 731 // try { 732 // url = new URL(jar.substring("jar:".length(), jar.length() - 2)); 733 // Pathname p = (Pathname)Pathname.create(url); 734 // jars = jars.push(p); 735 // } catch (MalformedURLException e) { 736 // error(new LispError("Failed to parse URL " 737 // + "'" + url + "'" 738 // + e.getMessage())); 739 // } 740 // } 741 // jars = jars.nreverse(); 742 // setDevice(jars); 743 // invalidateNamestring(); 744 // return; 745 746 747 // // An entry in a JAR file 748 // final int separatorIndex = s.lastIndexOf(jarSeparator); 749 // if (separatorIndex > 0 && s.startsWith("jar:")) { 750 // return PathnameJar.create(s); 751 // } 752 // final String jarURL = s.substring(0, separatorIndex + jarSeparator.length()); 753 // URL url = null; 754 // try { 755 // url = new URL(jarURL); 756 // } catch (MalformedURLException ex) { 757 // error(new LispError("Failed to parse URL " 758 // + "'" + jarURL + "'" 759 // + ex.getMessage())); 760 // } 761 // Pathname d = (Pathname)Pathname.create(url); 762 // if (getDevice() instanceof Cons) { 763 // LispObject[] jars = d.copyToArray(); 764 // // XXX Is this ever reached? If so, need to append lists 765 // Debug.assertTrue(false); 766 // } else { 767 // setDevice(d.getDevice()); 768 // } 769 // s = "/" + s.substring(separatorIndex + jarSeparator.length()); 770 // Pathname p = (Pathname)Pathname.create("file:" + s); // Use URI escaping rules 771 // setDirectory(p.getDirectory()); 772 // setName(p.getName()); 773 // setType(p.getType()); 774 // setVersion(p.getVersion()); 775 // return; 776 // } 777 778 779 780 -
trunk/abcl/src/org/armedbear/lisp/PathnameURL.java
r15393 r15395 1 1 /* 2 * Pathname Jar.java2 * PathnameURL.java 3 3 * 4 4 * Copyright (C) 2020 @easye … … 36 36 37 37 import java.io.File; 38 import java.io.InputStream; 39 import java.io.IOException; 38 40 import java.net.URL; 39 41 import java.net.URI; … … 42 44 import java.text.MessageFormat; 43 45 44 public class PathnameURL extends Pathname { 46 public class PathnameURL 47 extends Pathname 48 { 45 49 static final Symbol SCHEME = internKeyword("SCHEME"); 46 50 static final Symbol AUTHORITY = internKeyword("AUTHORITY"); … … 147 151 148 152 Pathname p = (Pathname)Pathname.create(path != null ? path : ""); 149 result.setDirectory(p.getDirectory()); 150 result.setName(p.getName()); 151 result.setType(p.getType()); 153 result 154 .setDirectory(p.getDirectory()) 155 .setName(p.getName()) 156 .setType(p.getType()); 152 157 153 158 return result; … … 203 208 204 209 public String getNamestringAsURI() { 205 URL url = makeURL(this); 206 return url.toString(); 210 LispObject schemeProperty = Symbol.GETF.execute(getHost(), SCHEME, NIL); 211 LispObject authorityProperty = Symbol.GETF.execute(getHost(), AUTHORITY, NIL); 212 LispObject queryProperty = Symbol.GETF.execute(getHost(), QUERY, NIL); 213 LispObject fragmentProperty = Symbol.GETF.execute(getHost(), FRAGMENT, NIL); 214 215 String scheme; 216 String authority; 217 if (!schemeProperty.equals(NIL)) { 218 scheme = schemeProperty.getStringValue(); 219 authority = authorityProperty.getStringValue(); 220 } else { 221 scheme = "file"; 222 authority = ""; 223 } 224 225 String directory = getDirectoryNamestring(); 226 String file = Symbol.FILE_NAMESTRING.execute(this).getStringValue(); 227 String path = ""; 228 229 if (!directory.equals("")) { 230 path = directory + file; 231 } else { 232 path = file; 233 } 234 235 String query = null; 236 if (!queryProperty.equals(NIL)) { 237 query = queryProperty.getStringValue(); 238 } 239 240 String fragment = null; 241 if (!fragmentProperty.equals(NIL)) { 242 fragment = fragmentProperty.getStringValue(); 243 } 244 245 try { 246 URI uri = new URI(scheme, authority, path, query, fragment); 247 return uri.toString(); 248 } catch (URISyntaxException e) { 249 simple_error("Failed to construct a URI: ~a", this); 250 return (String)UNREACHED; 251 } 207 252 } 208 253 … … 217 262 218 263 public static LispObject truename(PathnameURL p, boolean errorIfDoesNotExist) { 264 if (p.getHost().equals(NIL) 265 || Symbol.GETF.execute(p.getHost(), PathnameURL.SCHEME, NIL).equals("file")) { 266 return Pathname.truename((Pathname)p, errorIfDoesNotExist); 267 } 268 219 269 if (p.getInputStream() != null) { 220 270 // If there is no type, query or fragment, we check to … … 232 282 return Pathname.doTruenameExit(p, errorIfDoesNotExist); 233 283 } 284 285 public InputStream getInputStream() { 286 InputStream result = null; 287 288 URL url = this.toURL(); 289 try { 290 result = url.openStream(); 291 } catch (IOException e) { 292 Debug.warn("Failed to get InputStream from " 293 + "'" + getNamestring() + "'" 294 + ": " + e); 295 } 296 return result; 297 } 298 299 public long getLastModified() { 300 return getURLConnection().getLastModified(); 301 } 234 302 } 235 303 304 305 306 // From Pathname.init() 307 // A URL 308 // if (isValidURL(s)) { 309 // URL url = null; 310 // try { 311 // url = new URL(s); 312 // } catch (MalformedURLException e) { 313 // Debug.assertTrue(false); 314 // } 315 // String scheme = url.getProtocol(); 316 // if (scheme.equals("file")) { 317 // URI uri = null; 318 // try { 319 // uri = new URI(s); 320 // } catch (URISyntaxException ex) { 321 // error(new SimpleError("Improper URI syntax for " 322 // + "'" + url.toString() + "'" 323 // + ": " + ex.toString())); 324 // } 325 326 // String uriPath = uri.getPath(); 327 // if (null == uriPath) { 328 // // Under Windows, deal with pathnames containing 329 // // devices expressed as "file:z:/foo/path" 330 // uriPath = uri.getSchemeSpecificPart(); 331 // if (uriPath == null || uriPath.equals("")) { 332 // error(new LispError("The URI has no path: " + uri)); 333 // } 334 // } 335 // final File file = new File(uriPath); 336 // String path = file.getPath(); 337 // if (uri.toString().endsWith("/") && !path.endsWith("/")) { 338 // path += "/"; 339 // } 340 // final Pathname p = (Pathname)Pathname.create(path); 341 // this.setHost(p.getHost()); 342 // this.setDevice(p.getDevice()); 343 // this.setDirectory(p.getDirectory()); 344 // this.setName(p.getName()); 345 // this.setType(p.getType()); 346 // this.setVersion(p.getVersion()); 347 // return; 348 // } 349 // Debug.assertTrue(scheme != null); 350 // URI uri = null; 351 // try { 352 // uri = url.toURI().normalize(); 353 // } catch (URISyntaxException e) { 354 // error(new LispError("Couldn't form URI from " 355 // + "'" + url + "'" 356 // + " because: " + e)); 357 // } 358 // String authority = uri.getAuthority(); 359 // if (authority == null) { 360 // authority = url.getAuthority(); 361 // if (authority == null) { 362 // Debug.trace(MessageFormat.format("{0} has a null authority.", url)); 363 // } 364 // } -
trunk/abcl/src/org/armedbear/lisp/Site.java
r15393 r15395 53 53 return; 54 54 } 55 URL url = Lisp.class.getResource("boot.lisp"); 55 URL url = Lisp.class.getResource("boot.lisp"); // what if this was "__loader__._"?!! 56 56 if (url != null) { 57 57 if (!Pathname.isSupportedProtocol(url.getProtocol())) { … … 59 59 } else { 60 60 Pathname p = (Pathname)Pathname.create(url); 61 p.setName(NIL); 62 p.setType(NIL); 63 p.invalidateNamestring(); 64 LISP_HOME = p; 61 p.setName(NIL).setType(NIL); 62 LISP_HOME = p; 65 63 } 66 64 return; 67 65 } 68 Debug.trace("Unable to determine LISP_HOME.");66 simple_error("Unable to determine LISP_HOME."); 69 67 } 70 68 -
trunk/abcl/src/org/armedbear/lisp/Symbol.java
r15099 r15395 3111 3111 public static final Symbol LAYOUT = 3112 3112 PACKAGE_SYS.addExternalSymbol("LAYOUT"); 3113 public static final Symbol MATCH_WILD_JAR_PATHNAME = 3114 PACKAGE_SYS.addExternalSymbol("MATCH-WILD-JAR-PATHNAME"); 3113 3115 public static final Symbol NAME = 3114 3116 PACKAGE_SYS.addExternalSymbol("NAME"); -
trunk/abcl/src/org/armedbear/lisp/Utilities.java
r14176 r15395 91 91 } 92 92 93 public static ZipInputStream getZipInputStream(ZipFile zipfile,94 String entryName) {95 return Utilities.getZipInputStream(zipfile, entryName, false);96 }97 98 public static ZipInputStream getZipInputStream(ZipFile zipfile,99 String entryName,100 boolean errorOnFailure) {101 ZipEntry zipEntry = zipfile.getEntry(entryName);102 ZipInputStream stream = null;103 try {104 stream = new ZipInputStream(zipfile.getInputStream(zipEntry));105 } catch (IOException e) {106 if (errorOnFailure) {107 Lisp.error(new FileError("Failed to open '" + entryName + "' in zipfile '"108 + zipfile + "': " + e.getMessage()));109 }110 return null;111 }112 return stream;113 }114 115 public static InputStream getEntryAsInputStream(ZipInputStream zipInputStream,116 String entryName)117 {118 ZipEntry entry = getEntry(zipInputStream, entryName);119 ByteArrayOutputStream bytes = readEntry(zipInputStream);120 return new ByteArrayInputStream(bytes.toByteArray());121 122 }123 124 public static ByteArrayOutputStream readEntry(ZipInputStream stream) {125 ByteArrayOutputStream result = new ByteArrayOutputStream();126 int count;127 byte buf[] = new byte[1024];128 try {129 while ((count = stream.read(buf, 0, buf.length)) != -1) {130 result.write(buf, 0, count);131 }132 } catch (java.io.IOException e) {133 Debug.trace("Failed to read entry from "134 + stream135 + ": " + e);136 return null;137 }138 return result;139 }140 141 public static ZipEntry getEntry(ZipInputStream zipInputStream, String entryName) {142 return Utilities.getEntry(zipInputStream, entryName, false);143 }144 145 public static ZipEntry getEntry(ZipInputStream zipInputStream,146 String entryName,147 boolean errorOnFailure)148 {149 ZipEntry entry = null;150 do {151 try {152 entry = zipInputStream.getNextEntry();153 } catch (IOException e) {154 if (errorOnFailure) {155 Lisp.error(new FileError("Failed to seek for "156 + "'" + entryName + "'"157 + " in " + zipInputStream.toString()));158 }159 return null;160 }161 } while (entry != null && !entry.getName().equals(entryName));162 if (entry != null) {163 return entry;164 }165 if (errorOnFailure) {166 Lisp.error(new FileError("Failed to find "167 + "'" + entryName + "'"168 + " in " + zipInputStream.toString()));169 }170 return null;171 172 }173 174 public static final boolean checkZipFile(Pathname name) {175 InputStream input = name.getInputStream();176 try {177 byte[] bytes = new byte[4];178 int bytesRead = input.read(bytes);179 return (bytesRead == 4180 && bytes[0] == 0x50181 && bytes[1] == 0x4b182 && bytes[2] == 0x03183 && bytes[3] == 0x04);184 } catch (Throwable t) { // any error probably means 'no'185 return false;186 } finally {187 if (input != null) {188 try {189 input.close();190 }191 catch (IOException e) {} // ignore exceptions192 }193 }194 }195 196 static InputStream getInputStream(ZipFile jarFile, Pathname inner) {197 String entryPath = inner.asEntryPath();198 ZipEntry entry = jarFile.getEntry(entryPath);199 if (entry == null) {200 Debug.trace("Failed to find entry "201 + "'" + entryPath + "'"202 + " in "203 + "'" + jarFile.getName() + "'");204 return null;205 }206 InputStream result = null;207 try {208 result = jarFile.getInputStream(entry);209 } catch (IOException e) {210 Debug.trace("Failed to open InputStream for "211 + "'" + entryPath + "'"212 + " in "213 + "'" + jarFile.getName() + "'");214 return null;215 }216 return result;217 }218 93 219 94 static String escapeFormat(String s) { -
trunk/abcl/src/org/armedbear/lisp/ZipCache.java
r14627 r15395 33 33 package org.armedbear.lisp; 34 34 35 import java.io.ByteArrayInputStream; 36 import java.io.ByteArrayOutputStream; 35 37 import org.armedbear.lisp.util.HttpHead; 36 38 import static org.armedbear.lisp.Lisp.*; … … 38 40 import java.io.File; 39 41 import java.io.IOException; 42 import java.io.InputStream; 40 43 import java.net.JarURLConnection; 41 44 import java.net.MalformedURLException; … … 45 48 import java.text.SimpleDateFormat; 46 49 import java.util.Date; 50 import java.util.Enumeration; 51 import java.util.Iterator; 47 52 import java.util.HashMap; 48 53 import java.util.Locale; 54 import java.util.LinkedHashMap; 55 import java.util.Map; 56 import java.util.Set; 49 57 import java.util.zip.ZipException; 50 58 import java.util.zip.ZipFile; 59 import java.util.zip.ZipEntry; 60 import java.util.zip.ZipInputStream; 51 61 52 62 /** 53 * A cache for all zip/jar file access es by URLthat uses the last63 * A cache for all zip/jar file access by JarPathname that uses the last 54 64 * modified time of the cached resource. 55 *56 * This implementation is synchronized on accesses via get().57 * Usage without multiple threads recompiling code that is then58 * re-loaded should be fine.59 65 * 60 66 * If you run into problems with caching, use … … 64 70 */ 65 71 public class ZipCache { 66 67 // To make this thread safe, we should return a proxy for ZipFile 68 // that keeps track of the number of outstanding references handed 69 // out, not allowing ZipFile.close() to succeed until that count 70 // has been reduced to 1 or the finalizer is executing. 71 // Unfortunately the relatively simple strategy of extending 72 // ZipFile via a CachedZipFile does not work because there is not 73 // a null arg constructor for ZipFile. 74 static class Entry { 75 long lastModified; 76 ZipFile file; 77 } 78 79 static boolean cacheEnabled = true; 80 81 private final static Primitive DISABLE_ZIP_CACHE = new disable_zip_cache(); 82 final static class disable_zip_cache extends Primitive { 83 disable_zip_cache() { 84 super("disable-zip-cache", PACKAGE_SYS, true, "", 85 "Disable all caching of ABCL FASLs and ZIPs."); 72 public static final boolean checkZipFile(Pathname name) { 73 InputStream input = name.getInputStream(); 74 try { 75 byte[] bytes = new byte[4]; 76 int bytesRead = input.read(bytes); 77 return bytesRead == 4 && bytes[0] == 80 && bytes[1] == 75 && bytes[2] == 3 && bytes[3] == 4; 78 } catch (Throwable t) { 79 // any error probably means 'no' 80 return false; 81 } finally { 82 if (input != null) { 83 try { 84 input.close(); 85 } catch (IOException e) { 86 } // ignore exceptions 87 } 88 } 89 } 90 static InputStream getInputStream(ZipFile jarFile, String entryPath) { 91 ZipEntry entry = jarFile.getEntry(entryPath); 92 if (entry == null) { 93 Debug.trace("Failed to find entry " + "'" + entryPath + "'" + " in " + "'" + jarFile.getName() + "'"); 94 return null; 95 } 96 InputStream result = null; 97 try { 98 result = jarFile.getInputStream(entry); 99 } catch (IOException e) { 100 Debug.trace("Failed to open InputStream for " + "'" + entryPath + "'" + " in " + "'" + jarFile.getName() + "'"); 101 return null; 102 } 103 return result; 104 } 105 public static ZipInputStream getZipInputStream(ZipFile zipfile, String entryName) { 106 return ZipCache.getZipInputStream(zipfile, entryName, false); 107 } 108 public static ZipInputStream getZipInputStream(ZipFile zipfile, String entryName, boolean errorOnFailure) { 109 ZipEntry zipEntry = zipfile.getEntry(entryName); 110 ZipInputStream stream = null; 111 try { 112 stream = new ZipInputStream(zipfile.getInputStream(zipEntry)); 113 } catch (IOException e) { 114 if (errorOnFailure) { 115 simple_error("Failed to open '" + entryName + "' in zipfile '" + zipfile + "': " + e.getMessage()); 116 } 117 return null; 118 } 119 return stream; 120 } 121 public static ByteArrayOutputStream readEntry(ZipInputStream stream) { 122 ByteArrayOutputStream result = new ByteArrayOutputStream(); 123 int count; 124 byte[] buf = new byte[1024]; // What's a decent buffer size? 125 try { 126 while ((count = stream.read(buf, 0, buf.length)) != -1) { 127 result.write(buf, 0, count); 128 } 129 } catch (IOException e) { 130 Debug.trace("Failed to read entry from " + stream + ": " + e); 131 return null; 132 } 133 return result; 134 } 135 public static ZipEntry getEntry(ZipInputStream zipInputStream, String entryName) { 136 return ZipCache.getEntry(zipInputStream, entryName, false); 137 } 138 public static ZipEntry getEntry(ZipInputStream zipInputStream, String entryName, boolean errorOnFailure) { 139 ZipEntry entry = null; 140 do { 141 try { 142 entry = zipInputStream.getNextEntry(); 143 } catch (IOException e) { 144 if (errorOnFailure) { 145 Lisp.error(new FileError("Failed to seek for " + "'" + entryName + "'" + " in " + zipInputStream.toString())); 86 146 } 87 @Override 88 public LispObject execute() { 89 ZipCache.disable(); 90 return T; 147 return null; 148 } 149 } while (entry != null && !entry.getName().equals(entryName)); 150 if (entry != null) { 151 return entry; 152 } 153 if (errorOnFailure) { 154 Lisp.error(new FileError("Failed to find " + "'" + entryName + "'" + " in " + zipInputStream.toString())); 155 } 156 return null; 157 } 158 159 public static InputStream getEntryAsInputStream(ZipInputStream zipInputStream, String entryName) { 160 ZipEntry entry = getEntry(zipInputStream, entryName); 161 ByteArrayOutputStream bytes = readEntry(zipInputStream); 162 return new ByteArrayInputStream(bytes.toByteArray()); 163 } 164 165 public static InputStream getEntryAsInputStream(PathnameJar archiveEntry) { 166 InputStream result = null; 167 if (archiveEntry.getDevice().length() > 1) { 168 simple_error("Unimplemented retrieval of InputStream from a nested jar reference"); 169 return (InputStream)UNREACHED; 170 // Pathname inner = (Pathname) getDevice().cdr().car(); 171 // InputStream input = ZipCache.getInputStream(jarFile, inner); 172 // ZipInputStream zipInputStream = new ZipInputStream(input); 173 // result = ZipCache.getEntryAsInputStream(zipInputStream, entryPath); 174 } else { 175 Archive archive = ZipCache.getArchive(archiveEntry); 176 ZipFile zipFile = archive.file; 177 ZipEntry entry = archive.getEntry(archiveEntry); 178 179 try { 180 result = zipFile.getInputStream(entry); 181 } catch (IOException e) { 182 simple_error("Failed to get InputStream for ~a", archiveEntry); 183 } 184 } 185 return result; 186 } 187 188 // To make this thread safe, we should return a proxy for ZipFile 189 // that keeps track of the number of outstanding references handed 190 // out, not allowing ZipFile.close() to succeed until that count 191 // has been reduced to 1 or the finalizer is executing. 192 // Unfortunately the relatively simple strategy of extending 193 // ZipFile via a CachedZipFile does not work because there is not 194 // a null arg constructor for ZipFile. 195 static HashMap<PathnameJar, Archive> cache = new HashMap<PathnameJar, Archive>(); 196 197 static public class Archive { 198 ZipFile file; 199 ZipInputStream inputStream; // Unused, speculative 200 LinkedHashMap<PathnameJar, ZipEntry> entries 201 = new LinkedHashMap<PathnameJar, ZipEntry>(); 202 long lastModified; 203 204 public ZipEntry getEntry(PathnameJar entryPathname) { 205 ZipEntry result = entries.get(entryPathname); 206 if (result != null) { 207 return result; 208 } 209 String entryPath = entryPathname.asEntryPath(); 210 result = file.getEntry(entryPath); 211 212 if (result == null) { 213 return null; 214 } 215 216 // ZipFile.getEntry() will return directories when asked for 217 // files. 218 if (result.isDirectory() 219 && (!entryPathname.getName().equals(NIL) 220 || !entryPathname.getType().equals(NIL))) { 221 return null; 222 } 223 224 entries.put(entryPathname, result); 225 return result; 226 } 227 228 void populateAllEntries(PathnameJar jar) { 229 ZipFile f = file; 230 if (f.size() == entries.size()) { 231 return; 232 } 233 234 Enumeration<? extends ZipEntry> e = f.entries(); 235 while (e.hasMoreElements()) { 236 ZipEntry entry = e.nextElement(); 237 String name = entry.getName(); 238 PathnameJar entryPathname 239 = (PathnameJar)PathnameJar.createEntryFromJar(jar, name); 240 entries.put(entryPathname, entry); 241 } 242 } 243 } 244 245 static boolean cacheEnabled = true; 246 private final static Primitive DISABLE_ZIP_CACHE = new disable_zip_cache(); 247 final static class disable_zip_cache extends Primitive { 248 disable_zip_cache() { 249 super("disable-zip-cache", PACKAGE_SYS, true, "", 250 "Disable all caching of ABCL FASLs and ZIPs."); 251 } 252 @Override 253 public LispObject execute() { 254 ZipCache.disable(); 255 return T; 256 } 257 } 258 static public synchronized void disable() { 259 cacheEnabled = false; 260 cache.clear(); 261 } 262 263 synchronized public static LinkedHashMap<PathnameJar,ZipEntry> getEntries(PathnameJar jar) { 264 Archive archive = getArchive(jar); 265 archive.populateAllEntries(jar); // Very expensive for jars with large number of entries 266 return archive.entries; 267 } 268 269 synchronized public static Iterator<Map.Entry<PathnameJar,ZipEntry>> getEntriesIterator(PathnameJar jar) { 270 LinkedHashMap<PathnameJar,ZipEntry> entries = getEntries(jar); 271 Set<Map.Entry<PathnameJar,ZipEntry>> set = entries.entrySet(); 272 return set.iterator(); 273 } 274 275 276 static ZipEntry getZipEntry(PathnameJar archiveEntry) { 277 PathnameJar archiveJar = archiveEntry.getArchive(); 278 Archive zip = getArchive(archiveJar); 279 ZipEntry entry = zip.getEntry(archiveEntry); 280 return entry; 281 } 282 283 synchronized public static Archive getArchive(PathnameJar jar) { 284 Pathname rootJar = (Pathname) jar.getRootJar(); 285 LispObject innerJars = jar.getJars().cdr(); 286 if (innerJars != NIL) { 287 // FIXME 288 simple_error("Currently unimplemented recursive archive: ~a" , jar); 289 return (Archive)UNREACHED; 290 } 291 292 if (jar.isLocalFile()) { 293 Archive cached = cache.get(jar); 294 if (cached != null) { 295 return cached; 296 } 297 298 File f = rootJar.getFile(); 299 300 try { 301 Archive result = new Archive(); 302 result.file = new ZipFile(f); 303 result.lastModified = f.lastModified(); 304 cache.put(jar, result); 305 306 return result; 307 } catch (ZipException e) { 308 error(new FileError("Failed to construct ZipFile" 309 + " because " + e, 310 Pathname.makePathname(f))); 311 return null; 312 } catch (IOException e) { 313 error(new FileError("Failed to contruct ZipFile" 314 + " because " + e, 315 Pathname.makePathname(f))); 316 return (Archive)UNREACHED; 317 } 318 } else { 319 simple_error("Unimplemented fetch of remote resource."); 320 return (Archive)UNREACHED; 321 // CachedItem e = fetchURL(jarOrEntry, false); 322 // return e; 323 } 324 } 325 326 // Archive archive = cache.getArchive(jar); 327 328 // // Check that the cache entry still accesses a valid ZipFile 329 // if (entry != null) { 330 // // Simplest way to call private ZipFile.ensureOpen() 331 // try { 332 // int size = archive.file.size(); 333 // } catch (IllegalStateException e) { 334 // cache.remove(jar); 335 // entry = null; 336 // } 337 // } 338 339 // if (entry != null) { 340 // if (url.getProtocol().equals("file")) { 341 // File f = new File(url.getPath()); 342 // long current = f.lastModified(); 343 // if (current > entry.lastModified) { 344 // try { 345 // entry.file = new ZipFile(f); 346 // entry.lastModified = current; 347 // } catch (IOException e) { 348 // Debug.trace(e.toString()); // XXX 349 // } 350 // } 351 // } else if (url.getProtocol().equals("http")) { 352 // checkRemoteLastModified(); 353 // } else { 354 // entry = fetchURL(url, false); 355 // zipCache.put(url, entry); 356 // } 357 // } else { 358 // if (url.getProtocol().equals("file")) { 359 // entry = new Entry(); 360 // String path = url.getPath(); 361 362 // if (Utilities.isPlatformWindows) { 363 // String authority = url.getAuthority(); 364 // if (authority != null) { 365 // path = authority + path; 366 // } 367 // } 368 // File f = new File(path); 369 // entry.lastModified = f.lastModified(); 370 // try { 371 // entry.file = new ZipFile(f); 372 // } catch (ZipException e) { 373 // error(new FileError("Failed to get cached ZipFile" 374 // + " because " + e, 375 // Pathname.makePathname(f))); 376 // } catch (IOException e) { 377 // error(new FileError("Failed to get cached ZipFile" 378 // + " because " + e, 379 // Pathname.makePathname(f))); 380 // } 381 // } else { 382 // entry = fetchURL(url, true); 383 // } 384 // zipCache.put(url, entry); 385 // } 386 // return entry.file; 387 // } 388 389 static final SimpleDateFormat ASCTIME 390 = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy", Locale.US); 391 static final SimpleDateFormat RFC_1036 392 = new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US); 393 static final SimpleDateFormat RFC_1123 394 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); 395 396 static void checkRemoteLastModified (PathnameJar jarEntry) { 397 // Unfortunately, the Apple JDK under OS X doesn't do 398 // HTTP HEAD requests, instead refetching the entire 399 // resource, and I assume this is the case in all 400 // Sun-derived JVMs. So, we use a custom HEAD 401 // implementation only looking for Last-Modified 402 // headers, which if we don't find, we give up and 403 // refetch the resource. 404 405 String dateString = null; 406 // try { 407 // dateString = HttpHead.get(url, "Last-Modified"); 408 // } catch (IOException ex) { 409 // Debug.trace(ex); 410 // } 411 // Date date = null; 412 // ParsePosition pos = new ParsePosition(0); 413 414 // if (dateString != null) { 415 // date = RFC_1123.parse(dateString, pos); 416 // if (date == null) { 417 // date = RFC_1036.parse(dateString, pos); 418 // if (date == null) 419 // date = ASCTIME.parse(dateString, pos); 420 // } 421 // } 422 423 // if (date == null || date.getTime() > entry.lastModified) { 424 // entry = fetchURL(url, false); 425 // cache.put(url, entry); 426 // } 427 // if (date == null) { 428 // if (dateString == null) { 429 // Debug.trace("Failed to retrieve request header: " 430 // + url.toString()); 431 // } else { 432 // Debug.trace("Failed to parse Last-Modified date: " + 433 // dateString); 434 // } 435 // } 436 } 437 438 // FIXME recode once local fileaccesses are working 439 static private ZipFile fetchURL(PathnameJar url, boolean useCaches) { 440 ZipFile result = null; 441 URL jarURL = null; 442 try { 443 jarURL = new URL("jar:" + url.getRootJar() + "!/"); 444 } catch (MalformedURLException e) { 445 error(new LispError("Failed to form a jar: URL from " 446 + "'" + url + "'" 447 + " because " + e)); 448 } 449 URLConnection connection = null; 450 try { 451 connection = jarURL.openConnection(); 452 } catch (IOException e) { 453 error(new LispError("Failed to open " 454 + "'" + jarURL + "'" 455 + " with exception " 456 + e)); 457 } 458 if (!(connection instanceof JarURLConnection)) { 459 error(new LispError("Could not get a URLConnection from " 460 + "'" + jarURL + "'")); 461 } 462 JarURLConnection jarURLConnection = (JarURLConnection) connection; 463 jarURLConnection.setUseCaches(useCaches); 464 try { 465 result = jarURLConnection.getJarFile(); 466 } catch (IOException e) { 467 error(new LispError("Failed to fetch URL " 468 + "'" + jarURLConnection + "'" 469 + " because " + e)); 470 } 471 if (cacheEnabled) { 472 Archive archive = new Archive(); 473 archive.file = result; 474 archive.lastModified = jarURLConnection.getLastModified(); 475 cache.put(url, archive); 476 } 477 return result; 478 } 479 480 // ## remove-zip-cache-entry pathname => boolean 481 private static final Primitive REMOVE_ZIP_CACHE_ENTRY = new remove_zip_cache_entry(); 482 private static class remove_zip_cache_entry extends Primitive { 483 remove_zip_cache_entry() { 484 super("remove-zip-cache-entry", PACKAGE_SYS, true, "pathname"); 485 } 486 @Override 487 public LispObject execute(LispObject arg) { 488 Pathname p = coerceToPathname(arg); 489 if (!(p instanceof PathnameJar)) { 490 type_error(arg, Symbol.JAR_PATHNAME); 491 } 492 boolean result = ZipCache.remove((PathnameJar)p); 493 return result ? T : NIL; 494 } 495 } 496 497 synchronized public static boolean remove(PathnameJar p) { 498 Archive archive = cache.get(p.getNamestring()); 499 if (archive != null) { 500 try { 501 if (archive.file != null) { 502 archive.file.close(); 91 503 } 92 } 93 94 static public synchronized void disable() { 95 cacheEnabled = false; 96 zipCache.clear(); 97 } 98 99 static HashMap<URL, Entry> zipCache = new HashMap<URL, Entry>(); 100 101 synchronized public static ZipFile get(Pathname p) { 102 return get(Pathname.makeURL(p)); 103 } 104 105 static final SimpleDateFormat ASCTIME 106 = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy", Locale.US); 107 static final SimpleDateFormat RFC_1036 108 = new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US); 109 static final SimpleDateFormat RFC_1123 110 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); 111 112 113 synchronized public static ZipFile get(final URL url) { 114 if (!cacheEnabled) { 115 if (url.getProtocol().equals("file")) { 116 File f = new File(url.getPath()); 117 try { 118 return new ZipFile(f); 119 } catch (ZipException e) { 120 error(new FileError("Failed to construct ZipFile" 121 + " because " + e, 122 Pathname.makePathname(f))); 123 } catch (IOException e) { 124 error(new FileError("Failed to contruct ZipFile" 125 + " because " + e, 126 Pathname.makePathname(f))); 127 } 128 } else { 129 Entry e = fetchURL(url, false); 130 return e.file; 131 } 132 } 133 134 Entry entry = zipCache.get(url); 135 136 // Check that the cache entry still accesses a valid ZipFile 137 if (entry != null) { 138 // Simplest way to call private ZipFile.ensureOpen() 139 try { 140 int size = entry.file.size(); 141 } catch (IllegalStateException e) { 142 zipCache.remove(url); 143 entry = null; 144 } 504 if (archive.inputStream != null) { 505 archive.inputStream.close(); 145 506 } 146 147 if (entry != null) { 148 if (url.getProtocol().equals("file")) { 149 File f = new File(url.getPath()); 150 long current = f.lastModified(); 151 if (current > entry.lastModified) { 152 try { 153 entry.file = new ZipFile(f); 154 entry.lastModified = current; 155 } catch (IOException e) { 156 Debug.trace(e.toString()); // XXX 157 } 158 } 159 } else if (url.getProtocol().equals("http")) { 160 // Unfortunately, the Apple JDK under OS X doesn't do 161 // HTTP HEAD requests, instead refetching the entire 162 // resource, and I assume this is the case in all 163 // Sun-derived JVMs. So, we use a custom HEAD 164 // implementation only looking for Last-Modified 165 // headers, which if we don't find, we give up and 166 // refetch the resource. 167 String dateString = null; 168 try { 169 dateString = HttpHead.get(url, "Last-Modified"); 170 } catch (IOException ex) { 171 Debug.trace(ex); 172 } 173 Date date = null; 174 ParsePosition pos = new ParsePosition(0); 175 176 if (dateString != null) { 177 date = RFC_1123.parse(dateString, pos); 178 if (date == null) { 179 date = RFC_1036.parse(dateString, pos); 180 if (date == null) 181 date = ASCTIME.parse(dateString, pos); 182 } 183 } 184 185 if (date == null || date.getTime() > entry.lastModified) { 186 entry = fetchURL(url, false); 187 zipCache.put(url, entry); 188 } 189 if (date == null) { 190 if (dateString == null) 191 Debug.trace("Failed to retrieve request header: " 192 + url.toString()); 193 else 194 Debug.trace("Failed to parse Last-Modified date: " + 195 dateString); 196 } 197 198 } else { 199 entry = fetchURL(url, false); 200 zipCache.put(url, entry); 201 } 202 } else { 203 if (url.getProtocol().equals("file")) { 204 entry = new Entry(); 205 String path = url.getPath(); 206 207 if (Utilities.isPlatformWindows) { 208 String authority = url.getAuthority(); 209 if (authority != null) { 210 path = authority + path; 211 } 212 } 213 File f = new File(path); 214 entry.lastModified = f.lastModified(); 215 try { 216 entry.file = new ZipFile(f); 217 } catch (ZipException e) { 218 error(new FileError("Failed to get cached ZipFile" 219 + " because " + e, 220 Pathname.makePathname(f))); 221 } catch (IOException e) { 222 error(new FileError("Failed to get cached ZipFile" 223 + " because " + e, 224 Pathname.makePathname(f))); 225 } 226 } else { 227 entry = fetchURL(url, true); 228 } 229 zipCache.put(url, entry); 230 } 231 return entry.file; 232 } 233 234 static private Entry fetchURL(URL url, boolean cached) { 235 Entry result = new Entry(); 236 URL jarURL = null; 237 try { 238 jarURL = new URL("jar:" + url + "!/"); 239 } catch (MalformedURLException e) { 240 error(new LispError("Failed to form a jar: URL from " 241 + "'" + url + "'" 242 + " because " + e)); 243 } 244 URLConnection connection = null; 245 try { 246 connection = jarURL.openConnection(); 247 } catch (IOException e) { 248 error(new LispError("Failed to open " 249 + "'" + jarURL + "'" 250 + " with exception " 251 + e)); 252 } 253 if (!(connection instanceof JarURLConnection)) { 254 error(new LispError("Could not get a URLConnection from " 255 + "'" + jarURL + "'")); 256 } 257 JarURLConnection jarURLConnection = (JarURLConnection) connection; 258 jarURLConnection.setUseCaches(cached); 259 try { 260 result.file = jarURLConnection.getJarFile(); 261 } catch (IOException e) { 262 error(new LispError("Failed to fetch URL " 263 + "'" + jarURLConnection + "'" 264 + " because " + e)); 265 } 266 result.lastModified = jarURLConnection.getLastModified(); 267 return result; 268 } 269 270 // ## remove-zip-cache-entry pathname => boolean 271 private static final Primitive REMOVE_ZIP_CACHE_ENTRY = new remove_zip_cache_entry(); 272 private static class remove_zip_cache_entry extends Primitive { 273 remove_zip_cache_entry() { 274 super("remove-zip-cache-entry", PACKAGE_SYS, true, "pathname"); 275 } 276 @Override 277 public LispObject execute(LispObject arg) { 278 Pathname p = coerceToPathname(arg); 279 boolean result = ZipCache.remove(p); 280 return result ? T : NIL; 281 } 282 } 283 284 synchronized public static boolean remove(URL url) { 285 Entry entry = zipCache.get(url); 286 if (entry != null) { 287 try { 288 entry.file.close(); 289 } catch (IOException e) {} 290 zipCache.remove(entry); 291 return true; 292 } 293 return false; 294 } 295 296 synchronized public static boolean remove(Pathname p) { 297 URL url = Pathname.makeURL(p); 298 if (url == null) { 299 return false; 300 } 301 return ZipCache.remove(url); 302 } 303 304 synchronized public static boolean remove(File f) { 305 Pathname p = Pathname.makePathname(f); 306 return ZipCache.remove(p); 307 } 507 cache.remove(p); 508 509 return true; 510 } catch (IOException e) { 511 simple_error("failed to close zip cache references", e); 512 } 513 } 514 return false; 515 } 516 517 static public long getLastModified(PathnameJar p) { 518 return 0; // FIXME 519 // JAR cases 520 // 0. JAR from URL 521 // 1. JAR 522 // 2. JAR in JAR 523 // 3. Entry in JAR 524 // 4. Entry in JAR in JAR 525 // String entryPath = p.asEntryPath(); 526 527 // LispObject jars = p.getDevice(); 528 // if (jars.cdr().equals(NIL)) { 529 // if (entryPath.length() == 0) { 530 // LispObject o = jars.car(); 531 // // 0. JAR from URL 532 // // 1. JAR 533 // return ((Pathname)o).getLastModified(); 534 // } else { 535 // // 3. Entry in JAR 536 // final ZipEntry entry 537 // = ZipCache.get((Pathname)getDevice().car()).getEntry(entryPath); 538 // if (entry == null) { 539 // return 0; 540 // } 541 // final long time = entry.getTime(); 542 // if (time == -1) { 543 // return 0; 544 // } 545 // return time; 546 // } 547 // } else { 548 // ZipFile outerJar = ZipCache.get((Pathname)d.car()); 549 // if (entryPath.length() == 0) { 550 // // 4. JAR in JAR 551 // String jarPath = ((Pathname)d.cdr()).asEntryPath(); 552 // final ZipEntry entry = outerJar.getEntry(jarPath); 553 // final long time = entry.getTime(); 554 // if (time == -1) { 555 // return 0; 556 // } 557 // return time; 558 // } else { 559 // // 5. Entry in JAR in JAR 560 // String innerJarPath = ((Pathname)d.cdr()).asEntryPath(); 561 // ZipEntry entry = outerJar.getEntry(entryPath); 562 // ZipInputStream innerJarInputStream 563 // = ZipCache.getZipInputStream(outerJar, innerJarPath); 564 // ZipEntry innerEntry = ZipCache.getEntry(innerJarInputStream, 565 // entryPath); 566 // long time = innerEntry.getTime(); 567 // if (time == -1) { 568 // return 0; 569 // } 570 // return time; 571 // } 572 // } 573 } 574 308 575 } -
trunk/abcl/src/org/armedbear/lisp/delete_file.java
r15393 r15395 50 50 public LispObject execute(LispObject arg) 51 51 { 52 // Don't follow symlinks! We want to delete the symlink itself, not 53 // the linked-to file. 54 Pathname pathname = coerceToPathname(arg); 55 if (arg instanceof Stream) 56 ((Stream)arg)._close(); 57 if (pathname instanceof LogicalPathname) 58 pathname = LogicalPathname.translateLogicalPathname((LogicalPathname)pathname); 59 if (pathname.isWild()) 60 return error(new FileError("Bad place for a wild pathname.", 61 pathname)); 62 final Pathname defaultedPathname = 63 Pathname.mergePathnames(pathname, 64 coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()), 65 NIL); 66 final String namestring = defaultedPathname.getNamestring(); 67 if (namestring == null) 68 return error(new FileError("Pathname has no namestring: " + defaultedPathname.princToString(), 69 defaultedPathname)); 70 final File file = new File(namestring); 71 ZipCache.remove(file); 72 if (file.exists()) { 73 // File exists. 74 for (int i = 0; i < 5; i++) { 75 if (file.delete()) 76 return T; 77 System.gc(); 78 Thread.yield(); 79 } 80 Pathname truename = (Pathname)Pathname.create(file.getAbsolutePath()); 81 StringBuilder sb = new StringBuilder("Unable to delete "); 82 sb.append(file.isDirectory() ? "directory " : "file "); 83 sb.append(truename.princToString()); 84 sb.append('.'); 85 return error(new FileError(sb.toString(), truename)); 86 } else { 87 // File does not exist. 52 // Don't follow symlinks! We want to delete the symlink itself, not 53 // the linked-to file. 54 Pathname pathname = coerceToPathname(arg); 55 if (arg instanceof Stream) 56 ((Stream)arg)._close(); 57 if (pathname instanceof LogicalPathname) 58 pathname = LogicalPathname.translateLogicalPathname((LogicalPathname)pathname); 59 if (pathname.isWild()) 60 return error(new FileError("Bad place for a wild pathname.", 61 pathname)); 62 final Pathname defaultedPathname 63 = (Pathname)Pathname.mergePathnames(pathname, 64 coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()), 65 NIL); 66 final String namestring = defaultedPathname.getNamestring(); 67 if (namestring == null) 68 return error(new FileError("Pathname has no namestring: " + defaultedPathname.princToString(), 69 defaultedPathname)); 70 final File file = new File(namestring); 71 72 if (file.exists()) { 73 // File exists. 74 for (int i = 0; i < 5; i++) { 75 if (file.delete()) 88 76 return T; 77 System.gc(); 78 Thread.yield(); 89 79 } 80 Pathname truename = (Pathname)Pathname.create(file.getAbsolutePath()); 81 StringBuilder sb = new StringBuilder("Unable to delete "); 82 sb.append(file.isDirectory() ? "directory " : "file "); 83 sb.append(truename.princToString()); 84 sb.append('.'); 85 return error(new FileError(sb.toString(), truename)); 86 } else { 87 // File does not exist. 88 return T; 89 } 90 90 } 91 91 -
trunk/abcl/src/org/armedbear/lisp/probe_file.java
r14921 r15395 47 47 private static final class pf_probe_file extends Primitive { 48 48 pf_probe_file() { 49 super( "probe-file", "pathspec");49 super(Symbol.PROBE_FILE, "pathspec"); 50 50 } 51 51 @Override 52 52 public LispObject execute(LispObject arg) 53 53 { 54 return Pathname.truename(arg, false); 54 Pathname p = coerceToPathname(arg); 55 // TODO: refactor Pathname{,Jar,URL}.truename() to be non-static? 56 if (p instanceof PathnameJar) { 57 return PathnameJar.truename((PathnameJar)p, false); 58 } else if (p instanceof PathnameURL) { 59 return PathnameURL.truename((PathnameURL)p, false); 60 } else { 61 return Pathname.truename(p, false); 62 } 55 63 } 56 64 }; … … 63 71 private static class pf_truename extends Primitive { 64 72 pf_truename() { 65 super( "truename", "filespec");73 super(Symbol.TRUENAME, "filespec"); 66 74 } 67 75 @Override 68 76 public LispObject execute(LispObject arg) 69 77 { 70 return Pathname.truename(arg, true); 78 Pathname p = coerceToPathname(arg); 79 // TODO: refactor Pathname{,Jar,URL}.truename() to be non-static? 80 if (p instanceof PathnameJar) { 81 return PathnameJar.truename((PathnameJar)p, true); 82 } else if (p instanceof PathnameURL) { 83 return PathnameURL.truename((PathnameURL)p, true); 84 } else { 85 return Pathname.truename(p, true); 86 } 71 87 } 72 88 }; … … 85 101 { 86 102 Pathname pathname = coerceToPathname(arg); 87 if (pathname.isWild()) 88 error(new FileError("Bad place for a wild pathname.", pathname)); 103 if (pathname.isWild()) { 104 error(new FileError("Cannot probe a wild pathname as a directory.", pathname)); 105 } 89 106 Pathname defaultedPathname = (Pathname)Pathname.MERGE_PATHNAMES.execute(pathname); 90 107 File file = defaultedPathname.getFile(); … … 113 130 Pathname pathname = coerceToPathname(arg); 114 131 if (pathname.isWild()) { 115 error(new FileError("Bad place for a wild pathname.", pathname)); 132 error(new FileError("Fundamentally unable to determine whether a wild pathname is a directory.", 133 pathname)); 116 134 } 117 135 return isDirectory(pathname); … … 127 145 if (wildErrorP != NIL) { 128 146 if (pathname.isWild()) { 129 error(new FileError("Bad place for a wild pathname.", pathname)); 147 error(new FileError("Fundamentally to determine whether a wild pathname is a directory.", 148 pathname)); 130 149 } 131 150 } -
trunk/abcl/src/org/armedbear/lisp/unzip.java
r15391 r15395 73 73 private LispObject unzipToDirectory(Pathname zipPath, Pathname dirPath) { 74 74 if (!zipPath.isAbsolute()) { 75 zipPath = Pathname.mergePathnames(zipPath,75 zipPath = (Pathname)Pathname.mergePathnames(zipPath, 76 76 coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue())); 77 77 } 78 LispObject o = Pathname.truename(zipPath, false);78 LispObject o = Symbol.PROBE_FILE.execute(zipPath); 79 79 if (!(o instanceof Pathname)) { 80 80 return error(new FileError("No file found: " + zipPath, zipPath)); -
trunk/abcl/src/org/armedbear/lisp/zip.java
r14176 r15395 113 113 ZipOutputStream out = 114 114 new ZipOutputStream(new FileOutputStream(zipfileNamestring)); 115 Pathname root = (Pathname) Pathname.truename(coerceToPathname(third));115 Pathname root = (Pathname) Symbol.PROBE_FILE.execute(third); 116 116 String rootPath = root.getDirectoryNamestring(); 117 117 int rootPathLength = rootPath.length(); … … 119 119 LispObject list = second; 120 120 while (list != NIL) { 121 Pathname pathname = (Pathname) Pathname.truename(coerceToPathname(list.car()));121 Pathname pathname = (Pathname) Symbol.PROBE_FILE.execute(list.car()); 122 122 String namestring = pathname.getNamestring(); 123 123 if (namestring == null) { -
trunk/abcl/test/src/org/armedbear/lisp/PathnameJarTest.java
r15394 r15395 10 10 import static org.junit.Assert.*; 11 11 12 public class PathnameJarTest { 13 14 public PathnameJarTest() { 15 } 16 17 @BeforeClass 18 public static void setUpClass() { 19 } 20 21 @AfterClass 22 public static void tearDownClass() { 23 } 24 25 @Before 26 public void setUp() { 27 } 28 29 @After 30 public void tearDown() { 12 public class PathnameJarTest 13 { 14 @Test 15 public void enumerate1() { 16 String s = "jar:jar:file:/a/foo.jar!/b/baz.abcl!/path/c.lisp"; 17 List<String> r = PathnameJar.enumerate(s); 18 assertTrue("3 results", r.size() == 3); 19 String parts[] = { 20 "file:/a/foo.jar", 21 "b/baz.abcl!/", 22 "/path/c.lisp" 23 }; 24 for (int i = 0; i < parts.length; i++) { 25 assertTrue(parts[i], r.get(i).equals(parts[i])); 26 } 31 27 } 32 28 33 29 @Test 34 public void testParseJars1() { 35 String s1 = "jar:jar:file:/a/foo.jar!/b/baz.abcl!/path/c.lisp"; 36 List<String> r1 = PathnameJar.enumerate(s1); 37 assertTrue(r1.size() == 3); 38 String s10 = "file:/a/foo.jar"; 39 assertTrue(s10.equals(r1.get(0))); 40 String s11 = "/b/baz.abcl!/"; 41 assertTrue(s11.equals(r1.get(1))); 42 String s12 = "/path/c.lisp"; 43 assertTrue(s12.equals(r1.get(2))); 30 public void enumerate2() { 31 String s = "jar:jar:file:/a/foo.jar!/b/baz.abcl!/"; 32 List<String> r = PathnameJar.enumerate(s); 33 assertTrue("2 results", r.size() == 2); 34 String parts[] = { 35 "file:/a/foo.jar", 36 "b/baz.abcl!/" 37 }; 38 for (int i = 0; i < parts.length; i++) { 39 assertTrue(parts[i], r.get(i).equals(parts[i])); 40 } 44 41 } 45 42 46 43 @Test 47 public void testParseJars10() { 48 String s1 = "jar:jar:file:/a/foo.jar!/b/baz.abcl!/"; 49 List<String> r1 = PathnameJar.enumerate(s1); 50 assertTrue(r1.size() == 2); 51 String s10 = "file:/a/foo.jar"; 52 assertTrue(s10.equals(r1.get(0))); 53 String s11 = "/b/baz.abcl!/"; 54 assertTrue(s11.equals(r1.get(1))); 44 public void enumerate3() { 45 String s = "jar:jar:https://example.com/a/foo.jar!/b/baz.abcl!/path/c.lisp"; 46 List<String> r = PathnameJar.enumerate(s); 47 assertTrue("3 results", r.size() == 3); 48 String parts[] = { 49 "https://example.com/a/foo.jar", 50 "b/baz.abcl!/", 51 "/path/c.lisp" 52 }; 53 for (int i = 0; i < parts.length; i++) { 54 assertTrue(parts[i], r.get(i).equals(parts[i])); 55 } 55 56 } 56 57 57 58 @Test 58 public void testParseJars2() { 59 String s1 = "jar:jar:https://example.com/a/foo.jar!/b/baz.abcl!/path/c.lisp"; 60 List<String> r1 = PathnameJar.enumerate(s1); 61 assertTrue(r1.size() == 3); 62 String s10 = "https://example.com/a/foo.jar"; 63 assertTrue(s10.equals(r1.get(0))); 64 String s11 = "/b/baz.abcl!/"; 65 assertTrue(s11.equals(r1.get(1))); 66 String s12 = "/path/c.lisp"; 67 assertTrue(s12.equals(r1.get(2))); 59 public void enumerate4() { 60 String s = "jar:jar:jar:file:/a/foo.jar!/b/baz.abcl!/log4j.jar!/MF/manifest.mf"; 61 List<String> r = PathnameJar.enumerate(s); 62 assertTrue("4 results", r.size() == 4); 63 String parts[] = { 64 "file:/a/foo.jar", 65 "b/baz.abcl!/", 66 "log4j.jar!/", 67 "/MF/manifest.mf" 68 }; 69 for (int i = 0; i < parts.length; i++) { 70 assertTrue(parts[i], r.get(i).equals(parts[i])); 71 } 68 72 } 69 73 … … 72 76 String namestrings[] = { 73 77 "jar:file:foo.jar!/", 78 "jar:file:/foo.jar!/", 74 79 "jar:jar:file:foo.jar!/baz.abcl!/", 75 "jar:jar:file:foo.jar!/baz.abcl!/__loader__._" 80 "jar:jar:file:/foo.jar!/baz.abcl!/", 81 "jar:jar:file:foo.jar!/baz.abcl!/__loader__._", 82 "jar:jar:file:/foo.jar!/baz.abcl!/__loader__._", 83 "jar:jar:jar:file:a/b/foo.jar!/c/baz.zip!/log4j.jar!/MF/manifest.mf", 84 "jar:jar:jar:file:/a/b/foo.jar!/c/baz.zip!/log4j.jar!/MF/manifest.mf" 76 85 }; 77 86 -
trunk/abcl/test/src/org/armedbear/lisp/PathnameTest.java
r15393 r15395 123 123 assertTrue(parsedNamestring.equals(namestring)); 124 124 } 125 126 @Test 127 public void equality() { 128 Pathname p1 = (Pathname)Pathname.create("file://tmp/"); 129 Pathname p2 = (Pathname)Pathname.create("file://tmp/"); 130 boolean result = p1.equals(p2); 131 assertTrue("Java equals() for Pathname", result); 132 133 PathnameJar p3 = (PathnameJar)Pathname.create("jar:file:/abcl.jar!/tmp/"); 134 PathnameJar p4 = (PathnameJar)Pathname.create("jar:file:/abcl.jar!/tmp/"); 135 result = p3.equals(p4); 136 assertTrue("Java equals() for PathnameJar", result); 137 } 125 138 }
Note: See TracChangeset
for help on using the changeset viewer.