Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   ***** BEGIN LICENSE BLOCK *****
   * Version: EPL 1.0/GPL 2.0/LGPL 2.1
   *
   * The contents of this file are subject to the Eclipse Public
   * License Version 1.0 (the "License"); you may not use this file
   * except in compliance with the License. You may obtain a copy of
   * the License at http://www.eclipse.org/legal/epl-v10.html
   *
  * Software distributed under the License is distributed on an "AS
  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  * implied. See the License for the specific language governing
  * rights and limitations under the License.
  *
  * Copyright (C) 2013 Benoit Daloze <eregontp@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the EPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the EPL, the GPL or the LGPL.
  ***** END LICENSE BLOCK *****/
 package org.jruby.ext.pathname;
 
 import static org.jruby.anno.FrameField.BACKREF;
 
 import org.jruby.Ruby;
 
 @JRubyClass(name = "Pathname")
 public class RubyPathname extends RubyObject {
     private RubyString path;
 
     static void createPathnameClass(Ruby runtime) {
         RubyClass cPathname = runtime.defineClass("Pathname"runtime.getObject(),
                 );
 
         cPathname.defineAnnotatedMethods(RubyPathname.class);
 
         runtime.getKernel().defineAnnotatedMethods(PathnameKernelMethods.class);
 
         defineDelegateMethods(cPathnameruntime.getFile(), "atime""ctime""mtime""ftype",
                 "rename""stat""lstat""truncate""extname""open");
         defineDelegateMethodsAppendPath(cPathnameruntime.getFile(), "chmod""lchmod""chown",
                 "lchown""utime");
         defineDelegateMethodsSinglePath(cPathnameruntime.getFile(), "realpath""realdirpath",
                 "basename""dirname""expand_path""readlink");
         defineDelegateMethodsArrayOfPaths(cPathnameruntime.getFile(), "split");
 
         defineDelegateMethods(cPathnameruntime.getIO(), "read""binread""write""binwrite",
                 "readlines""sysopen");
 
         defineDelegateMethods(cPathnameruntime.getFileTest(), "blockdev?""chardev?",
                 "executable?""executable_real?""exist?""grpowned?""directory?""file?",
                 "pipe?""socket?""owned?""readable?""world_readable?""readable_real?",
                 "setuid?""setgid?""size""size?""sticky?""symlink?""writable?",
                 "world_writable?""writable_real?""zero?");
 
         defineDelegateMethods(cPathnameruntime.getDir(), "mkdir""rmdir");
         defineDelegateMethodsArrayOfPaths(cPathnameruntime.getDir(), "entries");
 
         cPathname.undefineMethod("=~");
     }
 
     static interface ReturnValueMapper {
         IRubyObject map(ThreadContext contextRubyClass klazzIRubyObject value);
     }
 
     static interface AddArg {
         IRubyObject[] addArg(IRubyObject[] argsRubyString path);
     }
 
     private static final ReturnValueMapper IDENTITY_MAPPER = new ReturnValueMapper() {
         @Override
         public IRubyObject map(ThreadContext contextRubyClass klazzIRubyObject value) {
             return value;
         }
    };
    private static final ReturnValueMapper SINGLE_PATH_MAPPER = new ReturnValueMapper() {
        @Override
        public IRubyObject map(ThreadContext contextRubyClass klazzIRubyObject value) {
            return newInstance(contextklazzvalue);
        }
    };
    private static final ReturnValueMapper ARRAY_OF_PATHS_MAPPER = new ReturnValueMapper() {
        @Override
        public IRubyObject map(ThreadContext contextRubyClass klazzIRubyObject value) {
            return mapToPathnames(contextklazzvalue);
        }
    };
    private static final AddArg UNSHIFT_PATH = new AddArg() {
        @Override
        public IRubyObject[] addArg(IRubyObject[] argsRubyString path) {
            return insert(args, 0, path);
        }
    };
    private static final AddArg APPEND_PATH = new AddArg() {
        @Override
        public IRubyObject[] addArg(IRubyObject[] argsRubyString path) {
            return insert(argsargs.lengthpath);
        }
    };
    private static void defineDelegateMethodsGeneric(RubyClass cPathnamefinal RubyModule klass,
            final ReturnValueMapper mapperfinal AddArg addArgString... methods) {
        for (String method : methods) {
            cPathname.addMethod(methodnew JavaMethod.JavaMethodNBlock(cPathname,
                    .) {
                @Override
                public IRubyObject call(ThreadContext contextIRubyObject _selfRubyModule clazz,
                        String nameIRubyObject[] argsBlock block) {
                    RubyPathname self = (RubyPathname_self;
                    args = addArg.addArg(argsself.path);
                    return mapper.map(context, (RubyClassclazzklass.callMethod(contextnameargsblock));
                }
            });
        }
    }
    private static void defineDelegateMethods(RubyClass cPathnamefinal RubyModule klass,
            String... methods) {
        defineDelegateMethodsGeneric(cPathnameklassmethods);
    }
    private static void defineDelegateMethodsAppendPath(RubyClass cPathname,
            final RubyModule klassString... methods) {
        defineDelegateMethodsGeneric(cPathnameklassmethods);
    }
    private static void defineDelegateMethodsSinglePath(RubyClass cPathname,
            final RubyModule klassString... methods) {
        defineDelegateMethodsGeneric(cPathnameklassmethods);
    }
    private static void defineDelegateMethodsArrayOfPaths(RubyClass cPathname,
            final RubyModule klassString... methods) {
        defineDelegateMethodsGeneric(cPathnameklassmethods);
    }
    public static class PathnameKernelMethods {
        @JRubyMethod(name = "Pathname", module = true, visibility = .)
        public static IRubyObject newPathname(IRubyObject recvIRubyObject path) {
            return RubyPathname.newInstance(recv.getRuntime().getCurrentContext(), path);
        }
    }
    private static ObjectAllocator PATHNAME_ALLOCATOR = new ObjectAllocator() {
        @Override
        public IRubyObject allocate(Ruby runtimeRubyClass klass) {
            return new RubyPathname(runtimeklass);
        }
    };
    public RubyPathname(Ruby runtimeRubyClass metaClass) {
        super(runtimemetaClass);
         = null;
    }
    public static RubyPathname newInstance(ThreadContext contextRubyClass klassIRubyObject path) {
        RubyPathname pathname = new RubyPathname(context.runtimeklass);
        return (RubyPathnamepathname.initialize(contextpath);
    }
    public static RubyPathname newInstance(ThreadContext contextIRubyObject path) {
        return newInstance(contextcontext.runtime.getClass("Pathname"), path);
    }
    public IRubyObject initialize(ThreadContext contextIRubyObject path) {
        String toPath = toPathMethod(context.runtime);
        if (path.respondsTo(toPath)) {
            path = path.callMethod(contexttoPath);
        }
        RubyString str = path.convertToString();
        if (str.getByteList().indexOf('\0') != -1) {
            throw context.runtime.newArgumentError("pathname contains null byte");
        }
        infectBy(str);
        this. = (RubyStringstr.dup();
        // TODO: remove (either direct bridge to field or all native)
        setInstanceVariable("@path"this.);
        return this;
    }
    private static String toPathMethod(Ruby runtime) {
        return runtime.is1_8() ? "to_str" : "to_path";
    }
    public IRubyObject initialize_copy(ThreadContext contextIRubyObject pathname) {
        super.initialize_copy(pathname);
        initialize(contextpathname);
        return this;
    }
    @JRubyMethod(compat = .)
    public IRubyObject to_str(ThreadContext context) {
        return ;
    }
    @JRubyMethod(compat = .)
    public IRubyObject to_path(ThreadContext context) {
        return ;
    }
    @Override
    public IRubyObject freeze(ThreadContext context) {
        .freeze(context);
        return super.freeze(context);
    }
    @Override
    public IRubyObject taint(ThreadContext context) {
        .taint(context);
        return super.taint(context);
    }
    @Override
    public IRubyObject untaint(ThreadContext context) {
        .untaint(context);
        return super.untaint(context);
    }
    @Override
    @JRubyMethod(name = { "==""eql?" })
    public IRubyObject op_equal(ThreadContext contextIRubyObject other) {
        if (other instanceof RubyPathname) {
            return Helpers.rbEqual(context, ((RubyPathnameother).);
        } else {
            return context.runtime.getFalse();
        }
    }
    private int cmp(RubyPathname other) {
        byte[] a = .getByteList().bytes();
        byte[] b = other.path.getByteList().bytes();
        int i;
        for (i = 0; i < a.length && i < b.lengthi++) {
            byte ca = a[i];
            byte cb = b[i];
            if (ca == '/') {
                ca = '\0';
            }
            if (cb == '/') {
                cb = '\0';
            }
            if (ca != cb) {
                return ca < cb ? -1 : 1;
            }
        }
        if (i < a.length) {
            return 1;
        }
        if (i < b.length) {
            return -1;
        }
        return 0;
    }
    @Override
    @JRubyMethod(name = "<=>")
    public IRubyObject op_cmp(ThreadContext contextIRubyObject other) {
        if (other instanceof RubyPathname) {
            return context.runtime.newFixnum(cmp((RubyPathnameother));
        } else {
            return context.nil;
        }
    }
    @JRubyMethod(name = "hash")
    public RubyFixnum hash(ThreadContext context) {
        return .hash();
    }
    @Override
    public int hashCode() {
        return .hashCode();
    }
    public IRubyObject to_s(ThreadContext context) {
        return .dup();
    }
    public IRubyObject inspect(ThreadContext context) {
        return context.runtime.newString("<Pathname:" +  + ">");
    }
    @JRubyMethod(required = 1, optional = 1, reads = , writes = )
    public IRubyObject sub(ThreadContext contextIRubyObject[] argsBlock block) {
        IRubyObject result = .callMethod(context"sub"argsblock);
        return newInstance(contextresult);
    }
    public IRubyObject sub_ext(ThreadContext contextIRubyObject newExt) {
        IRubyObject ext = context.runtime.getFile().callMethod(context"extname");
        IRubyObject newPath = .chomp(contextext).callMethod(context"+"newExt);
        return newInstance(contextnewPath);
    }
    /* Facade for File */
    @JRubyMethod(alias = "fnmatch?", required = 1, optional = 1)
    public IRubyObject fnmatch(ThreadContext contextIRubyObject[] args) {
        args = insertPath(args, 1);
        return context.runtime.getFile().callMethod(context"fnmatch?"args);
    }
    public IRubyObject make_link(ThreadContext contextIRubyObject old) {
        IRubyObject[] args = new IRubyObject[] { old };
        return context.runtime.getFile().callMethod(context"link"args);
    }
    public IRubyObject make_symlink(ThreadContext contextIRubyObject old) {
        IRubyObject[] args = new IRubyObject[] { old };
        return context.runtime.getFile().callMethod(context"symlink"args);
    }
    /* Facade for IO */
    @JRubyMethod(optional = 3)
    public IRubyObject each_line(ThreadContext contextIRubyObject[] argsBlock block) {
        return context.runtime.getIO().callMethod(context"foreach"unshiftPath(args), block);
    }
    /* Facade for Dir */
    @JRubyMethod(alias = "pwd", meta = true)
    public static IRubyObject getwd(ThreadContext contextIRubyObject recv) {
        return newInstance(contextcontext.runtime.getDir().callMethod("getwd"));
    }
    @JRubyMethod(required = 1, optional = 1, meta = true)
    public static IRubyObject glob(ThreadContext contextIRubyObject recvIRubyObject[] args,
            Block block) {
        // TODO: yield block while iterating
        RubyArray files = mapToPathnames(context, (RubyClassrecv,
                context.runtime.getDir().callMethod(context"glob"args));
        if (block.isGiven()) {
            files.each(contextblock);
            return context.nil;
        } else {
            return files;
        }
    }
    public IRubyObject opendir(ThreadContext contextBlock block) {
        return context.runtime.getDir().callMethod(context"open"new IRubyObject[] {  },
                block);
    }
    public IRubyObject each_entry(ThreadContext contextBlock block) {
        if (block.isGiven()) {
            // TODO: yield block while iterating
            RubyArray entries = callMethod(context"entries").convertToArray();
            entries.each(contextblock);
            return context.nil;
        } else {
            return context.runtime.getDir().callMethod(context"foreach");
        }
    }
    /* Mix of File and Dir */
    @JRubyMethod(name = {"unlink""delete"})
    public IRubyObject unlink(ThreadContext context) {
        try {
            return context.runtime.getDir().callMethod(context"unlink");
        } catch (RaiseException ex) {
            if (!context.runtime.getErrno().getClass("ENOTDIR").isInstance(ex.getException())) {
                throw ex;
            }
            return context.runtime.getFile().callMethod(context"unlink");
        }
    }
    /* Helpers */
    private IRubyObject[] insertPath(IRubyObject[] argsint i) {
        return insert(argsi);
    }
    private IRubyObject[] unshiftPath(IRubyObject[] args) {
        return insert(args, 0, );
    }
    private static IRubyObject[] insert(IRubyObject[] oldint iIRubyObject obj) {
        IRubyObject[] ary = new IRubyObject[old.length + 1];
        if (i > 0) {
            System.arraycopy(old, 0, ary, 0, i);
        }
        ary[i] = obj;
        if (old.length > i) {
            System.arraycopy(oldiaryi + 1, old.length - i);
        }
        return ary;
    }
    private static RubyArray mapToPathnames(ThreadContext contextRubyClass clazzIRubyObject ary) {
        RubyArray paths = ary.convertToArray();
        for (int i = 0; i < paths.size(); i++) {
            RubyString path = paths.eltOk(i).convertToString();
            paths.store(inewInstance(contextclazzpath));
        }
        return paths;
    }
New to GrepCode? Check out our FAQ X