001: /***** BEGIN LICENSE BLOCK *****
002: * Version: CPL 1.0/GPL 2.0/LGPL 2.1
003: *
004: * The contents of this file are subject to the Common Public
005: * License Version 1.0 (the "License"); you may not use this file
006: * except in compliance with the License. You may obtain a copy of
007: * the License at http://www.eclipse.org/legal/cpl-v10.html
008: *
009: * Software distributed under the License is distributed on an "AS
010: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
011: * implied. See the License for the specific language governing
012: * rights and limitations under the License.
013: *
014: * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
015: * Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
016: * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
017: * Copyright (C) 2004 Joey Gibson <joey@joeygibson.com>
018: * Copyright (C) 2004 Charles O Nutter <headius@headius.com>
019: * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
020: *
021: * Alternatively, the contents of this file may be used under the terms of
022: * either of the GNU General Public License Version 2 or later (the "GPL"),
023: * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
024: * in which case the provisions of the GPL or the LGPL are applicable instead
025: * of those above. If you wish to allow use of your version of this file only
026: * under the terms of either the GPL or the LGPL, and not to allow others to
027: * use your version of this file under the terms of the CPL, indicate your
028: * decision by deleting the provisions above and replace them with the notice
029: * and other provisions required by the GPL or the LGPL. If you do not delete
030: * the provisions above, a recipient may use your version of this file under
031: * the terms of any one of the CPL, the GPL or the LGPL.
032: ***** END LICENSE BLOCK *****/package org.jruby;
033:
034: import org.jruby.runtime.Block;
035: import org.jruby.runtime.CallbackFactory;
036: import org.jruby.runtime.ObjectAllocator;
037: import org.jruby.runtime.builtin.IRubyObject;
038: import org.jruby.util.JRubyFile;
039:
040: /**
041: * note: renamed from FileStatClass.java
042: * Implements File::Stat
043: */
044: public class RubyFileStat extends RubyObject {
045: private static final int READ = 0222;
046: private static final int WRITE = 0444;
047:
048: private RubyFixnum blksize;
049: private RubyBoolean isDirectory;
050: private RubyBoolean isFile;
051: private RubyString ftype;
052: private RubyFixnum mode;
053: private RubyTime mtime;
054: private RubyTime ctime;
055: private RubyBoolean isReadable;
056: private RubyBoolean isWritable;
057: private RubyFixnum size;
058: private RubyBoolean isSymlink;
059:
060: private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
061: public IRubyObject allocate(Ruby runtime, RubyClass klass) {
062: return new RubyFileStat(runtime, klass);
063: }
064: };
065:
066: public static RubyClass createFileStatClass(Ruby runtime) {
067: // TODO: NOT_ALLOCATABLE_ALLOCATOR is probably ok here. Confirm. JRUBY-415
068: final RubyClass fileStatClass = runtime.getClass("File")
069: .defineClassUnder("Stat", runtime.getObject(),
070: ALLOCATOR);
071: final CallbackFactory callbackFactory = runtime
072: .callbackFactory(RubyFileStat.class);
073:
074: fileStatClass.defineFastMethod("initialize", callbackFactory
075: .getMethod("initialize", RubyKernel.IRUBY_OBJECT));
076: // fileStatClass.defineMethod("<=>", callbackFactory.getMethod(""));
077: // fileStateClass.includeModule(runtime.getModule("Comparable"));
078: // fileStatClass.defineMethod("atime", callbackFactory.getMethod(""));
079: fileStatClass.defineFastMethod("blksize", callbackFactory
080: .getFastMethod("blksize"));
081: // fileStatClass.defineMethod("blockdev?", callbackFactory.getMethod(""));
082: // fileStatClass.defineMethod("blocks", callbackFactory.getMethod(""));
083: // fileStatClass.defineMethod("chardev?", callbackFactory.getMethod(""));
084: fileStatClass.defineFastMethod("ctime", callbackFactory
085: .getFastMethod("ctime"));
086: // fileStatClass.defineMethod("dev", callbackFactory.getMethod(""));
087: // fileStatClass.defineMethod("dev_major", callbackFactory.getMethod(""));
088: // fileStatClass.defineMethod("dev_minor", callbackFactory.getMethod(""));
089: fileStatClass.defineFastMethod("directory?", callbackFactory
090: .getFastMethod("directory_p"));
091: // fileStatClass.defineMethod("executable?", callbackFactory.getMethod(""));
092: // fileStatClass.defineMethod("executable_real?", callbackFactory.getMethod(""));
093: fileStatClass.defineFastMethod("file?", callbackFactory
094: .getFastMethod("file_p"));
095: fileStatClass.defineFastMethod("ftype", callbackFactory
096: .getFastMethod("ftype"));
097: // fileStatClass.defineMethod("gid", callbackFactory.getMethod(""));
098: // fileStatClass.defineMethod("grpowned?", callbackFactory.getMethod(""));
099: fileStatClass.defineFastMethod("ino", callbackFactory
100: .getFastMethod("ino"));
101: fileStatClass.defineFastMethod("mode", callbackFactory
102: .getFastMethod("mode"));
103: fileStatClass.defineFastMethod("mtime", callbackFactory
104: .getFastMethod("mtime"));
105: // fileStatClass.defineMethod("nlink", callbackFactory.getMethod(""));
106: // fileStatClass.defineMethod("owned?", callbackFactory.getMethod(""));
107: // fileStatClass.defineMethod("pipe?", callbackFactory.getMethod(""));
108: // fileStatClass.defineMethod("rdev", callbackFactory.getMethod(""));
109: // fileStatClass.defineMethod("rdev_major", callbackFactory.getMethod(""));
110: // fileStatClass.defineMethod("rdev_minor", callbackFactory.getMethod(""));
111: fileStatClass.defineFastMethod("readable?", callbackFactory
112: .getFastMethod("readable_p"));
113: // fileStatClass.defineMethod("readable_real?", callbackFactory.getMethod(""));
114: // fileStatClass.defineMethod("setgid?", callbackFactory.getMethod(""));
115: // fileStatClass.defineMethod("setuid?", callbackFactory.getMethod(""));
116: fileStatClass.defineFastMethod("size", callbackFactory
117: .getFastMethod("size"));
118: // fileStatClass.defineMethod("size?", callbackFactory.getMethod(""));
119: // fileStatClass.defineMethod("socket?", callbackFactory.getMethod(""));
120: // fileStatClass.defineMethod("sticky?", callbackFactory.getMethod(""));
121: fileStatClass.defineFastMethod("symlink?", callbackFactory
122: .getFastMethod("symlink_p"));
123: // fileStatClass.defineMethod("uid", callbackFactory.getMethod(""));
124: fileStatClass.defineFastMethod("writable?", callbackFactory
125: .getFastMethod("writable"));
126: // fileStatClass.defineMethod("writable_real?", callbackFactory.getMethod(""));
127: // fileStatClass.defineMethod("zero?", callbackFactory.getMethod(""));
128:
129: return fileStatClass;
130: }
131:
132: protected RubyFileStat(Ruby runtime, RubyClass clazz) {
133: super (runtime, clazz);
134:
135: }
136:
137: public IRubyObject initialize(IRubyObject fname, Block unusedBlock) {
138: Ruby runtime = getRuntime();
139: JRubyFile file = JRubyFile.create(
140: runtime.getCurrentDirectory(), fname.toString());
141:
142: if (!file.exists()) {
143: throw runtime
144: .newErrnoENOENTError("No such file or directory - "
145: + file.getPath());
146: }
147:
148: // We cannot determine, so always return 4096 (better than blowing up)
149: blksize = runtime.newFixnum(4096);
150: isDirectory = runtime.newBoolean(file.isDirectory());
151: isFile = runtime.newBoolean(file.isFile());
152: ftype = file.isDirectory() ? runtime.newString("directory")
153: : (file.isFile() ? runtime.newString("file") : null);
154:
155: // implementation to lowest common denominator...Windows has no file mode, but C ruby returns either 0100444 or 0100666
156: int baseMode = 0100000;
157: if (file.canRead()) {
158: baseMode += READ;
159: }
160: if (file.canWrite()) {
161: baseMode += WRITE;
162: }
163: mode = runtime.newFixnum(baseMode);
164: mtime = runtime.newTime(file.lastModified());
165: ctime = runtime.newTime(file.getParentFile().lastModified());
166: isReadable = runtime.newBoolean(file.canRead());
167: isWritable = runtime.newBoolean(file.canWrite());
168: size = runtime.newFixnum(file.length());
169: // We cannot determine this in Java, so we will always return false (better than blowing up)
170: isSymlink = runtime.getFalse();
171: return this ;
172: }
173:
174: public RubyFixnum blksize() {
175: return blksize;
176: }
177:
178: public RubyBoolean directory_p() {
179: return isDirectory;
180: }
181:
182: public RubyBoolean file_p() {
183: return isFile;
184: }
185:
186: public RubyString ftype() {
187: return ftype;
188: }
189:
190: // Limitation: We have no pure-java way of getting inode. webrick needs this defined to work.
191: public IRubyObject ino() {
192: return getRuntime().newFixnum(0);
193: }
194:
195: public IRubyObject mode() {
196: return mode;
197: }
198:
199: public IRubyObject mtime() {
200: return mtime;
201: }
202:
203: public IRubyObject ctime() {
204: return ctime;
205: }
206:
207: public IRubyObject readable_p() {
208: return isReadable;
209: }
210:
211: public IRubyObject size() {
212: return size;
213: }
214:
215: public IRubyObject symlink_p() {
216: return isSymlink;
217: }
218:
219: public IRubyObject writable() {
220: return isWritable;
221: }
222: }
|