Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a66946cd1f56^
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 61c3ca138e52
Choose a head ref
  • 19 commits
  • 30 files changed
  • 1 contributor

Commits on Apr 12, 2016

  1. Copy the full SHA
    a66946c View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f5d0c97 View commit details
  3. Copy the full SHA
    4c59930 View commit details
  4. [ji] unify Java Comparable behaviour - make type incompatibility `Typ…

    …eError`s
    
    previously it was sometimes ClassCastException, TypeError (attempted coercion)
    kares committed Apr 12, 2016
    Copy the full SHA
    39c6ed3 View commit details
  5. Copy the full SHA
    0754dbc View commit details
  6. Copy the full SHA
    228f640 View commit details
  7. Copy the full SHA
    5c0e345 View commit details
  8. explicit static imports

    kares committed Apr 12, 2016
    Copy the full SHA
    fe8db7b View commit details

Commits on Apr 13, 2016

  1. [ji] moving (and improving) **java.util.rb** extensions to native code

    ... and not just for speed (most List extensions also missed specs) :
    
    - List [] and []= were improved to properly work like with a Ruby Array
    - detecting random-acess List for faster iteration
    - backward List iteration on rindex - for non random access using listIterator
    
    - Collection +/- will need more work as currently dup doesn't clone java objects
    kares committed Apr 13, 2016
    Copy the full SHA
    9e2d0af View commit details
  2. [ji] add some Java object dup/clone support (ab)using the java.lang.C…

    …loneable contract
    
    ... will work with most Java collection types as they provide a public clone method
     this also makes java.util.Collection's (previous) +/- additions actually work nicely !
    kares committed Apr 13, 2016
    Copy the full SHA
    264ba1a View commit details
  3. [ji] also support dup/clone-ing collections that do not provide a Jav…

    …a clone method
    
    ... we can do so if we're able to allocate a new instance of the same class
    kares committed Apr 13, 2016
    Copy the full SHA
    b28515f View commit details
  4. [ji] correctly dup and clone Java arrays

    ... prev only clone worked but without Ruby's semantics for cloning singleton class
    kares committed Apr 13, 2016
    Copy the full SHA
    320fd9f View commit details
  5. Copy the full SHA
    2cd1b79 View commit details
  6. Copy the full SHA
    36721cf View commit details
  7. Copy the full SHA
    7755dd3 View commit details
  8. Copy the full SHA
    15309c2 View commit details

Commits on Apr 14, 2016

  1. [ji] moving **java.util.regex.rb** into native for more fine grained …

    …control
    
    Java's Matcher now aligned with Ruby's MatchData (including named groups)
    kares committed Apr 14, 2016
    Copy the full SHA
    3b3290d View commit details
  2. Copy the full SHA
    1fb30a8 View commit details
  3. Copy the full SHA
    61c3ca1 View commit details
