Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
mkristian committed Jul 25, 2014
1 parent 3ada3d9 commit d87e197
Showing 10 changed files with 146 additions and 77 deletions.
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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 {
@@ -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;
}
}
@@ -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);
@@ -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();
}

@@ -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
@@ -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);
4 changes: 3 additions & 1 deletion core/src/main/java/org/jruby/util/ClasspathResource.java
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@

import java.net.URL;

import org.jruby.runtime.load.ExtendedFileResource;

class ClasspathResource extends URLResource {

private static final String CLASSPATH = "classpath:/";
@@ -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;
15 changes: 12 additions & 3 deletions core/src/main/java/org/jruby/util/EmptyFileResource.java
Original file line number Diff line number Diff line change
@@ -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();
@@ -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
Original file line number Diff line number Diff line change
@@ -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}.
46 changes: 46 additions & 0 deletions core/src/main/java/org/jruby/util/FileResourceFactory.java
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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) {
25 changes: 21 additions & 4 deletions core/src/main/java/org/jruby/util/JarResource.java
Original file line number Diff line number Diff line change
@@ -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();
@@ -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
27 changes: 22 additions & 5 deletions core/src/main/java/org/jruby/util/RegularFileResource.java
Original file line number Diff line number Diff line change
@@ -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();

@@ -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;
}
}
}
11 changes: 9 additions & 2 deletions core/src/main/java/org/jruby/util/URLResource.java
Original file line number Diff line number Diff line change
@@ -8,10 +8,11 @@
import jnr.posix.FileStat;
import jnr.posix.POSIX;

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

class URLResource implements FileResource {
class URLResource implements ExtendedFileResource {

private final URL url;

@@ -119,7 +120,7 @@ public ChannelDescriptor openDescriptor(ModeFlags flags, POSIX posix, int perm)
return null;
}

public static FileResource create(String pathname)
public static ExtendedFileResource create(String pathname)
{
URL url;
try
@@ -136,5 +137,11 @@ public static FileResource create(String pathname)
return null;
}
}

@Override
public URL getURL()
{
return url;
}

}

0 comments on commit d87e197

Please sign in to comment.