source: trunk/abcl/src/org/armedbear/lisp/Utilities.java @ 12594

Last change on this file since 12594 was 12441, checked in by Mark Evenson, 15 years ago

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.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.7 KB
Line 
1/*
2 * Utilities.java
3 *
4 * Copyright (C) 2003-2007 Peter Graves
5 * $Id: Utilities.java 12441 2010-02-10 16:22:21Z mevenson $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import static org.armedbear.lisp.Lisp.*;
37
38import java.io.ByteArrayInputStream;
39import java.io.ByteArrayOutputStream;
40import java.io.File;
41import java.io.IOException;
42import java.io.InputStream;
43import java.util.jar.JarFile;
44import java.util.zip.ZipEntry;
45import java.util.zip.ZipFile;
46import java.util.zip.ZipInputStream;
47
48public final class Utilities
49{
50    public static final boolean isPlatformUnix;
51    public static final boolean isPlatformWindows;
52
53    static {
54        String osName = System.getProperty("os.name");
55        isPlatformUnix = osName.startsWith("Linux") ||
56            osName.startsWith("Mac OS X") || osName.startsWith("Darwin") ||
57            osName.startsWith("Solaris") ||
58            osName.startsWith("SunOS") || osName.startsWith("AIX") ||
59            osName.startsWith("FreeBSD") || osName.startsWith("OpenBSD") ||
60            osName.startsWith("NetBSD");
61        isPlatformWindows = osName.startsWith("Windows");
62    }
63
64    public static boolean isFilenameAbsolute(String filename)
65    {
66        final int length = filename.length();
67        if (length > 0) {
68            char c0 = filename.charAt(0);
69            if (c0 == '\\' || c0 == '/')
70                return true;
71            if (length > 2) {
72                if (isPlatformWindows) {
73                    // Check for drive letter.
74                    char c1 = filename.charAt(1);
75                    if (c1 == ':') {
76                        if (c0 >= 'a' && c0 <= 'z')
77                            return true;
78                        if (c0 >= 'A' && c0 <= 'Z')
79                            return true;
80                    }
81                } else {
82                    // Unix.
83                    if (filename.equals("~") || filename.startsWith("~/"))
84                        return true;
85                }
86            }
87        }
88        return false;
89    }
90
91    public static File getFile(Pathname pathname)
92    {
93        return getFile(pathname,
94                       coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()));
95    }
96
97    public static File getFile(Pathname pathname, Pathname defaultPathname)
98
99    {
100        Pathname merged =
101            Pathname.mergePathnames(pathname, defaultPathname, NIL);
102        String namestring = merged.getNamestring();
103        if (namestring != null)
104            return new File(namestring);
105        error(new FileError("Pathname has no namestring: " + merged.writeToString(),
106                             merged));
107        // Not reached.
108        return null;
109    }
110
111    public static Pathname getDirectoryPathname(File file)
112
113    {
114        try {
115            String namestring = file.getCanonicalPath();
116            if (namestring != null && namestring.length() > 0) {
117                if (namestring.charAt(namestring.length() - 1) != File.separatorChar)
118                    namestring = namestring.concat(File.separator);
119            }
120            return new Pathname(namestring);
121        }
122        catch (IOException e) {
123            error(new LispError(e.getMessage()));
124            // Not reached.
125            return null;
126        }
127    }
128
129    public static ZipInputStream getZipInputStream(ZipFile zipfile,
130                                                   String entryName) {
131        return Utilities.getZipInputStream(zipfile, entryName, false);
132    }
133
134  public static ZipInputStream getZipInputStream(ZipFile zipfile,
135                                                 String entryName,
136                                                 boolean errorOnFailure) {
137    ZipEntry zipEntry = zipfile.getEntry(entryName);
138    ZipInputStream stream = null;
139    try {
140      stream = new ZipInputStream(zipfile.getInputStream(zipEntry));
141    } catch (IOException e) {
142      if (errorOnFailure) {
143          Lisp.error(new FileError("Failed to open '" + entryName + "' in zipfile '"
144                                   + zipfile + "': " + e.getMessage()));
145      }
146      return null;
147    }
148    return stream;
149  }
150
151  public static InputStream getEntryAsInputStream(ZipInputStream zipInputStream,
152                                                    String entryName)
153    {
154        ZipEntry entry = getEntry(zipInputStream, entryName);
155        ByteArrayOutputStream bytes = readEntry(zipInputStream);
156        return new ByteArrayInputStream(bytes.toByteArray());
157
158    }
159
160    public static ByteArrayOutputStream readEntry(ZipInputStream stream) {
161        ByteArrayOutputStream result = new ByteArrayOutputStream();
162        int count;
163        byte buf[] = new byte[1024];
164        try {
165            while ((count = stream.read(buf, 0, buf.length)) != -1) {
166                result.write(buf, 0, count);
167            }
168        } catch (java.io.IOException e) {
169            Debug.trace("Failed to read entry from " 
170                        + stream
171                        + ": " + e);
172            return null;
173        }
174        return result;
175    }
176
177    public static ZipEntry getEntry(ZipInputStream zipInputStream, String entryName) {
178        return Utilities.getEntry(zipInputStream, entryName, false);
179    }
180
181  public static ZipEntry getEntry(ZipInputStream zipInputStream,
182                                  String entryName,
183                                  boolean errorOnFailure)
184  {
185    ZipEntry entry = null;
186    do {
187      try {
188        entry = zipInputStream.getNextEntry();
189      } catch (IOException e) {
190        if (errorOnFailure) {
191          Lisp.error(new FileError("Failed to seek for "
192            + "'" + entryName + "'"
193            + " in " + zipInputStream.toString()));
194        }
195        return null;
196      }
197    } while (entry != null && !entry.getName().equals(entryName));
198    if (entry != null) {
199      return entry;
200    }
201    if (errorOnFailure) {
202      Lisp.error(new FileError("Failed to find "
203        + "'" + entryName + "'"
204        + " in " + zipInputStream.toString()));
205    }
206    return null;
207
208  }
209   
210    public static final boolean checkZipFile(Pathname name) {
211        InputStream input = name.getInputStream();
212        try {
213            byte[] bytes = new byte[4];
214            int bytesRead = input.read(bytes);
215            return (bytesRead == 4
216                    && bytes[0] == 0x50
217                    && bytes[1] == 0x4b
218                    && bytes[2] == 0x03
219                    && bytes[3] == 0x04);
220        } catch (Throwable t) { // any error probably means 'no'
221            return false;
222        } finally {
223            if (input != null) {
224                try {
225                    input.close();
226                }
227                catch (IOException e) {} // ignore exceptions
228            }
229        }
230    }
231
232    static InputStream getInputStream(ZipFile jarFile, Pathname inner) {
233        String entryPath = inner.asEntryPath();
234        ZipEntry entry = jarFile.getEntry(entryPath);
235        if (entry == null) {
236            Debug.trace("Failed to find entry "
237                    + "'" + entryPath + "'"
238                    + " in " 
239                    + "'" + jarFile.getName() + "'");
240            return null;
241        }
242        InputStream result = null;
243        try {
244            result = jarFile.getInputStream(entry);
245        } catch (IOException e) {
246            Debug.trace("Failed to open InputStream for "
247              + "'" + entryPath + "'"
248              + " in "
249              + "'" + jarFile.getName() + "'");
250            return null;
251        }
252        return result;
253    }
254
255
256
257}
Note: See TracBrowser for help on using the repository browser.