Skip to content

Commit

Permalink
have an ExtendedFileResource which keeps the URL of reource to load j…
Browse files Browse the repository at this point in the history
…ar files
  • Loading branch information
mkristian committed Jul 25, 2014
1 parent 3ada3d9 commit d87e197
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 77 deletions.
@@ -0,0 +1,9 @@
package org.jruby.runtime.load;

import java.net.URL;

import org.jruby.util.FileResource;

public interface ExtendedFileResource extends FileResource {
URL getURL();
}
47 changes: 17 additions & 30 deletions core/src/main/java/org/jruby/runtime/load/LibrarySearcher.java
@@ -1,21 +1,21 @@
package org.jruby.runtime.load;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;

import org.jruby.Ruby;
import org.jruby.RubyHash;
import org.jruby.RubyString;
import org.jruby.ast.executable.Script;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.LoadService.SuffixType;
import org.jruby.util.FileResource;
import org.jruby.util.FileResourceFactory;
import org.jruby.util.JRubyFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Map;

class LibrarySearcher {
static class Ruby18 extends LibrarySearcher {
Expand All @@ -24,12 +24,12 @@ public Ruby18(LoadService loadService) {
}

@Override
protected String resolveLoadName(FileResource unused, String ruby18Path) {
protected String resolveLoadName(ExtendedFileResource unused, String ruby18Path) {
return ruby18Path;
}

@Override
protected String resolveScriptName(FileResource unused, String ruby18Path) {
protected String resolveScriptName(ExtendedFileResource unused, String ruby18Path) {
return ruby18Path;
}
}
Expand Down Expand Up @@ -158,7 +158,7 @@ private FoundLibrary findFileResourceWithLoadPath(String searchName, String suff
String pathWithSuffix = fullPath + suffix;

DebugLog.Resource.logTry(pathWithSuffix);
FileResource resource = JRubyFile.createResource(runtime, pathWithSuffix);
ExtendedFileResource resource = FileResourceFactory.createResource(runtime, pathWithSuffix);
if (resource.exists()) {
DebugLog.Resource.logFound(pathWithSuffix);
String scriptName = resolveScriptName(resource, pathWithSuffix);
Expand Down Expand Up @@ -189,11 +189,11 @@ private static boolean isAbsolute(String path) {
return new File(path).isAbsolute();
}

protected String resolveLoadName(FileResource resource, String ruby18path) {
protected String resolveLoadName(ExtendedFileResource resource, String ruby18path) {
return resource.absolutePath();
}

protected String resolveScriptName(FileResource resource, String ruby18Path) {
protected String resolveScriptName(ExtendedFileResource resource, String ruby18Path) {
return resource.absolutePath();
}

Expand All @@ -202,11 +202,13 @@ static class ResourceLibrary implements Library {
private final String scriptName;
private final InputStream is;
private final String location;
private final URL url;

public ResourceLibrary(String searchName, String scriptName, FileResource resource) {
public ResourceLibrary(String searchName, String scriptName, ExtendedFileResource resource) {
this.searchName = searchName;
this.scriptName = scriptName;
this.location = resource.absolutePath();
this.url = resource.getURL();

// getInputStream may return a null to denote that it cannot really read the resource.
// We should raise LoadError in the end, but probably only once we actually try to load
Expand Down Expand Up @@ -245,22 +247,7 @@ private void loadClass(Ruby runtime, boolean wrap) {
}

private void loadJar(Ruby runtime, boolean wrap) {
try {
URL url;
File f = new File(location);
if (f.exists() || location.contains( "!")){
url = f.toURI().toURL();
if ( location.contains( "!") ) {
url = new URL( "jar:" + url );
}
}
else {
url = new URL(location);
}
runtime.getJRubyClassLoader().addURL(url);
} catch (MalformedURLException badUrl) {
runtime.newIOErrorFromException(badUrl);
}
runtime.getJRubyClassLoader().addURL(url);

// If an associated Service library exists, load it as well
ClassExtensionLibrary serviceExtension = ClassExtensionLibrary.tryFind(runtime, searchName);
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/java/org/jruby/util/ClasspathResource.java
Expand Up @@ -2,6 +2,8 @@

import java.net.URL;

import org.jruby.runtime.load.ExtendedFileResource;

class ClasspathResource extends URLResource {

private static final String CLASSPATH = "classpath:/";
Expand All @@ -12,7 +14,7 @@ class ClasspathResource extends URLResource {
super(url);
}

public static FileResource create(String pathname)
public static ExtendedFileResource create(String pathname)
{
if (!pathname.startsWith(CLASSPATH)) {
return null;
Expand Down
15 changes: 12 additions & 3 deletions core/src/main/java/org/jruby/util/EmptyFileResource.java
@@ -1,13 +1,16 @@
package org.jruby.util;

import java.io.InputStream;
import java.net.URL;

import jnr.posix.FileStat;
import jnr.posix.POSIX;
import org.jruby.runtime.ThreadContext;

import org.jruby.runtime.load.ExtendedFileResource;
import org.jruby.util.io.ChannelDescriptor;
import org.jruby.util.io.ModeFlags;
import java.io.InputStream;

class EmptyFileResource implements FileResource {
class EmptyFileResource implements ExtendedFileResource {
// All empty resources are the same and immutable, so may as well
// cache the instance
private static final EmptyFileResource INSTANCE = new EmptyFileResource();
Expand Down Expand Up @@ -94,4 +97,10 @@ public InputStream getInputStream() {
public ChannelDescriptor openDescriptor(ModeFlags flags, POSIX posix, int perm) throws ResourceException {
throw new ResourceException.NotFound(absolutePath());
}

@Override
public URL getURL()
{
return null;
}
}
4 changes: 3 additions & 1 deletion core/src/main/java/org/jruby/util/FileResource.java
@@ -1,10 +1,12 @@
package org.jruby.util;

import java.io.InputStream;

import jnr.posix.FileStat;
import jnr.posix.POSIX;

import org.jruby.util.io.ChannelDescriptor;
import org.jruby.util.io.ModeFlags;
import java.io.InputStream;

/**
* This is a shared interface for files loaded as {@link java.io.File} and {@link java.util.zip.ZipEntry}.
Expand Down
46 changes: 46 additions & 0 deletions core/src/main/java/org/jruby/util/FileResourceFactory.java
@@ -0,0 +1,46 @@
package org.jruby.util;

import org.jruby.Ruby;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.load.ExtendedFileResource;

public class FileResourceFactory {
public static ExtendedFileResource createResource(ThreadContext context, String pathname) {
return createResource(context.runtime, pathname);
}

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

public static ExtendedFileResource createResource(String cwd, String pathname) {
ExtendedFileResource emptyResource = EmptyFileResource.create(pathname);
if (emptyResource != null) {
return emptyResource;
}

ExtendedFileResource jarResource = JarResource.create(pathname);
if (jarResource != null) {
return jarResource;
}

// HACK turn the pathname into something meaningful in case of being an URI
ExtendedFileResource cpResource = ClasspathResource.create(pathname.replace(cwd == null ? "" : cwd, "" ));
if (cpResource != null) {
return cpResource;
}

// HACK this codes get triggers by LoadService via findOnClasspath, so remove the prefix to get the uri
ExtendedFileResource urlResource = URLResource.create(pathname.replace("classpath:/", ""));
if (urlResource != null) {
return urlResource;
}

if (pathname.startsWith("file:")) {
pathname = pathname.substring(5);
}

// If any other special resource types fail, count it as a filesystem backed resource.
return new RegularFileResource(JRubyFile.create(cwd, pathname));
}
}
35 changes: 4 additions & 31 deletions core/src/main/java/org/jruby/util/JRubyFile.java
Expand Up @@ -53,48 +53,21 @@
*/
public class JRubyFile extends JavaSecuredFile {
private static final long serialVersionUID = 435364547567567L;

public static JRubyFile create(String cwd, String pathname) {
return createNoUnicodeConversion(cwd, pathname);
}

public static FileResource createResource(ThreadContext context, String pathname) {
return createResource(context.runtime, pathname);
return FileResourceFactory.createResource(context.runtime, pathname);
}

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

public static FileResource createResource(String cwd, String pathname) {
FileResource emptyResource = EmptyFileResource.create(pathname);
if (emptyResource != null) {
return emptyResource;
}

FileResource jarResource = JarResource.create(pathname);
if (jarResource != null) {
return jarResource;
}

// HACK turn the pathname into something meaningful in case of being an URI
FileResource cpResource = ClasspathResource.create(pathname.replace(cwd == null ? "" : cwd, "" ));
if (cpResource != null) {
return cpResource;
}

// HACK this codes get triggers by LoadService via findOnClasspath, so remove the prefix to get the uri
FileResource urlResource = URLResource.create(pathname.replace("classpath:/", ""));
if (urlResource != null) {
return urlResource;
}

if (pathname.startsWith("file:")) {
pathname = pathname.substring(5);
}

// If any other special resource types fail, count it as a filesystem backed resource.
return new RegularFileResource(create(cwd, pathname));
return FileResourceFactory.createResource(cwd, pathname);
}

public static String normalizeSeps(String path) {
Expand Down
25 changes: 21 additions & 4 deletions core/src/main/java/org/jruby/util/JarResource.java
@@ -1,16 +1,20 @@
package org.jruby.util;

import jnr.posix.FileStat;
import jnr.posix.POSIX;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.jar.JarEntry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

abstract class JarResource implements FileResource {
import jnr.posix.FileStat;
import jnr.posix.POSIX;

import org.jruby.runtime.load.ExtendedFileResource;

abstract class JarResource implements ExtendedFileResource {
private static Pattern PREFIX_MATCH = Pattern.compile("^(?:jar:)?(?:file:)?(.*)$");

private static final JarCache jarCache = new JarCache();
Expand Down Expand Up @@ -85,6 +89,19 @@ public String absolutePath() {
return jarPrefix + entryName();
}

@Override
public URL getURL()
{
try
{
return new URL( "jar:" + absolutePath() );
}
catch (MalformedURLException e)
{
return null;
}
}

@Override
public boolean exists() {
// If a jar resource got created, then it always corresponds to some kind of resource
Expand Down
27 changes: 22 additions & 5 deletions core/src/main/java/org/jruby/util/RegularFileResource.java
@@ -1,25 +1,29 @@
package org.jruby.util;

import jnr.posix.FileStat;
import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.FileChannel;

import jnr.posix.FileStat;
import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;

import org.jruby.runtime.load.ExtendedFileResource;
import org.jruby.util.io.ChannelDescriptor;
import org.jruby.util.io.ModeFlags;

/**
* Represents a "regular" file, backed by regular file system.
*/
class RegularFileResource implements FileResource {
class RegularFileResource implements ExtendedFileResource {
private final JRubyFile file;
private final POSIX symlinkPosix = POSIXFactory.getPOSIX();

Expand Down Expand Up @@ -234,4 +238,17 @@ private ChannelDescriptor createDescriptor(ModeFlags flags) throws ResourceExcep

return new ChannelDescriptor(fileChannel, flags, fileDescriptor, isInAppendMode);
}

@Override
public URL getURL()
{
try
{
return new File(absolutePath()).toURI().toURL();
}
catch (MalformedURLException e)
{
return null;
}
}
}

0 comments on commit d87e197

Please sign in to comment.