Changeset 12503


Ignore:
Timestamp:
02/22/10 16:32:45 (12 years ago)
Author:
Mark Evenson
Message:

DIRECTORY now works for jar pathnames.

The semantics for listing directories are a little bit different from
DIRECTORY on filesystems because directory entries in jar files
*always* have a trailing '/'.

Location:
trunk/abcl
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/CHANGES

    r12501 r12503  
    1515
    1616* [svn r12422] Jar pathname support extensively re-worked and tested
    17   so that LOAD, PROBE-FILE, TRUENAME, and WRITE-FILE-DATE all work
    18   both for local and remote jar pathnames of the form
     17  so that LOAD, PROBE-FILE, TRUENAME, DIRECTORY, and WRITE-FILE-DATE
     18  all work both for local and remote jar pathnames of the form
    1919  "jar:URL!/JAR-ENTRY".
    2020
     
    2424  jar.
    2525       
    26   NB: jar pathnames do *not* currently work as an argument to OPEN or
    27   DIRECTORY.
     26  NB: jar pathnames do *not* currently work as an argument to OPEN.
    2827
    2928  SYS:UNZIP implemented to unpack ZIP files. 
  • trunk/abcl/doc/design/pathnames/abcl-jar-url.text

    r12433 r12503  
    44Mark Evenson
    55Created: 09 JAN 2010
    6 Modified: 08 FEB 2010
     6Modified: 22 FEB 2010
    77
    88Notes towards sketching an implementation of "jar:" references to be
     
    5454------
    5555
    56 As of svn r12431, all the above goals have been implemented and tested
     56As of svn r12501, all the above goals have been implemented and tested
    5757*except* for:
    58 
    59 5.  DIRECTORY working within JAR files
    6058
    61597.  Make jar pathnames work as a valid argument for OPEN.
  • trunk/abcl/src/org/armedbear/lisp/Pathname.java

    r12486 r12503  
    3939import java.io.InputStream;
    4040import java.io.FileInputStream;
    41 import java.net.JarURLConnection;
    4241import java.net.MalformedURLException;
    4342import java.net.URL;
    44 import java.net.URLConnection;
    4543import java.net.URLDecoder;
    46 import java.util.HashMap;
     44import java.util.Enumeration;
    4745import java.util.StringTokenizer;
    48 import java.util.jar.JarEntry;
    49 import java.util.jar.JarFile;
    5046import java.util.zip.ZipEntry;
    5147import java.util.zip.ZipFile;
    5248import java.util.zip.ZipInputStream;
    53 import java.util.zip.ZipException;
    5449
    5550public class Pathname extends LispObject {
     
    12471242        }
    12481243    }
     1244
     1245    private static Function pathname_match_p;
     1246    private static LispObject matchesWildcard(LispObject pathname, LispObject wildcard) {
     1247        if (pathname_match_p == null) {
     1248            pathname_match_p
     1249              = (Function) PACKAGE_SYS.findAccessibleSymbol("PATHNAME-MATCH-P")
     1250                .getSymbolFunction();
     1251            if (pathname_match_p == null) {
     1252                Debug.assertTrue(false);
     1253            }
     1254        }
     1255        return pathname_match_p.execute(pathname, wildcard);
     1256    }
     1257
    12491258    // ### list-directory directory
    12501259    private static final Primitive LIST_DIRECTORY = new pf_list_directory();
     
    12591268                pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname);
    12601269            }
     1270
     1271            LispObject result = NIL;
    12611272            if (pathname.isJar()) {
    1262                 return error(new FileError("Unimplemented directory listing of JAR files.", pathname));
    1263             }
    1264             LispObject result = NIL;
     1273                String directory = pathname.asEntryPath();
     1274                Debug.assertTrue(directory != null);  // We should only be listing directories
     1275
     1276                if (pathname.device.cdr() instanceof Cons) {
     1277                    return error(new FileError("Unimplemented directory listing of JAR within JAR.", pathname));
     1278                }
     1279
     1280                if (directory.length() == 0) {
     1281                    directory = "/*";
     1282                } else {
     1283                    if (directory.endsWith("/")) {
     1284                        directory = "/" + directory + "*";
     1285                    } else {
     1286                        directory = "/" + directory + "/*";
     1287                    }
     1288                }
     1289                SimpleString wildcard = new SimpleString(directory);
     1290                SimpleString wildcardDirectory = new SimpleString(directory + "/");
     1291
     1292                ZipFile jar = ZipCache.get(pathname.device.car());
     1293                LispObject matches;
     1294                for (Enumeration<? extends ZipEntry> entries = jar.entries();
     1295                     entries.hasMoreElements();) {
     1296                    ZipEntry entry = entries.nextElement();
     1297                    String entryName = "/" + entry.getName();
     1298
     1299                    if (entryName.endsWith("/")) {
     1300                        matches = matchesWildcard(new SimpleString(entryName),
     1301                                                  wildcardDirectory);
     1302                    } else {
     1303                        matches = matchesWildcard(new SimpleString(entryName),
     1304                                                  wildcard);
     1305                    }
     1306                    if (!matches.equals(NIL)) {
     1307                        String namestring = new String(pathname.getNamestring());
     1308                        namestring = namestring.substring(0, namestring.lastIndexOf("!/") + 2)
     1309                                 + entry.getName();
     1310                        Pathname p = new Pathname(namestring);
     1311                        result = new Cons(p, result);
     1312                    }
     1313                }
     1314                return result;
     1315            }
     1316
    12651317            String s = pathname.getNamestring();
    12661318            if (s != null) {
     
    12871339                        Debug.trace(e);
    12881340                    }
     1341                }
     1342            }
     1343            return result;
     1344        }
     1345    }
     1346
     1347    // ### match-wild-jar-pathname wild-jar-pathname
     1348    private static final Primitive LIST_JAR_DIRECTORY = new pf_match_wild_jar_pathname();
     1349    private static class pf_match_wild_jar_pathname extends Primitive {
     1350        pf_match_wild_jar_pathname() {
     1351            super("match-wild-jar-pathname", PACKAGE_SYS, false, "wild-jar-pathname");
     1352        }
     1353        @Override
     1354        public LispObject execute(LispObject arg) {
     1355            Pathname pathname = coerceToPathname(arg);
     1356            if (pathname instanceof LogicalPathname) {
     1357                pathname = LogicalPathname.translateLogicalPathname((LogicalPathname) pathname);
     1358            }
     1359            if (!pathname.isJar()) {
     1360                return new FileError("Not a jar pathname.", pathname);
     1361            }
     1362            if (!pathname.isWild()) {
     1363                return new FileError("Not a wild pathname.", pathname);
     1364            }
     1365            Pathname jarPathname = new Pathname(pathname);
     1366            jarPathname.directory = NIL;
     1367            jarPathname.name = NIL;
     1368            jarPathname.type = NIL;
     1369            jarPathname.invalidateNamestring();
     1370            // will propagate an appropiate Lisp error if jarPathname
     1371            // doesn't exist.
     1372            LispObject jarTruename = truename(jarPathname, true);
     1373
     1374            LispObject result = NIL;
     1375            String wild = "/" + pathname.asEntryPath();
     1376
     1377            if (pathname.device.cdr() instanceof Cons) {
     1378                return error(new FileError("Unimplemented directory listing of JAR within JAR.", pathname));
     1379            }
     1380           
     1381            final SimpleString wildcard = new SimpleString(wild);
     1382
     1383            ZipFile jar = ZipCache.get(pathname.device.car());
     1384
     1385            for (Enumeration<? extends ZipEntry> entries = jar.entries(); entries.hasMoreElements();) {
     1386                ZipEntry entry = entries.nextElement();
     1387                String entryName = "/" + entry.getName();
     1388               
     1389                LispObject matches = matchesWildcard(new SimpleString(entryName), wildcard);
     1390
     1391                if (!matches.equals(NIL)) {
     1392                    String namestring = new String(pathname.getNamestring());
     1393                    namestring = namestring.substring(0, namestring.lastIndexOf("!/") + 2)
     1394                        + entry.getName();
     1395                    Pathname p = new Pathname(namestring);
     1396                    result = new Cons(p, result);
    12891397                }
    12901398            }
  • trunk/abcl/src/org/armedbear/lisp/directory.lisp

    r12502 r12503  
    5454   (entries (list-directory newpath)))
    5555    (if (not wild)
    56   entries (mapcan (lambda (entry)
    57                           (let* ((pathname (pathname entry))
    58                                  (directory (pathname-directory pathname))
    59                                  (rest-wild (cdr wild)))
    60                             (unless (pathname-name pathname)
    61             (when (pathname-match-p (first (last directory)) (if (eql (car wild) :wild) "*" (car wild)))
    62         (when rest-wild
    63           (setf directory (nconc directory rest-wild)))
    64           (list-directories-with-wildcards
    65          (make-pathname :directory directory
    66             :defaults newpath))))))
    67                         entries))))
     56  entries
     57        (mapcan (lambda (entry)
     58                  (let* ((pathname (pathname entry))
     59                         (directory (pathname-directory pathname))
     60                         (rest-wild (cdr wild)))
     61                    (unless (pathname-name pathname)
     62                      (when (pathname-match-p (first (last directory))
     63                                              (if (eql (car wild) :wild) "*" (car wild)))
     64                        (when rest-wild
     65                          (setf directory (nconc directory rest-wild)))
     66                        (list-directories-with-wildcards
     67                         (make-pathname :directory directory
     68                                        :defaults newpath))))))
     69                entries))))
    6870
    6971
     
    7476    (if (or (position #\* (namestring pathname))
    7577      (wild-pathname-p pathname))
    76         (let ((namestring (directory-namestring pathname)))
    77           (when (and namestring (> (length namestring) 0))
    78             (when (featurep :windows)
    79               (let ((device (pathname-device pathname)))
    80                 (when device
    81                   (setq namestring (concatenate 'string device ":" namestring)))))
    82             (let ((entries (list-directories-with-wildcards namestring))
    83                   (matching-entries ()))
    84               (dolist (entry entries)
    85                 (cond ((file-directory-p entry)
    86                        (when (pathname-match-p (file-namestring (pathname-as-file entry)) (file-namestring pathname))
    87                          (push entry matching-entries)))
    88                       ((pathname-match-p (file-namestring entry) (file-namestring pathname))
    89                        (push entry matching-entries))))
    90               matching-entries)))
     78        (if (pathname-jar-p pathname)
     79            (match-wild-jar-pathname pathname)
     80            (let ((namestring (directory-namestring pathname)))
     81              (when (and namestring (> (length namestring) 0))
     82                (when (featurep :windows)
     83                  (let ((device (pathname-device pathname)))
     84                    (when device
     85                      (setq namestring (concatenate 'string device ":" namestring)))))
     86                (let ((entries (list-directories-with-wildcards namestring))
     87                      (matching-entries ()))
     88                  (dolist (entry entries)
     89                    (cond ((file-directory-p entry)
     90                           (when (pathname-match-p (file-namestring (pathname-as-file entry)) (file-namestring pathname))
     91                             (push entry matching-entries)))
     92                          ((pathname-match-p (file-namestring entry) (file-namestring pathname))
     93                           (push entry matching-entries))))
     94                  matching-entries))))
    9195        ;; Not wild.
    9296        (let ((truename (probe-file pathname)))
Note: See TracChangeset for help on using the changeset viewer.