Skip to content

Commit

Permalink
reduce the classloader lookups for require
Browse files Browse the repository at this point in the history
most creation of  the URLResource are via require 'some/thing' where
it is clear before hand that it is a file and not a directory

URLResource always returns a FileResource, it can be either a file or
a directory or it is marked as not existing. some classloaders return
a stream to directory resource and some classloaders do not. to distinguish
a file from directory you need to check for the .jrubydir file or dig
deeper into the classloader to find out whether this is directory or not.
mkristian committed May 30, 2015
1 parent f29d80c commit 9e79159
Showing 5 changed files with 34 additions and 28 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyInstanceConfig.java
Original file line number Diff line number Diff line change
@@ -394,7 +394,7 @@ public InputStream getScriptSource() {
} else if (script.startsWith("classpath:")) {
stream = getScriptSourceFromJar(script);
} else if (script.startsWith("uri:classloader:")) {
FileResource urlResource = URLResource.create(loader, script);
FileResource urlResource = URLResource.create(loader, script, true);
stream = urlResource.inputStream();
} else {
File file = JRubyFile.create(getCurrentDirectory(), getScriptFileName());
Original file line number Diff line number Diff line change
@@ -174,7 +174,7 @@ private FoundLibrary findFileResourceWithLoadPath(String searchName, String suff
String pathWithSuffix = fullPath + suffix;

DebugLog.Resource.logTry(pathWithSuffix);
FileResource resource = JRubyFile.createResource(runtime, pathWithSuffix);
FileResource resource = JRubyFile.createResourceAsFile(runtime, pathWithSuffix);
if (resource.exists()) {
DebugLog.Resource.logFound(pathWithSuffix);
String scriptName = resolveScriptName(resource, pathWithSuffix);
12 changes: 10 additions & 2 deletions core/src/main/java/org/jruby/util/JRubyFile.java
Original file line number Diff line number Diff line change
@@ -63,11 +63,19 @@ public static FileResource createResource(ThreadContext context, String pathname
return createResource(context.runtime, pathname);
}

public static FileResource createResourceAsFile(Ruby runtime, String pathname) {
return createResource(runtime, runtime.getCurrentDirectory(), pathname, true);
}

public static FileResource createResource(Ruby runtime, String pathname) {
return createResource(runtime, runtime.getCurrentDirectory(), pathname);
return createResource(runtime, runtime.getCurrentDirectory(), pathname, false);
}

public static FileResource createResource(Ruby runtime, String cwd, String pathname) {
return createResource(runtime, cwd, pathname, false);
}

private static FileResource createResource(Ruby runtime, String cwd, String pathname, boolean isFile) {
FileResource emptyResource = EmptyFileResource.create(pathname);
if (emptyResource != null) return emptyResource;

@@ -87,7 +95,7 @@ public static FileResource createResource(Ruby runtime, String cwd, String pathn
}

// replace is needed for maven/jruby-complete/src/it/app_using_classpath_uri to work
if (pathname.startsWith("uri:")) return URLResource.create(runtime, pathname);
if (pathname.startsWith("uri:")) return URLResource.create(runtime, pathname, isFile);

if (pathname.startsWith("file:")) {
pathname = pathname.substring(5);
26 changes: 10 additions & 16 deletions core/src/main/java/org/jruby/util/URLResource.java
Original file line number Diff line number Diff line change
@@ -149,38 +149,38 @@ public Channel openChannel( ModeFlags flags, int perm ) throws ResourceException
return Channels.newChannel(inputStream());
}

public static FileResource create(ClassLoader cl, String pathname) {
public static FileResource create(ClassLoader cl, String pathname, boolean isFile) {
try
{
pathname = new URI(pathname.replaceFirst("^/*", "/")).normalize().getPath().replaceAll("^/([.][.]/)*", "");
} catch (URISyntaxException e) {
pathname = pathname.replaceAll("^[.]?/*", "");
}
URL url = cl.getResource(pathname);
String[] files = listClassLoaderFiles(cl, pathname);
String[] files = isFile ? null : listClassLoaderFiles(cl, pathname);
return new URLResource(URI_CLASSLOADER + pathname,
cl,
url == null ? null : pathname,
files);
}

public static FileResource createClassloaderURI(Ruby runtime, String pathname) {
return create(runtime.getJRubyClassLoader(), pathname);
public static FileResource createClassloaderURI(Ruby runtime, String pathname, boolean isFile) {
return create(runtime.getJRubyClassLoader(), pathname, isFile);
}

public static FileResource create(Ruby runtime, String pathname)
public static FileResource create(Ruby runtime, String pathname, boolean isFile)
{
if (!pathname.startsWith(URI)) {
return null;
}
pathname = pathname.substring(URI.length());
if (pathname.startsWith(CLASSLOADER)) {
return createClassloaderURI(runtime, pathname.substring(CLASSLOADER.length()));
return createClassloaderURI(runtime, pathname.substring(CLASSLOADER.length()), isFile);
}
return createRegularURI(pathname);
return createRegularURI(pathname, isFile);
}

private static FileResource createRegularURI(String pathname) {
private static FileResource createRegularURI(String pathname, boolean isFile) {
URL url;
try
{
@@ -200,7 +200,7 @@ private static FileResource createRegularURI(String pathname) {
// file does not exists
return new URLResource(URI + pathname, (URL)null, null);
}
String[] files = listFiles(pathname);
String[] files = isFile ? null : listFiles(pathname);
if (files != null) {
return new URLResource(URI + pathname, (URL)null, files);
}
@@ -252,12 +252,9 @@ private static String[] listFilesFromInputStream(InputStream is) {
}

private static String[] listClassLoaderFiles(ClassLoader classloader, String pathname) {
if (pathname.endsWith(".rb") || pathname.endsWith(".class") || pathname.endsWith(".jar")) {
return null;
}
try
{
pathname = pathname + (pathname.equals("") ? ".jrubydir" : "/.jrubydir");
pathname += pathname.equals("") ? ".jrubydir" : "/.jrubydir";
Enumeration<URL> urls = classloader.getResources(pathname);
if (!urls.hasMoreElements()) {
return null;
@@ -280,9 +277,6 @@ private static String[] listClassLoaderFiles(ClassLoader classloader, String pat
}

private static String[] listFiles(String pathname) {
if (pathname.endsWith(".rb") || pathname.endsWith(".class") || pathname.endsWith(".jar")) {
return null;
}
try
{
InputStream is = new URL(pathname + "/.jrubydir").openStream();
20 changes: 12 additions & 8 deletions core/src/test/java/org/jruby/util/URLResourceTest.java
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ public class URLResourceTest extends TestCase {

public void testDirectory(){
String uri = Thread.currentThread().getContextClassLoader().getResource( "somedir" ).toExternalForm();
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:" + uri);
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:" + uri, false);

assertNotNull(resource );
assertFalse(resource.isFile());
@@ -22,7 +22,7 @@ public void testDirectory(){

public void testNoneDirectory(){
String uri = Thread.currentThread().getContextClassLoader().getResource( "somedir/dir_without_listing" ).toExternalForm();
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:" + uri);
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:" + uri, false);

assertNotNull(resource );
// you can open streams on file-system directories
@@ -34,7 +34,7 @@ public void testNoneDirectory(){

public void testFile(){
String uri = Thread.currentThread().getContextClassLoader().getResource( "somedir/.jrubydir" ).toExternalForm();
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:" + uri);
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:" + uri, false);

assertNotNull(resource );
// you can open streams on file-system directories
@@ -46,7 +46,7 @@ public void testFile(){

public void testNonExistingFile(){
String uri = Thread.currentThread().getContextClassLoader().getResource( "somedir" ).toExternalForm();
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:" + uri + "/not_there");
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:" + uri + "/not_there", false);

assertNotNull(resource );
assertFalse(resource.isFile());
@@ -57,7 +57,8 @@ public void testNonExistingFile(){

public void testDirectoryClassloader()
{
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:classloader:/somedir");
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(),
"uri:classloader:/somedir", false);

assertNotNull( resource );
assertFalse( resource.isFile() );
@@ -70,7 +71,8 @@ public void testDirectoryClassloader()

public void testNoneDirectoryClassloader()
{
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:classloader:/somedir/dir_without_listing");
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(),
"uri:classloader:/somedir/dir_without_listing", false);

assertNotNull( resource );
// you can open streams on file-system directories
@@ -82,7 +84,8 @@ public void testNoneDirectoryClassloader()

public void testFileClassloader()
{
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:classloader:/somedir/.jrubydir" );
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(),
"uri:classloader:/somedir/.jrubydir", false );

assertNotNull( resource );
// you can open streams on file-system directories
@@ -94,7 +97,8 @@ public void testFileClassloader()

public void testNonExistingFileClassloader()
{
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(), "uri:classloader:/somedir/not_there" );
FileResource resource = URLResource.create(Ruby.getGlobalRuntime(),
"uri:classloader:/somedir/not_there", false );

assertNotNull( resource );
assertFalse( resource.isFile() );

0 comments on commit 9e79159

Please sign in to comment.