package org.jruby.runtime.load;
import org.jruby.Ruby;
import org.jruby.ir.IRScope;
import org.jruby.util.JRubyClassLoader;
import org.jruby.util.OneShotClassLoader;
import org.objectweb.asm.ClassReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import static org.jruby.RubyFile.canonicalize;
import static org.jruby.util.JRubyFile.normalizeSeps;
public class CompiledScriptLoader {
public static IRScope loadScriptFromFile(Ruby runtime, InputStream inStream, File resourcePath, String resourceName, boolean isAbsolute) {
String name = getFilenameFromPathAndName(resourcePath, resourceName, isAbsolute);
try {
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) {
if (runtime.getDebug().isTrue()) {
e.printStackTrace();
}
throw runtime.newLoadError(name + " is not compiled Ruby; use java_import to load normal classes");
}
} 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 '" + name + "': " + le);
} finally {
try {
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) {
return normalizeSeps(resourcePath != null && !isAbsolute ? canonicalize(resourcePath.getPath()) : resourceName);
}
}