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.
  • Loading branch information
mkristian committed May 30, 2015
1 parent f29d80c commit 9e79159
Show file tree
Hide file tree
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
Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
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
Expand Up @@ -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;

Expand All @@ -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);
Expand Down
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
Expand Up @@ -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
{
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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();
Expand Down
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
Expand Up @@ -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());
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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());
Expand All @@ -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() );
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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() );
Expand Down

0 comments on commit 9e79159

Please sign in to comment.