Skip to content

Commit 0e17f04

Browse files
authoredJun 9, 2018
Merge pull request #5211 from jruby/ji-path
[ji] coercing Ruby File/Dir to Java File/Path
2 parents 6baf780 + 6562738 commit 0e17f04

File tree

6 files changed

+95
-45
lines changed

6 files changed

+95
-45
lines changed
 

‎core/src/main/java/org/jruby/RubyDir.java

+39-18
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,25 @@
3232

3333
package org.jruby;
3434

35-
import static org.jruby.RubyEnumerator.enumeratorize;
36-
35+
import java.io.Closeable;
3736
import java.io.File;
3837
import java.io.FileInputStream;
3938
import java.io.IOException;
39+
import java.nio.file.FileSystems;
40+
import java.nio.file.Path;
41+
import java.nio.file.Watchable;
4042
import java.util.ArrayList;
4143
import java.util.Arrays;
4244
import java.util.Collections;
4345
import java.util.List;
4446
import java.util.regex.Pattern;
4547

4648
import jnr.posix.FileStat;
47-
48-
import org.jruby.anno.JRubyMethod;
49-
import org.jruby.anno.JRubyClass;
50-
5149
import jnr.posix.util.Platform;
5250

5351
import org.jcodings.Encoding;
54-
import org.jcodings.specific.UTF8Encoding;
52+
import org.jruby.anno.JRubyMethod;
53+
import org.jruby.anno.JRubyClass;
5554
import org.jruby.exceptions.RaiseException;
5655
import org.jruby.javasupport.JavaUtil;
5756
import org.jruby.runtime.Block;
@@ -62,22 +61,23 @@
6261
import org.jruby.util.*;
6362
import org.jruby.ast.util.ArgsUtil;
6463

