package org.jruby.ext.jruby;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.List;
import org.jruby.*;
import org.jruby.anno.JRubyMethod;
import org.jruby.ast.util.ArgsUtil;
import org.jruby.exceptions.RaiseException;
import org.jruby.javasupport.Java;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.BasicLibraryService;
import org.jruby.runtime.load.Library;
import org.jruby.util.ClasspathLauncher;
import static org.jruby.util.URLUtil.getPath;
public class JRubyUtilLibrary implements Library {
public void load(Ruby runtime, boolean wrap) {
RubyModule JRuby = runtime.getOrCreateModule("JRuby");
RubyModule JRubyUtil = JRuby.defineModuleUnder("Util");
JRubyUtil.defineAnnotatedMethods(JRubyUtilLibrary.class);
JRubyUtil.setConstant("SEPARATOR", runtime.newString(org.jruby.util.cli.ArgumentProcessor.SEPARATOR));
JRubyUtil.setConstant("ON_WINDOWS", runtime.newBoolean(org.jruby.platform.Platform.IS_WINDOWS));
JRubyUtil.setConstant("ON_SOLARIS", runtime.newBoolean(org.jruby.platform.Platform.IS_SOLARIS));
}
@JRubyMethod(module = true)
public static IRubyObject gc(ThreadContext context, IRubyObject recv) {
System.gc();
return context.nil;
}
@JRubyMethod(name = { "objectspace", "object_space?" }, alias = { "objectspace?" }, module = true)
public static IRubyObject getObjectSpaceEnabled(IRubyObject recv) {
final Ruby runtime = recv.getRuntime();
return RubyBoolean.newBoolean(runtime, runtime.isObjectSpaceEnabled());
}
@JRubyMethod(name = { "objectspace=", "object_space=" }, module = true)
public static IRubyObject setObjectSpaceEnabled(IRubyObject recv, IRubyObject arg) {
final Ruby runtime = recv.getRuntime();
boolean enabled = arg.isTrue();
if (enabled) {
runtime.getWarnings().warn("ObjectSpace impacts performance. See http://wiki.jruby.org/PerformanceTuning#dont-enable-objectspace");
}
runtime.setObjectSpaceEnabled(enabled);
return runtime.newBoolean(enabled);
}
@JRubyMethod(meta = true, name = "native_posix?")
public static IRubyObject native_posix_p(ThreadContext context, IRubyObject self) {
return context.runtime.newBoolean(context.runtime.getPosix().isNative());
}
@Deprecated
public static IRubyObject getClassLoaderResources(IRubyObject recv, IRubyObject name) {
return class_loader_resources(recv.getRuntime().getCurrentContext(), recv, name);
}
@JRubyMethod(module = true, name = "class_loader_resources", alias = "classloader_resources", required = 1, optional = 1)
public static IRubyObject class_loader_resources(ThreadContext context, IRubyObject recv, IRubyObject... args) {
final Ruby runtime = context.runtime;
final ClassLoader loader = runtime.getJRubyClassLoader();
final String name = args[0].convertToString().asJavaString();
final RubyArray resources = RubyArray.newArray(runtime);
boolean raw = false, path = false;
if (args.length > 1 && args[1] instanceof RubyHash) {
IRubyObject[] values = ArgsUtil.extractKeywordArgs(context, (RubyHash) args[1], "raw", "path");
raw = values[0] != null && values[0].isTrue();
path = values[1] != null && values[1].isTrue();
}
try {
Enumeration<URL> e = loader.getResources(name);
while (e.hasMoreElements()) {
final URL entry = e.nextElement();
if (path) {
resources.append( RubyString.newString(runtime, getPath(entry)) );
} else if (raw) {
resources.append( Java.getInstance(runtime, entry) );
} else {
resources.append( RubyString.newString(runtime, entry.toString()) );
}
}
} catch (IOException ex) {
throw context.runtime.newIOErrorFromException(ex);
}
return resources;
}
@JRubyMethod(meta = true)
public static IRubyObject classpath_launcher(ThreadContext context, IRubyObject recv) {
final Ruby runtime = context.runtime;
String launcher = runtime.getInstanceConfig().getEnvironment().get("RUBY");
if ( launcher == null ) launcher = ClasspathLauncher.jrubyCommand(runtime);
return runtime.newString(launcher);
}
@JRubyMethod(name = "extra_gem_paths", meta = true)
public static IRubyObject (ThreadContext context, IRubyObject recv) {
final Ruby runtime = context.runtime;
final List<String> extraGemPaths = runtime.getInstanceConfig().getExtraGemPaths();
IRubyObject[] extra_gem_paths = new IRubyObject[extraGemPaths.size()];
int i = 0; for (String gemPath : extraGemPaths) {
extra_gem_paths[i++] = runtime.newString(gemPath);
}
return RubyArray.newArrayNoCopy(runtime, extra_gem_paths);
}
@JRubyMethod(name = "current_directory", meta = true)
public static IRubyObject current_directory(ThreadContext context, IRubyObject recv) {
final Ruby runtime = context.runtime;
return runtime.newString(runtime.getCurrentDirectory());
}
@JRubyMethod(name = "set_last_exit_status", meta = true)
public static IRubyObject set_last_exit_status(ThreadContext context, IRubyObject recv,
IRubyObject status, IRubyObject pid) {
RubyProcess.RubyStatus processStatus = RubyProcess.RubyStatus.newProcessStatus(context.runtime,
status.convertToInteger().getLongValue(),
pid.convertToInteger().getLongValue()
);
context.setLastExitStatus(processStatus);
return processStatus;
}
@JRubyMethod(meta = true, name = "set_meta_class")
public static IRubyObject set_meta_class(ThreadContext context, IRubyObject recv, IRubyObject obj, IRubyObject klass) {
if (!(klass instanceof RubyClass)) {
klass = klass.getMetaClass();
}
((RubyObject) obj).setMetaClass((RubyClass) klass);
return context.nil;
}
@JRubyMethod(module = true, name = { "load_ext" })
public static IRubyObject load_ext(ThreadContext context, IRubyObject recv, IRubyObject klass) {
if (klass instanceof RubySymbol) {
switch(((RubySymbol) klass).asJavaString()) {
case "string" : CoreExt.loadStringExtensions(context.runtime); return context.tru;
default : throw context.runtime.newArgumentError(':' + ((RubySymbol) klass).asJavaString());
}
}
return loadExtension(context.runtime, klass.convertToString().toString()) ? context.tru : context.fals;
}
private static boolean loadExtension(final Ruby runtime, final String className) {
Class<?> clazz = runtime.getJavaSupport().loadJavaClassQuiet(className);
if (BasicLibraryService.class.isAssignableFrom(clazz)) {
try {
return ((BasicLibraryService) clazz.newInstance()).basicLoad(runtime);
} catch (org.jruby.exceptions.Exception e) {
throw e;
} catch (ReflectiveOperationException e) {
final RaiseException ex = runtime.newNameError("cannot instantiate (ext) Java class " + className, className, e, true);
ex.initCause(e); throw ex;
} catch (Exception e) {
final RaiseException ex = runtime.newNameError("cannot load (ext) (" + className + ")", null, e, true);
ex.initCause(e); throw ex;
}
}
if (Library.class.isAssignableFrom(clazz)) {
try {
((Library) clazz.newInstance()).load(runtime, false);
return true;
} catch (org.jruby.exceptions.Exception e) {
throw e;
} catch (ReflectiveOperationException e) {
final RaiseException ex = runtime.newNameError("cannot instantiate (ext) Java class " + className, className, e, true);
ex.initCause(e);
throw ex;
} catch (java.lang.Exception e) {
final RaiseException ex = runtime.newNameError("cannot load (ext) (" + className + ")", null, e, true);
ex.initCause(e); throw ex;
}
}
try {
Object result = clazz.getMethod("load", Ruby.class).invoke(null, runtime);
return (result instanceof Boolean) && ! ((Boolean) result).booleanValue() ? false : true;
} catch (org.jruby.exceptions.Exception e) {
throw e;
} catch (java.lang.Exception e) {
final RaiseException ex = runtime.newNameError("cannot load (ext) (" + className + ")", null, e, true);
ex.initCause(e); throw ex;
}
}
@Deprecated
public static class StringUtils {
public static IRubyObject unseeded_hash(ThreadContext context, IRubyObject recv) {
return CoreExt.String.unseeded_hash(context, recv);
}
}
@JRubyMethod(name = "cache_stats", module = true)
public static IRubyObject cache_stats(ThreadContext context, IRubyObject self) {
Ruby runtime = context.runtime;
RubyHash stat = RubyHash.newHash(runtime);
stat.op_aset(context, runtime.newSymbol("method_invalidation_count"), runtime.newFixnum(runtime.getCaches().getMethodInvalidationCount()));
stat.op_aset(context, runtime.newSymbol("constant_invalidation_count"), runtime.newFixnum(runtime.getCaches().getConstantInvalidationCount()));
return stat;
}
@JRubyMethod(module = true)
@Deprecated
public static RubyArray internal_libraries(ThreadContext context, IRubyObject self) {
Ruby runtime = context.runtime;
runtime.getWarnings().warn("JRuby::Util.internal_libraries is deprecated");
return runtime.newEmptyArray();
}
}