Changeset 12441


Ignore:
Timestamp:
02/10/10 16:22:21 (11 years ago)
Author:
Mark Evenson
Message:

Return of the ZipCache? now using last modified time.

Treat jars as zips in ZipCache? which maintains an cache of all
ZipFiles? accessed via Pathname jars (which should be the entire system
as Load now uses Pathname). ZipCache? currently does not invalidate
entries for any non-file resources due to deficiencies in the JVM that
need to be corrected on a per-protocol basis. For instance, for HTTP
we need an implementation that uses HTTP HEAD requests to get the
Last-Modified header as opposed to re-fetching the entire resource as
the JVM URLConnection does.

SYS:REMOVE-ZIP-CACHE-ENTRY implements a way to invalidate ZipCache?
entries from Lisp. Used it in COMPILE-FILE to successfully recompile
FASLs under Windows.

Rewrite remaining Pathname Primtives in the informative stack trace style.

Implement Debug.warn() which can be shut off with SYS::*DEBUG-WARN*.
The intent here is to have a way to warn about Java side events which
having potentially worrying side-effects during development which is
by default not visible to end users (although it can be).

Removed unused EXT:LAST-MODIFIED in favor of existing ANSI FILE-WRITE-DATE.

Location:
trunk/abcl/src/org/armedbear/lisp
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/src/org/armedbear/lisp/Autoload.java

    r12422 r12441  
    645645        autoload(PACKAGE_SYS, "puthash", "HashTableFunctions");
    646646        autoload(PACKAGE_SYS, "puthash", "HashTableFunctions");
     647        autoload(PACKAGE_SYS, "remove-zip-cache-entry", "ZipCache");
    647648        autoload(PACKAGE_SYS, "set-function-info-value", "function_info");
    648649        autoload(PACKAGE_SYS, "set-generic-function-argument-precedence-order","StandardGenericFunction", true);
  • trunk/abcl/src/org/armedbear/lisp/Debug.java

    r12288 r12441  
    3434package org.armedbear.lisp;
    3535
     36import static org.armedbear.lisp.Lisp.*;
     37
    3638public final class Debug
    3739{
     40   
    3841    public static final void assertTrue(boolean b)
    3942    {
     
    6164        t.printStackTrace();
    6265    }
     66
     67    public static final Symbol _DEBUG_WARN_
     68        = exportSpecial("*DEBUG-WARN*", PACKAGE_SYS, NIL);
     69
     70    public static void setDebugWarnings(boolean flag) {
     71        if (flag) {
     72            _DEBUG_WARN_.setSymbolValue(T);
     73        } else {
     74            _DEBUG_WARN_.setSymbolValue(NIL);
     75        }
     76    }
     77   
     78    public static final void warn(String s) {
     79        if (_DEBUG_WARN_.getSymbolValue() != null) {
     80            trace(s);
     81        }
     82    }
    6383}
  • trunk/abcl/src/org/armedbear/lisp/Pathname.java

    r12435 r12441  
    4444import java.net.URLConnection;
    4545import java.net.URLDecoder;
     46import java.util.HashMap;
    4647import java.util.StringTokenizer;
    4748import java.util.jar.JarEntry;
    4849import java.util.jar.JarFile;
    4950import java.util.zip.ZipEntry;
     51import java.util.zip.ZipFile;
    5052import java.util.zip.ZipInputStream;
     53import java.util.zip.ZipException;
    5154
    5255public class Pathname extends LispObject {
     
    16411644            // 3.  JAR with Entry
    16421645            // 4.  JAR in JAR with Entry
    1643             JarFile jarFile = getJarFile(jars.car());
     1646            ZipFile jarFile = ZipCache.get(jars.car());
    16441647            String entryPath = pathname.asEntryPath();
    16451648            if (jarFile != null) {
     
    17081711    }
    17091712
    1710     /** Make a JarURL from a generic URL reference. */
    1711     private static URL makeJarURL(String url) {
    1712         String jarURL = "jar:" + url + "!/";
     1713    protected static URL makeURL(LispObject device) {
    17131714        URL result = null;
    17141715        try {
    1715             result = new URL(jarURL);
    1716         } catch (MalformedURLException ex) {
    1717             // XXX
    1718             Debug.trace("Could not form jar URL from  "
    1719               + "'" + jarURL + "'"
    1720               + " because " + ex);
    1721         }
    1722         return result;
    1723     }
    1724  
    1725     private static JarFile getJarFile(LispObject device) {
    1726         URL url = null;
    17271716        if (device instanceof SimpleString) {
    1728             url = makeJarURL(((SimpleString) device).getStringValue());
     1717            result = new URL(((SimpleString)device).getStringValue());
    17291718        } else {
    1730             url = makeJarURL((Pathname) device);
    1731         }
    1732         if (url == null) {
    1733             return null;
    1734         }
    1735         URLConnection connection;
    1736         try {
    1737             connection = url.openConnection();
    1738         } catch (IOException ex) {
    1739             Debug.trace("Failed to open "
    1740               + "'" + url + "'");
    1741             return null;
    1742         }
    1743         if (!(connection instanceof JarURLConnection)) {
    1744             // XXX
    1745             Debug.trace("Could not get a URLConnection from " + url);
    1746             return null;
    1747         }
    1748         JarURLConnection jarURLConnection = (JarURLConnection) connection;
    1749         // XXX implement custom protocol handler that actual does the necessary caching
    1750         connection.setUseCaches(false);
    1751         JarFile result;
    1752         try {
    1753             result = jarURLConnection.getJarFile();
    1754         } catch (IOException ex) {
    1755             Debug.trace("Could not get a JarURLConnection from "
    1756               + "'" + jarURLConnection + "'");
    1757             return null;
     1719        // XXX ensure that we have cannonical path.
     1720            Pathname p = (Pathname)device;
     1721            result = new URL("file:" + p.getNamestring());
     1722        }
     1723        } catch (MalformedURLException e) {
     1724            Debug.trace("Could not form URL from " + device);
    17581725        }
    17591726        return result;
     
    17661733            // XXX We only return the bytes of an entry in a JAR
    17671734            Debug.assertTrue(entryPath != null);
    1768             JarFile jarFile = Pathname.getJarFile(device.car());
     1735            ZipFile jarFile = ZipCache.get(device.car());
    17691736            Debug.assertTrue(jarFile != null);
    17701737            // Is this a JAR within a JAR?
     
    18021769        return result;
    18031770    }
    1804 
    1805     // ### last-modified pathname => time-in-milliseconds
    1806     public static final Primitive LAST_MODIFIED
    1807         = new Primitive("LAST-MODIFIED", PACKAGE_EXT, true, "pathname",
    1808                         "If PATHNAME exists, returns the last modified time in miliseconds since the UNIX epoch.") 
    1809             {
    1810                 @Override
    1811                 public LispObject execute(LispObject arg) {
    1812                     final Pathname p = coerceToPathname(arg);
    1813                     if (p.isWild()) {
    1814                         error(new FileError("Bad place for a wild pathname.", p));
    1815                     }
    1816                     long time = p.getLastModified();
    1817                     return LispInteger.getInstance(time);
    1818                 }
    1819             };
    18201771
    18211772    /** @return Time in milliseconds since the UNIX epoch at which the
     
    18401791                if (o instanceof SimpleString) {
    18411792                    // 0. JAR from URL
    1842                     URL u = makeJarURL(o.getStringValue());
    1843                     URLConnection c = null;
    1844                     try {
    1845                       c = u.openConnection();
    1846                     } catch(IOException e) {
    1847                       Debug.trace("Failed to open Connection for URL "
    1848                                   + "'" + u + "'");
    1849                       return 0;
    1850                     }
    1851                     c.getLastModified();
     1793                    // URL u = makeJarURL(o.getStringValue());
     1794                    // XXX unimplemented
     1795                    Debug.assertTrue(false);
     1796                    // URLConnection c = null;
     1797                    // try {
     1798                    //   c = u.openConnection();
     1799                    // } catch(IOException e) {
     1800                    //   Debug.trace("Failed to open Connection for URL "
     1801                    //               + "'" + u + "'");
     1802                    //   return 0;
     1803                    // }
     1804                    // c.getLastModified();
    18521805                } else  { 
    18531806                    // 1. JAR
     
    18561809            } else {
    18571810                // 3. Entry in JAR
    1858                 final JarEntry entry = getJarFile(device.car()).getJarEntry(entryPath);
     1811                final ZipEntry entry
     1812                    = ZipCache.get(device.car()).getEntry(entryPath);
    18591813                if (entry == null) {
    18601814                    return 0;
     
    18671821            }
    18681822        } else {
    1869             JarFile outerJar = getJarFile(d.car());
     1823            ZipFile outerJar = ZipCache.get(d.car());
    18701824            if (entryPath.length() == 0) {
    18711825                // 4.  JAR in JAR
    18721826                String jarPath = ((Pathname)d.cdr()).asEntryPath();
    1873                 final JarEntry entry = outerJar.getJarEntry(jarPath);
     1827                final ZipEntry entry = outerJar.getEntry(jarPath);
    18741828                final long time = entry.getTime();
    18751829                if (time == -1) {
     
    18951849    }
    18961850
    1897     // ### mkdir
    1898     private static final Primitive MKDIR =
    1899       new Primitive("mkdir", PACKAGE_SYS, false) {
    1900 
    1901           @Override
    1902           public LispObject execute(LispObject arg) {
    1903               final Pathname pathname = coerceToPathname(arg);
    1904               if (pathname.isWild()) {
    1905                   error(new FileError("Bad place for a wild pathname.", pathname));
    1906               }
    1907               Pathname defaultedPathname =
     1851    // ### mkdir pathname
     1852    private static final Primitive MKDIR = new mkdir();
     1853    private static class mkdir extends Primitive {
     1854        mkdir() {
     1855            super("mkdir", PACKAGE_SYS, false, "pathname");
     1856        }
     1857
     1858        @Override
     1859        public LispObject execute(LispObject arg) {
     1860            final Pathname pathname = coerceToPathname(arg);
     1861            if (pathname.isWild()) {
     1862                error(new FileError("Bad place for a wild pathname.", pathname));
     1863            }
     1864            Pathname defaultedPathname =
    19081865                mergePathnames(pathname,
    1909                 coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()),
    1910                 NIL);
    1911               File file = Utilities.getFile(defaultedPathname);
    1912               return file.mkdir() ? T : NIL;
    1913           }
    1914       };
     1866                               coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()),
     1867                               NIL);
     1868            File file = Utilities.getFile(defaultedPathname);
     1869            return file.mkdir() ? T : NIL;
     1870        }
     1871    }
     1872
    19151873    // ### rename-file filespec new-name => defaulted-new-name, old-truename, new-truename
    1916     public static final Primitive RENAME_FILE =
    1917       new Primitive("rename-file", "filespec new-name") {
    1918 
    1919           @Override
    1920           public LispObject execute(LispObject first, LispObject second) {
    1921               final Pathname original = (Pathname) truename(first, true);
    1922               final String originalNamestring = original.getNamestring();
    1923               Pathname newName = coerceToPathname(second);
    1924               if (newName.isWild()) {
    1925                   error(new FileError("Bad place for a wild pathname.", newName));
    1926               }
    1927               newName = mergePathnames(newName, original, NIL);
    1928               final String newNamestring;
    1929               if (newName instanceof LogicalPathname) {
    1930                   newNamestring = LogicalPathname.translateLogicalPathname((LogicalPathname) newName).getNamestring();
    1931               } else {
    1932                   newNamestring = newName.getNamestring();
    1933               }
    1934               if (originalNamestring != null && newNamestring != null) {
    1935                   final File source = new File(originalNamestring);
    1936                   final File destination = new File(newNamestring);
    1937                   if (Utilities.isPlatformWindows) {
    1938                       if (destination.isFile()) {
    1939                           destination.delete();
    1940                       }
    1941                   }
    1942                   if (source.renameTo(destination)) // Success!
    1943                   {
    1944                       return LispThread.currentThread().setValues(newName, original,
    1945                         truename(newName, true));
    1946                   }
    1947               }
    1948               return error(new FileError("Unable to rename "
    1949                 + original.writeToString()
    1950                 + " to " + newName.writeToString()
    1951                 + "."));
    1952           }
    1953       };
     1874    private static final Primitive RENAME_FILE = new rename_file();
     1875    private static class rename_file extends Primitive {
     1876        rename_file() {
     1877            super("rename-file", "filespec new-name");
     1878        }
     1879        @Override
     1880        public LispObject execute(LispObject first, LispObject second) {
     1881            final Pathname original = (Pathname) truename(first, true);
     1882            final String originalNamestring = original.getNamestring();
     1883            Pathname newName = coerceToPathname(second);
     1884            if (newName.isWild()) {
     1885                error(new FileError("Bad place for a wild pathname.", newName));
     1886            }
     1887            newName = mergePathnames(newName, original, NIL);
     1888            final String newNamestring;
     1889            if (newName instanceof LogicalPathname) {
     1890                newNamestring = LogicalPathname.translateLogicalPathname((LogicalPathname) newName).getNamestring();
     1891            } else {
     1892                newNamestring = newName.getNamestring();
     1893            }
     1894            if (originalNamestring != null && newNamestring != null) {
     1895                final File source = new File(originalNamestring);
     1896                final File destination = new File(newNamestring);
     1897                if (Utilities.isPlatformWindows) {
     1898                    if (destination.isFile()) {
     1899                        destination.delete();
     1900                    }
     1901                }
     1902                if (source.renameTo(destination)) { // Success!
     1903                        return LispThread.currentThread().setValues(newName, original,
     1904                                                                    truename(newName, true));
     1905                }
     1906            }
     1907            return error(new FileError("Unable to rename "
     1908                                       + original.writeToString()
     1909                                       + " to " + newName.writeToString()
     1910                                       + "."));
     1911        }
     1912    }
     1913
    19541914    // ### file-namestring pathname => namestring
    1955     private static final Primitive FILE_NAMESTRING =
    1956       new Primitive("file-namestring", "pathname") {
    1957 
    1958           @Override
    1959           public LispObject execute(LispObject arg) {
    1960               Pathname p = coerceToPathname(arg);
    1961               StringBuilder sb = new StringBuilder();
    1962               if (p.name instanceof AbstractString) {
    1963                   sb.append(p.name.getStringValue());
    1964               } else if (p.name == Keyword.WILD) {
    1965                   sb.append('*');
    1966               } else {
    1967                   return NIL;
    1968               }
    1969               if (p.type instanceof AbstractString) {
    1970                   sb.append('.');
    1971                   sb.append(p.type.getStringValue());
    1972               } else if (p.type == Keyword.WILD) {
    1973                   sb.append(".*");
    1974               }
    1975               return new SimpleString(sb);
    1976           }
    1977       };
     1915    private static final Primitive FILE_NAMESTRING = new file_namestring();
     1916    private static class file_namestring extends Primitive {
     1917        file_namestring() {
     1918            super("file-namestring", "pathname");
     1919        }
     1920        @Override
     1921        public LispObject execute(LispObject arg) {
     1922            Pathname p = coerceToPathname(arg);
     1923            StringBuilder sb = new StringBuilder();
     1924            if (p.name instanceof AbstractString) {
     1925                sb.append(p.name.getStringValue());
     1926            } else if (p.name == Keyword.WILD) {
     1927                sb.append('*');
     1928            } else {
     1929                return NIL;
     1930            }
     1931            if (p.type instanceof AbstractString) {
     1932                sb.append('.');
     1933                sb.append(p.type.getStringValue());
     1934            } else if (p.type == Keyword.WILD) {
     1935                sb.append(".*");
     1936            }
     1937            return new SimpleString(sb);
     1938        }
     1939    }
     1940
    19781941    // ### host-namestring pathname => namestring
    1979     private static final Primitive HOST_NAMESTRING =
    1980       new Primitive("host-namestring", "pathname") {
    1981 
    1982           @Override
    1983           public LispObject execute(LispObject arg) {
    1984               return coerceToPathname(arg).host;
    1985           }
    1986       };
     1942    private static final Primitive HOST_NAMESTRING = new host_namestring();
     1943    private static class host_namestring extends Primitive {
     1944        host_namestring() {
     1945            super("host-namestring", "pathname");
     1946        }
     1947        @Override
     1948        public LispObject execute(LispObject arg) {
     1949            return coerceToPathname(arg).host;
     1950        }
     1951    }
    19871952   
    19881953    public String toString() {
  • trunk/abcl/src/org/armedbear/lisp/Utilities.java

    r12422 r12441  
    230230    }
    231231
    232     static InputStream getInputStream(JarFile jarFile, Pathname inner) {
     232    static InputStream getInputStream(ZipFile jarFile, Pathname inner) {
    233233        String entryPath = inner.asEntryPath();
    234234        ZipEntry entry = jarFile.getEntry(entryPath);
  • trunk/abcl/src/org/armedbear/lisp/compile-file.lisp

    r12330 r12441  
    568568               do (write-line line out))))
    569569        (delete-file temp-file)
     570  (remove-zip-cache-entry output-file) ;; Necessary under windows
    570571        (rename-file temp-file2 output-file)
    571572
Note: See TracChangeset for help on using the changeset viewer.