64+
import static org.jruby.RubyEnumerator.enumeratorize;
65+
import static org.jruby.RubyString.UTF8;
66+
6567
/**
66-
* .The Ruby built-in class Dir.
68+
* The Ruby built-in class Dir.
6769
*
6870
* @author jvoegele
6971
*/
7072
@JRubyClass(name = "Dir", include = "Enumerable")
71-
public class RubyDir extends RubyObject {
73+
public class RubyDir extends RubyObject implements Closeable {
7274
private RubyString path; // What we passed to the constructor for method 'path'
7375
protected FileResource dir;
7476
private long lastModified = Long.MIN_VALUE;
7577
private String[] snapshot; // snapshot of contents of directory
7678
private int pos; // current position in directory
7779
private boolean isOpen = true;
7880

79-
private final static Encoding UTF8 = UTF8Encoding.INSTANCE;
80-
8181
private static final Pattern PROTOCOL_PATTERN = Pattern.compile("^(uri|jar|file|classpath):([^:]*:)?//?.*");
8282

8383
public RubyDir(Ruby runtime, RubyClass type) {
@@ -650,13 +650,15 @@ public static IRubyObject open19(ThreadContext context, IRubyObject recv, IRubyO
650650
* Closes the directory stream.
651651
*/
652652
@JRubyMethod(name = "close")
653-
public IRubyObject close() {
653+
public IRubyObject close(ThreadContext context) {
654+
close();
655+
return context.nil;
656+
}
657+
658+
public final void close() {
654659
// Make sure any read()s after close fail.
655660
checkDirIgnoreClosed();
656-
657661
isOpen = false;
658-
659-
return getRuntime().getNil();
660662
}
661663

662664
/**
@@ -769,6 +771,11 @@ public IRubyObject to_path(ThreadContext context) {
769771
return path(context);
770772
}
771773

774+
public String getPath() {
775+
if (path == null) return null;
776+
return path.asJavaString();
777+
}
778+
772779
/** Returns the next entry from this directory. */
773780
@JRubyMethod(name = "read")
774781
public IRubyObject read() {
@@ -992,17 +999,18 @@ public static RubyString getHomeDirectoryPath(ThreadContext context) {
992999
return getHomeDirectoryPath(context, context.runtime.getENV().op_aref(context, homeKey));
9931000
}
9941001

1002+
private static final ByteList user_home = new ByteList(new byte[] {'u','s','e','r','.','h','o','m','e'}, false);
1003+
9951004
static RubyString getHomeDirectoryPath(ThreadContext context, IRubyObject home) {
9961005
final Ruby runtime = context.runtime;
9971006

9981007
if (home == null || home == context.nil) {
9991008
IRubyObject ENV_JAVA = runtime.getObject().getConstant("ENV_JAVA");
1000-
home = ENV_JAVA.callMethod(context, "[]", runtime.newString("user.home"));
1009+
home = ENV_JAVA.callMethod(context, "[]", RubyString.newString(runtime, user_home, UTF8));
10011010
}
10021011

10031012
if (home == null || home == context.nil) {
1004-
RubyHash ENV = (RubyHash) runtime.getObject().getConstant("ENV");
1005-
home = ENV.op_aref(context, runtime.newString("LOGDIR"));
1013+
home = context.runtime.getENV().op_aref(context, runtime.newString("LOGDIR"));
10061014
}
10071015

10081016
if (home == null || home == context.nil) {
@@ -1012,6 +1020,19 @@ static RubyString getHomeDirectoryPath(ThreadContext context, IRubyObject home)
10121020
return (RubyString) home;
10131021
}
10141022

1023+
@Override
1024+
public <T> T toJava(Class<T> target) {
1025+
if (target == File.class) {
1026+
final String path = getPath();
1027+
return path == null ? null : (T) new File(path);
1028+
}
1029+
if (target == Path.class || target == Watchable.class) {
1030+
final String path = getPath();
1031+
return path == null ? null : (T) FileSystems.getDefault().getPath(path);
1032+
}
1033+
return super.toJava(target);
1034+
}
1035+
10151036
@Deprecated
10161037
public static RubyArray entries19(ThreadContext context, IRubyObject recv, IRubyObject arg) {
10171038
return entries(context, recv, arg);

‎core/src/main/java/org/jruby/RubyFile.java

+10-16
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import org.jruby.anno.JRubyClass;
4545
import org.jruby.anno.JRubyMethod;
4646
import org.jruby.exceptions.NotImplementedError;
47-
import org.jruby.exceptions.RaiseException;
4847
import org.jruby.runtime.*;
4948
import org.jruby.runtime.JavaSites.FileSites;
5049
import org.jruby.runtime.builtin.IRubyObject;
@@ -65,11 +64,7 @@
6564
import java.net.URL;
6665
import java.nio.channels.Channels;
6766
import java.nio.channels.FileChannel;
68-
import java.nio.file.FileStore;
69-
import java.nio.file.Files;
70-
import java.nio.file.LinkOption;
71-
import java.nio.file.Path;
72-
import java.nio.file.Paths;
67+
import java.nio.file.*;
7368
import java.nio.file.attribute.FileTime;
7469
import java.nio.file.attribute.PosixFileAttributeView;
7570
import java.util.ArrayList;
@@ -88,8 +83,8 @@
8883
import static org.jruby.util.io.EncodingUtils.vperm;
8984

9085
/**
91-
* Ruby File class equivalent in java.
92-
**/
86+
* The Ruby File class.
87+
*/
9388
@JRubyClass(name="File", parent="IO", include="FileTest")
9489
public class RubyFile extends RubyIO implements EncodingCapable {
9590

@@ -298,7 +293,7 @@ protected IRubyObject rbIoClose(ThreadContext context) {
298293
public IRubyObject flock(ThreadContext context, IRubyObject operation) {
299294

300295
// Solaris uses a ruby-ffi version defined in jruby/kernel/file.rb, so re-dispatch
301-
if (org.jruby.platform.Platform.IS_SOLARIS) {
296+
if (Platform.IS_SOLARIS) {
302297
return callMethod(context, "flock", operation);
303298
}
304299

@@ -423,7 +418,6 @@ public IRubyObject birthtime(ThreadContext context) {
423418

424419
public static final FileTime getBirthtimeWithNIO(String pathString) {
425420
// FIXME: birthtime is in stat, so we should use that if platform supports it (#2152)
426-
// TODO: This requires Java 7 APIs and may not work on Android
427421
Path path = Paths.get(pathString);
428422
PosixFileAttributeView view = Files.getFileAttributeView(path, PosixFileAttributeView.class, LinkOption.NOFOLLOW_LINKS);
429423
try {
@@ -943,10 +937,6 @@ public static IRubyObject ftype(ThreadContext context, IRubyObject recv, IRubyOb
943937
return runtime.newFileStat(path.getUnicodeValue(), true).ftype();
944938
}
945939

946-
/*
947-
* Fixme: This does not have exact same semantics as RubyArray.join, but they
948-
* probably could be consolidated (perhaps as join(args[], sep, doChomp)).
949-
*/
950940
@JRubyMethod(rest = true, meta = true)
951941
public static RubyString join(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
952942
return doJoin(context, recv, args);
@@ -2116,14 +2106,18 @@ private static RubyString checkHome(ThreadContext context) {
21162106
public <T> T toJava(Class<T> target) {
21172107
if (target == File.class) {
21182108
final String path = getPath();
2119-
return path == null ? null : target.cast(new File(path));
2109+
return path == null ? null : (T) new File(path);
2110+
}
2111+
if (target == Path.class || target == Watchable.class) {
2112+
final String path = getPath();
2113+
return path == null ? null : (T) FileSystems.getDefault().getPath(path);
21202114
}
21212115
return super.toJava(target);
21222116
}
21232117

21242118
private static RubyString doJoin(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
21252119
final Ruby runtime = context.runtime;
2126-
final String separator = runtime.getClass("File").getConstant("SEPARATOR").toString();
2120+
final String separator = runtime.getFile().getConstant("SEPARATOR").toString();
21272121

21282122
final RubyArray argsAry = RubyArray.newArrayMayCopy(runtime, args);
21292123

‎core/src/main/java/org/jruby/RubyString.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@
120120
public class RubyString extends RubyObject implements CharSequence, EncodingCapable, MarshalEncoding, CodeRangeable {
121121
public static final String DEBUG_INFO_FIELD = "@debug_created_info";
122122

123-
private static final ASCIIEncoding ASCII = ASCIIEncoding.INSTANCE;
124-
private static final UTF8Encoding UTF8 = UTF8Encoding.INSTANCE;
123+
static final ASCIIEncoding ASCII = ASCIIEncoding.INSTANCE;
124+
static final UTF8Encoding UTF8 = UTF8Encoding.INSTANCE;
125125

126126
// string doesn't share any resources
127127
private static final int SHARE_LEVEL_NONE = 0;
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
require File.dirname(__FILE__) + "/../spec_helper"
2+
3+
describe "Ruby Dir" do
4+
5+
it "is coercible to java.io.File" do
6+
dir = Dir.new('..')
7+
expect(java.io.File).to be === dir.to_java('java.io.File')
8+
file = dir.to_java(java.io.File)
9+
expect(file.getPath).to eql '..'
10+
dir.close
11+
end
12+
13+
it "is coercible to (java) Path" do
14+
Dir.open('.') do |dir|
15+
java_file= dir.to_java java.nio.file.Path
16+
expect(java_file).to eql java.io.File.new('.').toPath
17+
end
18+
end
19+
20+
end
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
require File.dirname(__FILE__) + "/../spec_helper"
2+
3+
describe "Ruby File" do
4+
5+
before(:all) { require 'tempfile' }
6+
7+
it "is coercible to java.io.File" do
8+
file = Tempfile.new("io_spec").to_java 'java.io.File'
9+
expect(java.io.File).to be === file
10+
file = File.open(__FILE__).to_java java.io.File
11+
expect(java.io.File).to be === file
12+
expect(file.getPath).to eql __FILE__
13+
end
14+
15+
it "is coercible to (java) Path" do
16+
File.open('.') do |file|
17+
java_file= file.to_java java.nio.file.Path
18+
expect(java_file).to eql java.io.File.new('.').toPath
19+
end
20+
end
21+
22+
end

‎spec/java_integration/addons/io_spec.rb

+2-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
require File.dirname(__FILE__) + "/../spec_helper"
2-
require 'tempfile'
32

43
describe "Ruby IO" do
54

5+
before(:all) { require 'tempfile' }
6+
67
let(:input_number) { "1234567890" }
78

89
it "gets an IO from a java.io.InputStream" do
@@ -126,12 +127,4 @@
126127
expect(str).to eq(String.from_java_bytes(bytes.array))
127128
end
128129

129-
it "is coercible to java.io.Files" do
130-
file = Tempfile.new("io_spec").to_java 'java.io.File'
131-
expect(java.io.File).to be === file
132-
file = File.open(__FILE__).to_java java.io.File
133-
expect(java.io.File).to be === file
134-
expect(file.getPath).to eql __FILE__
135-
end
136-
137130
end

0 commit comments

Comments
 (0)
Please sign in to comment.