Skip to content

Commit

Permalink
Cleanup filename and load logic for precompiled scripts.
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Jul 6, 2015
1 parent 32ef1f0 commit bce9d5c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 48 deletions.
74 changes: 39 additions & 35 deletions core/src/main/java/org/jruby/runtime/load/CompiledScriptLoader.java
Expand Up @@ -6,10 +6,8 @@
package org.jruby.runtime.load;

import org.jruby.Ruby;
import org.jruby.RubyFile;
import org.jruby.ir.IRScope;
import org.jruby.util.JRubyClassLoader;
import org.jruby.util.JRubyFile;
import org.jruby.util.OneShotClassLoader;
import org.objectweb.asm.ClassReader;

Expand All @@ -28,57 +26,63 @@
*/
public class CompiledScriptLoader {
public static IRScope loadScriptFromFile(Ruby runtime, InputStream inStream, File resourcePath, String resourceName, boolean isAbsolute) {
InputStream in = null;
String name = getFilenameFromPathAndName(resourcePath, resourceName, isAbsolute);
try {
in = new BufferedInputStream(inStream, 8192);
String name = normalizeSeps(resourceName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[8196];
int read = 0;
while ((read = in.read(buf)) != -1) {
baos.write(buf, 0, read);
}
buf = baos.toByteArray();
JRubyClassLoader jcl = runtime.getJRubyClassLoader();
OneShotClassLoader oscl = new OneShotClassLoader(jcl);

ClassReader cr = new ClassReader(buf);
String className = cr.getClassName().replace('/', '.');

Class clazz = oscl.defineClass(className, buf);

File path = resourcePath;

if(path != null && !isAbsolute) {
// Note: We use RubyFile's canonicalize rather than Java's,
// because Java's will follow symlinks and result in __FILE__
// being set to the target of the symlink rather than the
// filename provided.
name = normalizeSeps(canonicalize(path.getPath()));
}
Class clazz = loadCompiledScriptFromClass(runtime, inStream);

try {
Method method = clazz.getMethod("loadIR", Ruby.class, String.class);
return (IRScope)method.invoke(null, runtime, name);
} catch (Exception e) {
e.printStackTrace();
// fall through
if (runtime.getDebug().isTrue()) {
e.printStackTrace();
}
throw runtime.newLoadError(name + " is not compiled Ruby; use java_import to load normal classes");
}

throw runtime.newLoadError("use `java_import' to load normal Java classes: "+className);
} catch (IOException e) {
throw runtime.newIOErrorFromException(e);
} catch (LinkageError le) {
if (runtime.getDebug().isTrue()) {
le.printStackTrace();
}
throw runtime.newLoadError("Linkage error loading compiled script; you may need to recompile '" + resourceName + "': " + le);
throw runtime.newLoadError("Linkage error loading compiled script; you may need to recompile '" + name + "': " + le);
} finally {
try {
in.close();
inStream.close();
} catch (IOException ioe) {
throw runtime.newIOErrorFromException(ioe);
}
}
}

private static Class loadCompiledScriptFromClass(Ruby runtime, InputStream in) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[8192];
int read;
while ((read = in.read(buf)) != -1) {
baos.write(buf, 0, read);
}
buf = baos.toByteArray();
JRubyClassLoader jcl = runtime.getJRubyClassLoader();
OneShotClassLoader oscl = new OneShotClassLoader(jcl);

ClassReader cr = new ClassReader(buf);
String className = cr.getClassName().replace('/', '.');

return oscl.defineClass(className, buf);
}

public static String getFilenameFromPathAndName(File resourcePath, String resourceName, boolean isAbsolute) {
String name = normalizeSeps(resourceName);
File path = resourcePath;

if(path != null && !isAbsolute) {
// Note: We use RubyFile's canonicalize rather than Java's,
// because Java's will follow symlinks and result in __FILE__
// being set to the target of the symlink rather than the
// filename provided.
name = normalizeSeps(canonicalize(path.getPath()));
}
return name;
}
}
14 changes: 2 additions & 12 deletions core/src/main/java/org/jruby/runtime/load/ExternalScript.java
Expand Up @@ -48,25 +48,15 @@ public void load(Ruby runtime, boolean wrap) {
InputStream in = null;
try {
in = resource.getInputStream();
String name = normalizeSeps(resource.getName());
String name = resource.getName();

if (runtime.getInstanceConfig().getCompileMode().shouldPrecompileAll()) {
runtime.compileAndLoadFile(name, in, wrap);
} else {
java.io.File path = resource.getPath();

if(path != null && !resource.isAbsolute()) {
// Note: We use RubyFile's canonicalize rather than Java's,
// because Java's will follow symlinks and result in __FILE__
// being set to the target of the symlink rather than the
// filename provided.
name = normalizeSeps(canonicalize(path.getPath()));
}
name = CompiledScriptLoader.getFilenameFromPathAndName(resource.getPath(), name, resource.isAbsolute());

runtime.loadFile(name, new LoadServiceResourceInputStream(in), wrap);
}


} catch (IOException e) {
throw runtime.newIOErrorFromException(e);
} finally {
Expand Down
Expand Up @@ -268,7 +268,7 @@ public void load(Ruby runtime, boolean wrap) {
// Depending on the side-effect of the load, which loads the class but does not turn it into a script.
// I don't like it, but until we restructure the code a bit more, we'll need to quietly let it by here.
if (script == null) return;

runtime.loadScope(script, wrap);
} catch(IOException e) {
throw runtime.newLoadError("no such file to load -- " + searchName, searchName);
Expand Down

0 comments on commit bce9d5c

Please sign in to comment.