Showing with 2,559 additions and 67 deletions.
  1. +1 −5 core/src/main/java/org/jruby/RubyComparable.java
  2. +1 −1 core/src/main/java/org/jruby/RubyProc.java
  3. +2 −0 core/src/main/java/org/jruby/RubyRange.java
  4. +59 −1 core/src/main/java/org/jruby/java/proxies/ArrayJavaProxy.java
  5. +12 −1 core/src/main/java/org/jruby/java/proxies/JavaProxy.java
  6. +11 −4 core/src/main/java/org/jruby/javasupport/Java.java
  7. +2 −7 core/src/main/java/org/jruby/javasupport/JavaCallable.java
  8. +36 −0 core/src/main/java/org/jruby/javasupport/JavaUtil.java
  9. +140 −0 core/src/main/java/org/jruby/javasupport/ext/JavaIo.java
  10. +494 −0 core/src/main/java/org/jruby/javasupport/ext/JavaLang.java
  11. +330 −0 core/src/main/java/org/jruby/javasupport/ext/JavaLangReflect.java
  12. +101 −0 core/src/main/java/org/jruby/javasupport/ext/JavaNet.java
  13. +557 −0 core/src/main/java/org/jruby/javasupport/ext/JavaUtil.java
  14. +272 −0 core/src/main/java/org/jruby/javasupport/ext/JavaUtilRegex.java
  15. +75 −0 core/src/main/java/org/jruby/javasupport/ext/Kernel.java
  16. +1 −1 core/src/main/ruby/jruby/java/core_ext.rb
  17. +5 −5 core/src/main/ruby/jruby/java/java_ext.rb
  18. +4 −0 core/src/main/ruby/jruby/java/java_ext/java.io.rb
  19. +5 −0 core/src/main/ruby/jruby/java/java_ext/java.lang.rb
  20. +4 −0 core/src/main/ruby/jruby/java/java_ext/java.net.rb
  21. +3 −1 core/src/main/ruby/jruby/java/java_ext/java.util.rb
  22. +8 −4 core/src/main/ruby/jruby/java/java_ext/java.util.regex.rb
  23. +136 −0 spec/java_integration/extensions/collection_spec.rb
  24. +116 −18 spec/java_integration/extensions/list_spec.rb
  25. +125 −0 spec/java_integration/extensions/regex_spec.rb
  26. +0 −17 spec/java_integration/regex/matcher_end_spec.rb
  27. +1 −0 spec/java_integration/spec_helper.rb
  28. +40 −0 spec/java_integration/types/array_spec.rb
  29. +2 −0 test/jruby/test_helper.rb
  30. +16 −2 test/jruby/test_java_extension.rb
6 changes: 1 addition & 5 deletions core/src/main/java/org/jruby/RubyComparable.java
Original file line number Diff line number Diff line change
@@ -35,13 +35,9 @@

import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyModule;
import org.jruby.common.RubyWarnings;
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

import java.util.concurrent.Callable;

import static org.jruby.runtime.Helpers.invokedynamic;
import static org.jruby.runtime.invokedynamic.MethodNames.OP_CMP;

