Skip to content

Commit

Permalink
find gem extension classes for uri-like filenames
Browse files Browse the repository at this point in the history
depending on how the load-service resolves a require ($LOAD_PATH, argument
of require) it can happen that the ClassExtensionLibrary gets a uri-like
searchName. in such a case it needs to be treated as absolute file so the
class-name builder will try the right class-name as well.

fixes #2986

Sponsored By Lookout Inc.
mkristian committed May 25, 2015
1 parent e237201 commit 62fa282
Showing 2 changed files with 47 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -28,9 +28,12 @@
package org.jruby.runtime.load;

import jnr.posix.JavaSecuredFile;

import org.jruby.Ruby;

import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* The ClassExtensionLibrary wraps a class which implements BasicLibraryService,
@@ -44,6 +47,8 @@ public class ClassExtensionLibrary implements Library {
private final Class theClass;
private final String name;

private static Pattern URI_LIKE = Pattern.compile("(uri:classloader|file|jar|jar:file:uri):/?/?");

/**
* Try to locate an extension service in the current classloader resources. This happens
* after the jar has been added to JRuby's URLClassLoader (JRubyClassLoader) and is how
@@ -63,11 +68,19 @@ public class ClassExtensionLibrary implements Library {
* @return a ClassExtensionLibrary that will boot the ext, or null if none was found
*/
static ClassExtensionLibrary tryFind(Ruby runtime, String searchName) {
final boolean isAbsolute;
Matcher matcher = URI_LIKE.matcher(searchName);
if (matcher.matches()) {
searchName = matcher.replaceFirst("");
isAbsolute = true;
}
else {
isAbsolute = new JavaSecuredFile(searchName).isAbsolute();
}

// Create package name, by splitting on / and successively accumulating elements to form a class name
String[] elts = searchName.split("/");

boolean isAbsolute = new JavaSecuredFile(searchName).isAbsolute();

String simpleName = buildSimpleName(elts[elts.length - 1]);

int firstElement = isAbsolute ? elts.length - 1 : 0;
32 changes: 32 additions & 0 deletions test/test_load_gem_extensions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'test/unit'
require 'test/test_helper'
require 'rbconfig'
require 'jruby/path_helper'

class TestLoad < Test::Unit::TestCase
include TestHelper

def setup
@prev_loaded_features = $LOADED_FEATURES.dup
@prev_load_path = $LOAD_PATH.dup
end

def teardown
$LOADED_FEATURES.clear
$LOADED_FEATURES.concat(@prev_loaded_features)
$LOAD_PATH.clear
$LOAD_PATH.concat(@prev_load_path)
end

def test_require_extension_file_via_uri_protocol
require 'uri:file:./lib/ruby/shared/json/ext/parser'
# just check if extension class exists
JSON::Ext::Parser
end

def test_require_extension_file_via_uri_classloader_protocol
require 'uri:classloader:/lib/ruby/shared/json/ext/generator'
# just check if extension class exists
JSON::Ext::Generator
end
end

0 comments on commit 62fa282

Please sign in to comment.