|
From: <ls...@us...> - 2007-08-31 20:45:20
|
Revision: 3445
http://jnode.svn.sourceforge.net/jnode/?rev=3445&view=rev
Author: lsantha
Date: 2007-08-31 13:45:14 -0700 (Fri, 31 Aug 2007)
Log Message:
-----------
Openjdk integration.
Modified Paths:
--------------
trunk/core/src/openjdk/vm/java/io/NativeFileSystem.java
Added Paths:
-----------
trunk/core/src/openjdk/java/java/io/ExpiringCache.java
trunk/core/src/openjdk/java/java/io/UnixFileSystem.java
trunk/core/src/openjdk/vm/java/io/NativeUnixFileSystem.java
Added: trunk/core/src/openjdk/java/java/io/ExpiringCache.java
===================================================================
--- trunk/core/src/openjdk/java/java/io/ExpiringCache.java (rev 0)
+++ trunk/core/src/openjdk/java/java/io/ExpiringCache.java 2007-08-31 20:45:14 UTC (rev 3445)
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#)ExpiringCache.java 1.12 07/05/05
+ */
+
+package java.io;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.Set;
+
+class ExpiringCache {
+ private long millisUntilExpiration;
+ private Map map;
+ // Clear out old entries every few queries
+ private int queryCount;
+ private int queryOverflow = 300;
+ private int MAX_ENTRIES = 200;
+
+ static class Entry {
+ private long timestamp;
+ private String val;
+
+ Entry(long timestamp, String val) {
+ this.timestamp = timestamp;
+ this.val = val;
+ }
+
+ long timestamp() { return timestamp; }
+ void setTimestamp(long timestamp) { this.timestamp = timestamp; }
+
+ String val() { return val; }
+ void setVal(String val) { this.val = val; }
+ }
+
+ ExpiringCache() {
+ this(30000);
+ }
+
+ ExpiringCache(long millisUntilExpiration) {
+ this.millisUntilExpiration = millisUntilExpiration;
+ map = new LinkedHashMap() {
+ protected boolean removeEldestEntry(Map.Entry eldest) {
+ return size() > MAX_ENTRIES;
+ }
+ };
+ }
+
+ synchronized String get(String key) {
+ if (++queryCount >= queryOverflow) {
+ cleanup();
+ }
+ Entry entry = entryFor(key);
+ if (entry != null) {
+ return entry.val();
+ }
+ return null;
+ }
+
+ synchronized void put(String key, String val) {
+ if (++queryCount >= queryOverflow) {
+ cleanup();
+ }
+ Entry entry = entryFor(key);
+ if (entry != null) {
+ entry.setTimestamp(System.currentTimeMillis());
+ entry.setVal(val);
+ } else {
+ map.put(key, new Entry(System.currentTimeMillis(), val));
+ }
+ }
+
+ synchronized void clear() {
+ map.clear();
+ }
+
+ private Entry entryFor(String key) {
+ Entry entry = (Entry) map.get(key);
+ if (entry != null) {
+ long delta = System.currentTimeMillis() - entry.timestamp();
+ if (delta < 0 || delta >= millisUntilExpiration) {
+ map.remove(key);
+ entry = null;
+ }
+ }
+ return entry;
+ }
+
+ private void cleanup() {
+ Set keySet = map.keySet();
+ // Avoid ConcurrentModificationExceptions
+ String[] keys = new String[keySet.size()];
+ int i = 0;
+ for (Iterator iter = keySet.iterator(); iter.hasNext(); ) {
+ String key = (String) iter.next();
+ keys[i++] = key;
+ }
+ for (int j = 0; j < keys.length; j++) {
+ entryFor(keys[j]);
+ }
+ queryCount = 0;
+ }
+}
Added: trunk/core/src/openjdk/java/java/io/UnixFileSystem.java
===================================================================
--- trunk/core/src/openjdk/java/java/io/UnixFileSystem.java (rev 0)
+++ trunk/core/src/openjdk/java/java/io/UnixFileSystem.java 2007-08-31 20:45:14 UTC (rev 3445)
@@ -0,0 +1,323 @@
+/*
+ * Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.io;
+
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+
+
+class UnixFileSystem extends FileSystem {
+
+ private final char slash;
+ private final char colon;
+ private final String javaHome;
+
+ public UnixFileSystem() {
+ slash =
+ ((String) AccessController.doPrivileged(
+ new GetPropertyAction("file.separator"))).charAt(0);
+ colon =
+ ((String) AccessController.doPrivileged(
+ new GetPropertyAction("path.separator"))).charAt(0);
+ javaHome =
+ (String) AccessController.doPrivileged(
+ new GetPropertyAction("java.home"));
+ }
+
+
+ /* -- Normalization and construction -- */
+
+ public char getSeparator() {
+ return slash;
+ }
+
+ public char getPathSeparator() {
+ return colon;
+ }
+
+ /* A normal Unix pathname contains no duplicate slashes and does not end
+ with a slash. It may be the empty string. */
+
+ /* Normalize the given pathname, whose length is len, starting at the given
+ offset; everything before this offset is already normal. */
+ private String normalize(String pathname, int len, int off) {
+ if (len == 0) return pathname;
+ int n = len;
+ while ((n > 0) && (pathname.charAt(n - 1) == '/')) n--;
+ if (n == 0) return "/";
+ StringBuffer sb = new StringBuffer(pathname.length());
+ if (off > 0) sb.append(pathname.substring(0, off));
+ char prevChar = 0;
+ for (int i = off; i < n; i++) {
+ char c = pathname.charAt(i);
+ if ((prevChar == '/') && (c == '/')) continue;
+ sb.append(c);
+ prevChar = c;
+ }
+ return sb.toString();
+ }
+
+ /* Check that the given pathname is normal. If not, invoke the real
+ normalizer on the part of the pathname that requires normalization.
+ This way we iterate through the whole pathname string only once. */
+ public String normalize(String pathname) {
+ int n = pathname.length();
+ char prevChar = 0;
+ for (int i = 0; i < n; i++) {
+ char c = pathname.charAt(i);
+ if ((prevChar == '/') && (c == '/'))
+ return normalize(pathname, n, i - 1);
+ prevChar = c;
+ }
+ if (prevChar == '/') return normalize(pathname, n, n - 1);
+ return pathname;
+ }
+
+ public int prefixLength(String pathname) {
+ if (pathname.length() == 0) return 0;
+ return (pathname.charAt(0) == '/') ? 1 : 0;
+ }
+
+ public String resolve(String parent, String child) {
+ if (child.equals("")) return parent;
+ if (child.charAt(0) == '/') {
+ if (parent.equals("/")) return child;
+ return parent + child;
+ }
+ if (parent.equals("/")) return parent + child;
+ return parent + '/' + child;
+ }
+
+ public String getDefaultParent() {
+ return "/";
+ }
+
+ public String fromURIPath(String path) {
+ String p = path;
+ if (p.endsWith("/") && (p.length() > 1)) {
+ // "/foo/" --> "/foo", but "/" --> "/"
+ p = p.substring(0, p.length() - 1);
+ }
+ return p;
+ }
+
+
+ /* -- Path operations -- */
+
+ public boolean isAbsolute(File f) {
+ return (f.getPrefixLength() != 0);
+ }
+
+ public String resolve(File f) {
+ if (isAbsolute(f)) return f.getPath();
+ return resolve(System.getProperty("user.dir"), f.getPath());
+ }
+
+ // Caches for canonicalization results to improve startup performance.
+ // The first cache handles repeated canonicalizations of the same path
+ // name. The prefix cache handles repeated canonicalizations within the
+ // same directory, and must not create results differing from the true
+ // canonicalization algorithm in canonicalize_md.c. For this reason the
+ // prefix cache is conservative and is not used for complex path names.
+ private ExpiringCache cache = new ExpiringCache();
+ // On Unix symlinks can jump anywhere in the file system, so we only
+ // treat prefixes in java.home as trusted and cacheable in the
+ // canonicalization algorithm
+ private ExpiringCache javaHomePrefixCache = new ExpiringCache();
+
+ public String canonicalize(String path) throws IOException {
+ if (!useCanonCaches) {
+ return canonicalize0(path);
+ } else {
+ String res = cache.get(path);
+ if (res == null) {
+ String dir = null;
+ String resDir = null;
+ if (useCanonPrefixCache) {
+ // Note that this can cause symlinks that should
+ // be resolved to a destination directory to be
+ // resolved to the directory they're contained in
+ dir = parentOrNull(path);
+ if (dir != null) {
+ resDir = javaHomePrefixCache.get(dir);
+ if (resDir != null) {
+ // Hit only in prefix cache; full path is canonical
+ String filename = path.substring(1 + dir.length());
+ res = resDir + slash + filename;
+ cache.put(dir + slash + filename, res);
+ }
+ }
+ }
+ if (res == null) {
+ res = canonicalize0(path);
+ cache.put(path, res);
+ if (useCanonPrefixCache &&
+ dir != null && dir.startsWith(javaHome)) {
+ resDir = parentOrNull(res);
+ // Note that we don't allow a resolved symlink
+ // to elsewhere in java.home to pollute the
+ // prefix cache (java.home prefix cache could
+ // just as easily be a set at this point)
+ if (resDir != null && resDir.equals(dir)) {
+ File f = new File(res);
+ if (f.exists() && !f.isDirectory()) {
+ javaHomePrefixCache.put(dir, resDir);
+ }
+ }
+ }
+ }
+ }
+ assert canonicalize0(path).equals(res) || path.startsWith(javaHome);
+ return res;
+ }
+ }
+ private native String canonicalize0(String path) throws IOException;
+ // Best-effort attempt to get parent of this path; used for
+ // optimization of filename canonicalization. This must return null for
+ // any cases where the code in canonicalize_md.c would throw an
+ // exception or otherwise deal with non-simple pathnames like handling
+ // of "." and "..". It may conservatively return null in other
+ // situations as well. Returning null will cause the underlying
+ // (expensive) canonicalization routine to be called.
+ static String parentOrNull(String path) {
+ if (path == null) return null;
+ char sep = File.separatorChar;
+ int last = path.length() - 1;
+ int idx = last;
+ int adjacentDots = 0;
+ int nonDotCount = 0;
+ while (idx > 0) {
+ char c = path.charAt(idx);
+ if (c == '.') {
+ if (++adjacentDots >= 2) {
+ // Punt on pathnames containing . and ..
+ return null;
+ }
+ } else if (c == sep) {
+ if (adjacentDots == 1 && nonDotCount == 0) {
+ // Punt on pathnames containing . and ..
+ return null;
+ }
+ if (idx == 0 ||
+ idx >= last - 1 ||
+ path.charAt(idx - 1) == sep) {
+ // Punt on pathnames containing adjacent slashes
+ // toward the end
+ return null;
+ }
+ return path.substring(0, idx);
+ } else {
+ ++nonDotCount;
+ adjacentDots = 0;
+ }
+ --idx;
+ }
+ return null;
+ }
+
+ /* -- Attribute accessors -- */
+
+ public native int getBooleanAttributes0(File f);
+
+ public int getBooleanAttributes(File f) {
+ int rv = getBooleanAttributes0(f);
+ String name = f.getName();
+ boolean hidden = (name.length() > 0) && (name.charAt(0) == '.');
+ return rv | (hidden ? BA_HIDDEN : 0);
+ }
+
+ public native boolean checkAccess(File f, int access);
+ public native long getLastModifiedTime(File f);
+ public native long getLength(File f);
+ public native boolean setPermission(File f, int access, boolean enable, boolean owneronly);
+
+ /* -- File operations -- */
+
+ public native boolean createFileExclusively(String path)
+ throws IOException;
+ public boolean delete(File f) {
+ // Keep canonicalization caches in sync after file deletion
+ // and renaming operations. Could be more clever than this
+ // (i.e., only remove/update affected entries) but probably
+ // not worth it since these entries expire after 30 seconds
+ // anyway.
+ cache.clear();
+ javaHomePrefixCache.clear();
+ return delete0(f);
+ }
+ private native boolean delete0(File f);
+ public native String[] list(File f);
+ public native boolean createDirectory(File f);
+ public boolean rename(File f1, File f2) {
+ // Keep canonicalization caches in sync after file deletion
+ // and renaming operations. Could be more clever than this
+ // (i.e., only remove/update affected entries) but probably
+ // not worth it since these entries expire after 30 seconds
+ // anyway.
+ cache.clear();
+ javaHomePrefixCache.clear();
+ return rename0(f1, f2);
+ }
+ private native boolean rename0(File f1, File f2);
+ public native boolean setLastModifiedTime(File f, long time);
+ public native boolean setReadOnly(File f);
+
+
+ /* -- Filesystem interface -- */
+
+ public File[] listRoots() {
+ try {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkRead("/");
+ }
+ return new File[] { new File("/") };
+ } catch (SecurityException x) {
+ return new File[0];
+ }
+ }
+
+ /* -- Disk usage -- */
+ public native long getSpace(File f, int t);
+
+ /* -- Basic infrastructure -- */
+
+ public int compare(File f1, File f2) {
+ return f1.getPath().compareTo(f2.getPath());
+ }
+
+ public int hashCode(File f) {
+ return f.getPath().hashCode() ^ 1234321;
+ }
+
+
+ private static native void initIDs();
+
+ static {
+ initIDs();
+ }
+
+}
Modified: trunk/core/src/openjdk/vm/java/io/NativeFileSystem.java
===================================================================
--- trunk/core/src/openjdk/vm/java/io/NativeFileSystem.java 2007-08-31 20:36:35 UTC (rev 3444)
+++ trunk/core/src/openjdk/vm/java/io/NativeFileSystem.java 2007-08-31 20:45:14 UTC (rev 3445)
@@ -13,6 +13,7 @@
*/
public static Object getFileSystem()
{
- return new JNodeFileSystem();
+ //return new JNodeFileSystem();
+ return new UnixFileSystem();
}
}
Added: trunk/core/src/openjdk/vm/java/io/NativeUnixFileSystem.java
===================================================================
--- trunk/core/src/openjdk/vm/java/io/NativeUnixFileSystem.java (rev 0)
+++ trunk/core/src/openjdk/vm/java/io/NativeUnixFileSystem.java 2007-08-31 20:45:14 UTC (rev 3445)
@@ -0,0 +1,120 @@
+/*
+ * $Id$
+ */
+package java.io;
+
+/**
+ * @author Levente S\xE1ntha
+ */
+public class NativeUnixFileSystem {
+ private static String canonicalize0(UnixFileSystem ufs, String path) throws IOException {
+ // note : we expect that the File class from OpenJDK give an absolute path
+ return VMFile.toCanonicalForm(path);
+ }
+
+ private static int getBooleanAttributes0(UnixFileSystem ufs, File f) {
+ int attributes = 0;
+
+ attributes |= (VMFile.exists(f.getPath()) ? FileSystem.BA_EXISTS : 0);
+ attributes |= (VMFile.isFile(f.getPath()) ? FileSystem.BA_REGULAR : 0);
+ attributes |= (VMFile.isDirectory(f.getPath()) ? FileSystem.BA_DIRECTORY : 0);
+ attributes |= (VMFile.isHidden(f.getPath()) ? FileSystem.BA_HIDDEN : 0);
+
+ return attributes;
+ }
+
+ private static boolean checkAccess(UnixFileSystem ufs, File f, int access) {
+ boolean canAccess;
+ if (! VMFile.exists(f.getPath()))
+ return false;
+
+ switch(access)
+ {
+ case FileSystem.ACCESS_READ: canAccess = VMFile.canRead(f.getPath()); break;
+ case FileSystem.ACCESS_WRITE:
+ if (VMFile.isDirectory(f.getPath()))
+ canAccess = VMFile.canWriteDirectory(f);
+ else
+ canAccess = VMFile.canWrite(f.getPath());
+
+ break;
+ case FileSystem.ACCESS_EXECUTE: canAccess = VMFile.canExecute(f.getPath()); break;
+ default: throw new IllegalArgumentException("invalid access : "+access);
+ }
+ return canAccess;
+ }
+
+ private static long getLastModifiedTime(UnixFileSystem ufs, File f) {
+ return VMFile.lastModified(f.getPath());
+ }
+
+ private static long getLength(UnixFileSystem ufs, File f) {
+ return VMFile.length(f.getPath());
+ }
+
+ private static boolean setPermission(UnixFileSystem ufs, File f, int access, boolean enable, boolean owneronly) {
+ boolean success = false;
+ switch(access)
+ {
+ case FileSystem.ACCESS_READ: success = VMFile.setReadable(f.getPath(), enable, owneronly); break;
+ case FileSystem.ACCESS_WRITE: success = VMFile.setWritable(f.getPath(), enable, owneronly); break;
+ case FileSystem.ACCESS_EXECUTE: success = VMFile.setExecutable(f.getPath(), enable, owneronly); break;
+ }
+ return success;
+ }
+
+ private static boolean createFileExclusively(UnixFileSystem ufs, String path) {
+ try {
+ return VMFile.create(path);
+ } catch(IOException ioe){
+ return false;
+ }
+ }
+
+ private static boolean delete0(UnixFileSystem ufs, File f) {
+ return VMFile.delete(f.getPath());
+ }
+
+ private static String[] list(UnixFileSystem ufs, File f) {
+ if (!f.exists() || !f.isDirectory())
+ return null;
+
+ // Get the list of files
+ return VMFile.list(f.getPath());
+ }
+
+ private static boolean createDirectory(UnixFileSystem ufs, File f) {
+ return VMFile.mkdir(f.getPath());
+ }
+
+ private static boolean rename0(UnixFileSystem ufs, File f1, File f2) {
+ return VMFile.renameTo(f1.getPath(), f2.getPath());
+ }
+
+ private static boolean setLastModifiedTime(UnixFileSystem ufs, File f, long time) {
+ return VMFile.setLastModified(f.getPath(), time);
+ }
+
+ private static boolean setReadOnly(UnixFileSystem ufs, File f) {
+ // Test for existence.
+ if (! VMFile.exists(f.getPath()))
+ return false;
+
+ return VMFile.setReadOnly(f.getPath());
+ }
+
+ private static long getSpace(UnixFileSystem ufs, File f, int t) {
+ long space = 0L;
+ switch(t)
+ {
+ case FileSystem.SPACE_TOTAL: space = VMFile.getTotalSpace(f.getPath()); break; //TODO
+ case FileSystem.SPACE_FREE: space = VMFile.getFreeSpace(f.getPath()); break; //TODO
+ case FileSystem.SPACE_USABLE: space = VMFile.getUsableSpace(f.getPath()); break; //TODO
+ }
+ return space;
+ }
+
+ private static void initIDs() {
+
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|