@@ -68,7 +64,7 @@ public static RubyModule createComparable(Ruby runtime) {
*
*/
public static int cmpint(ThreadContext context, IRubyObject val, IRubyObject a, IRubyObject b) {
if (val.isNil()) cmperr(a, b);
if (val == context.nil) cmperr(a, b);
if (val instanceof RubyFixnum) {
final int asInt = RubyNumeric.fix2int((RubyFixnum) val);

2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyProc.java
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ protected RubyProc(Ruby runtime, RubyClass rubyClass, Block.Type type, String fi
}


RubyProc(Ruby runtime, RubyClass rubyClass, Block block, String file, int line) {
public RubyProc(Ruby runtime, RubyClass rubyClass, Block block, String file, int line) {
this(runtime, rubyClass, block.type);
this.block = block;
this.file = file;
2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/RubyRange.java
Original file line number Diff line number Diff line change
@@ -760,6 +760,8 @@ public IRubyObject size(ThreadContext context) {
return context.nil;
}

public final boolean isExcludeEnd() { return isExclusive; }

private static final ObjectMarshal RANGE_MARSHAL = new ObjectMarshal() {
@Override
public void marshalTo(Ruby runtime, Object obj, RubyClass type,
60 changes: 59 additions & 1 deletion core/src/main/java/org/jruby/java/proxies/ArrayJavaProxy.java
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;

public class ArrayJavaProxy extends JavaProxy {
public final class ArrayJavaProxy extends JavaProxy {

private final JavaUtil.JavaConverter converter;

@@ -343,6 +343,64 @@ public int hashCode() {
return 11 * Arrays.hashCode((Object[]) array);
}

@Override
public IRubyObject dup() {
final Ruby runtime = getRuntime();

RubyObject dup = new ArrayJavaProxy(runtime, getMetaClass(), cloneObject(), converter);

if (isTaint()) dup.setTaint(true);
initCopy(dup, this, "initialize_dup");

return dup;
}

private static void initCopy(IRubyObject clone, IRubyObject original, String method) {
original.copySpecialInstanceVariables(clone);
if (original.hasVariables()) clone.syncVariables(original);
}

@Override
@JRubyMethod(name = "clone")
public IRubyObject rbClone() {
final Ruby runtime = getRuntime();

RubyObject clone = new ArrayJavaProxy(runtime, getMetaClass(), cloneObject(), converter);
clone.setMetaClass(getSingletonClassClone());

if (isTaint()) clone.setTaint(true);
initCopy(clone, this, "initialize_clone");
if (isFrozen()) clone.setFrozen(true);

return clone;
}

@Override
protected Object cloneObject() {
final Object array = getObject();
final Class<?> componentType = array.getClass().getComponentType();
if ( componentType.isPrimitive() ) {
switch ( componentType.getName().charAt(0) ) {
case 'b':
if (componentType == byte.class) return ((byte[]) array).clone();
else /* if (componentType == boolean.class) */ return ((boolean[]) array).clone();
case 's':
/* if (componentType == short.class) */ return ((short[]) array).clone();
case 'c':
/* if (componentType == char.class) */ return ((char[]) array).clone();
case 'i':
/* if (componentType == int.class) */ return ((int[]) array).clone();
case 'l':
/* if (componentType == long.class) */ return ((long[]) array).clone();
case 'f':
/* if (componentType == float.class) */ return ((float[]) array).clone();
case 'd':
/* if (componentType == double.class) */ return ((double[]) array).clone();
}
}
return ((Object[]) array).clone();
}

public IRubyObject getRange(ThreadContext context, IRubyObject[] args) {
if (args.length == 1) {
return getRange(context, args[0]);
13 changes: 12 additions & 1 deletion core/src/main/java/org/jruby/java/proxies/JavaProxy.java
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@
import org.jruby.javasupport.JavaClass;
import org.jruby.javasupport.JavaMethod;
import org.jruby.javasupport.JavaObject;
import org.jruby.javasupport.JavaUtil;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
@@ -171,10 +172,20 @@ public static IRubyObject persistent(final ThreadContext context, final IRubyObj
public IRubyObject initialize_copy(IRubyObject original) {
super.initialize_copy(original);
// because we lazily init JavaObject in the data-wrapped slot, explicitly copy over the object
setObject( ((JavaProxy) original).getObject() );
setObject( ((JavaProxy) original).cloneObject() );
return this;
}

protected Object cloneObject() {
final Object object = getObject();
if (object instanceof Cloneable) {
// sufficient for java.util collection classes e.g. HashSet, ArrayList
Object clone = JavaUtil.clone(object);
return clone == null ? object : clone;
}
return object; // this is what JRuby did prior to <= 9.0.5
}

/**
* Create a name/newname map of fields to be exposed as methods.
*/
15 changes: 11 additions & 4 deletions core/src/main/java/org/jruby/javasupport/Java.java
Original file line number Diff line number Diff line change
@@ -91,13 +91,11 @@
import org.jruby.java.proxies.JavaInterfaceTemplate;
import org.jruby.java.proxies.JavaProxy;
import org.jruby.java.proxies.RubyObjectHolderProxy;
import org.jruby.java.util.BlankSlateWrapper;
import org.jruby.java.util.SystemPropertiesMap;
import org.jruby.javasupport.proxy.JavaProxyClassFactory;
import org.jruby.util.OneShotClassLoader;
import org.jruby.util.ByteList;
import org.jruby.util.ClassDefiningClassLoader;
import org.jruby.util.ClassProvider;
import org.jruby.util.IdUtil;
import org.jruby.util.JRubyClassLoader;
import org.jruby.util.SafePropertyAccessor;
@@ -118,10 +116,19 @@ public void load(Ruby runtime, boolean wrap) {

JavaPackage.createJavaPackageClass(runtime, Java);

org.jruby.javasupport.ext.Kernel.define(runtime);

org.jruby.javasupport.ext.JavaLang.define(runtime);
org.jruby.javasupport.ext.JavaLangReflect.define(runtime);
org.jruby.javasupport.ext.JavaUtil.define(runtime);
org.jruby.javasupport.ext.JavaUtilRegex.define(runtime);
org.jruby.javasupport.ext.JavaIo.define(runtime);
org.jruby.javasupport.ext.JavaNet.define(runtime);

// load Ruby parts of the 'java' library
runtime.getLoadService().load("jruby/java.rb", false);

// rewite ArrayJavaProxy superclass to point at Object, so it inherits Object behaviors
// rewire ArrayJavaProxy superclass to point at Object, so it inherits Object behaviors
final RubyClass ArrayJavaProxy = runtime.getClass("ArrayJavaProxy");
ArrayJavaProxy.setSuperClass(runtime.getJavaSupport().getObjectJavaClass().getProxyClass());
ArrayJavaProxy.includeModule(runtime.getEnumerable());
@@ -676,7 +683,7 @@ public static RubyModule getJavaPackageModule(final Ruby runtime, final Package
return getJavaPackageModule(runtime, pkg == null ? "" : pkg.getName());
}

private static RubyModule getJavaPackageModule(final Ruby runtime, final String packageString) {
public static RubyModule getJavaPackageModule(final Ruby runtime, final String packageString) {
final String packageName; final int length;
if ( ( length = packageString.length() ) == 0 ) {
packageName = "Default";
9 changes: 2 additions & 7 deletions core/src/main/java/org/jruby/javasupport/JavaCallable.java
Original file line number Diff line number Diff line change
@@ -139,16 +139,11 @@ protected final void checkArity(final int length) {
}

final Object[] convertArguments(final IRubyObject[] args) {
return convertArguments(args, 0);
return JavaUtil.convertArguments(args, parameterTypes, 0);
}

final Object[] convertArguments(final IRubyObject[] args, int offset) {
final Object[] arguments = new Object[ args.length - offset ];
final Class<?>[] types = parameterTypes;
for ( int i = arguments.length; --i >= 0; ) {
arguments[i] = args[ i + offset ].toJava( types[i] );
}
return arguments;
return JavaUtil.convertArguments(args, parameterTypes, offset);
}

protected final IRubyObject handleThrowable(ThreadContext context, final Throwable ex) {
36 changes: 36 additions & 0 deletions core/src/main/java/org/jruby/javasupport/JavaUtil.java
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static java.lang.Character.isLetter;
import static java.lang.Character.isLowerCase;
@@ -507,6 +508,41 @@ else if (rubyName.startsWith("is_")) {
}
}

public static Object[] convertArguments(final IRubyObject[] args, final Class<?>[] types) {
return convertArguments(args, types, 0);
}

public static Object[] convertArguments(final IRubyObject[] args, final Class<?>[] types, int offset) {
final Object[] arguments = new Object[ args.length - offset ];
for ( int i = arguments.length; --i >= 0; ) {
arguments[i] = args[ i + offset ].toJava( types[i] );
}
return arguments;
}

/**
* Clone a Java object, assuming its class has an accessible <code>clone</code> method.
* @param object
* @return cloned object or null (if method is not found or inaccessible)
*/
public static <T> T clone(final Object object) {
return (T) clone(object, false);
}

static Object clone(final Object object, final boolean silent) {
try {
final Method clone = object.getClass().getMethod("clone");
return clone.invoke(object);
}
catch (NoSuchMethodException|IllegalAccessException e) {
return null;
}
catch (InvocationTargetException e) {
if ( ! silent ) Helpers.throwException(e.getTargetException());
return null;
}
}

public static abstract class JavaConverter {
private final Class type;
public JavaConverter(Class type) {this.type = type;}
140 changes: 140 additions & 0 deletions core/src/main/java/org/jruby/javasupport/ext/JavaIo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/***** 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) 2016 The JRuby Team
*
* 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.javasupport.ext;

import org.jruby.Ruby;
import org.jruby.RubyIO;
import org.jruby.RubyModule;
import org.jruby.internal.runtime.methods.JavaMethod;
import org.jruby.javasupport.Java;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

import static org.jruby.javasupport.JavaUtil.unwrapJavaObject;
import static org.jruby.runtime.Visibility.PUBLIC;

/**
* <code>java.io</code> package Ruby additions.
*
* @author kares
*/
public abstract class JavaIo {

public static void define(final Ruby runtime) {
RubyModule proxyClass;

proxyClass = Java.getProxyClass(runtime, java.io.InputStream.class);
proxyClass.addMethodInternal("to_io", new InputStreamToIO(proxyClass));

proxyClass = Java.getProxyClass(runtime, java.io.OutputStream.class);
proxyClass.addMethodInternal("to_io", new OutputStreamToIO(proxyClass));

proxyClass = Java.getProxyClass(runtime, java.nio.channels.Channel.class);
proxyClass.addMethodInternal("to_io", new ChannelToIO(proxyClass));
}

private static final class InputStreamToIO extends JavaMethod.JavaMethodZeroOrOne {

InputStreamToIO(RubyModule implClass) {
super(implClass, PUBLIC);
}

@Override
public RubyIO call(ThreadContext context, IRubyObject self, RubyModule clazz, String name) {
return to_io(context, (java.io.InputStream) unwrapJavaObject(self), null);
}

@Override
public RubyIO call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject opts) {
return to_io(context, (java.io.InputStream) unwrapJavaObject(self), opts);
}

}

static RubyIO to_io(final ThreadContext context, final java.io.InputStream stream, final IRubyObject opts) {
final RubyIO io = new RubyIO(context.runtime, stream);
setAutoclose(context, io, opts);
return io;
}

private static final class OutputStreamToIO extends JavaMethod.JavaMethodZeroOrOne {

OutputStreamToIO(RubyModule implClass) {
super(implClass, PUBLIC);
}

@Override
public RubyIO call(ThreadContext context, IRubyObject self, RubyModule clazz, String name) {
return to_io(context, (java.io.OutputStream) unwrapJavaObject(self), null);
}

@Override
public RubyIO call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject opts) {
return to_io(context, (java.io.OutputStream) unwrapJavaObject(self), opts);
}

}

static RubyIO to_io(final ThreadContext context, final java.io.OutputStream stream, final IRubyObject opts) {
final RubyIO io = new RubyIO(context.runtime, stream);
setAutoclose(context, io, opts);
return io;
}

private static final class ChannelToIO extends JavaMethod.JavaMethodZeroOrOne {

ChannelToIO(RubyModule implClass) {
super(implClass, PUBLIC);
}

@Override
public RubyIO call(ThreadContext context, IRubyObject self, RubyModule clazz, String name) {
return to_io(context, self, null);
}

@Override
public RubyIO call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject opts) {
return to_io(context, self, opts);
}

private static RubyIO to_io(final ThreadContext context, final IRubyObject self, final IRubyObject opts) {
final RubyIO io = new RubyIO(context.runtime, (java.nio.channels.Channel) unwrapJavaObject(self));
setAutoclose(context, io, opts);
return io;
}

}

private static void setAutoclose(final ThreadContext context, final RubyIO io, final IRubyObject opts) {
if ( opts != null && opts != context.nil ) {
IRubyObject autoclose = opts.callMethod(context, "[]", context.runtime.newSymbol("autoclose"));
if ( autoclose != context.nil ) io.setAutoclose( autoclose.isTrue() );
}
}

}
Loading