From eec5ed8348a9122f837ba437d681d90761e8217e Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 4 Mar 2011 16:31:26 -0600 Subject: [PATCH] For JRUBY-5558: Spike making include_package act like a virtual constant table, behaving properly for class reopening, defined?, hierarchical search, etc. --- .../shared/builtin/javasupport/core_ext/module.rb | 74 ++++++++++---------- src/org/jruby/java/lookup/JavaPackageModule.java | 41 +++++++++++ src/org/jruby/javasupport/Java.java | 2 + 3 files changed, 80 insertions(+), 37 deletions(-) create mode 100644 src/org/jruby/java/lookup/JavaPackageModule.java diff --git a/lib/ruby/site_ruby/shared/builtin/javasupport/core_ext/module.rb b/lib/ruby/site_ruby/shared/builtin/javasupport/core_ext/module.rb index 87a9713..a2ad749 100644 --- a/lib/ruby/site_ruby/shared/builtin/javasupport/core_ext/module.rb +++ b/lib/ruby/site_ruby/shared/builtin/javasupport/core_ext/module.rb @@ -7,43 +7,43 @@ class Module # package will become available in this class/module, unless a constant # with the same name as a Java class is already defined. # - def include_package(package_name) - if defined? @included_packages - @included_packages << package_name - return - end - @included_packages = [package_name] - @java_aliases ||= {} - - def self.const_missing(constant) - real_name = @java_aliases[constant] || constant - - java_class = nil - last_error = nil - - @included_packages.each do |package| - begin - java_class = JavaUtilities.get_java_class(package + '.' + real_name.to_s) - rescue NameError - # we only rescue NameError, since other errors should bubble out - last_error = $! - end - break if java_class - end - - if java_class - return JavaUtilities.create_proxy_class(constant, java_class, self) - else - # try to chain to super's const_missing - begin - return super - rescue NameError - # super didn't find anything either, raise our Java error - raise NameError.new("#{constant} not found in packages #{@included_packages.join(', ')}; last error: #{last_error.message}") - end - end - end - end +# def include_package(package_name) +# if defined? @included_packages +# @included_packages << package_name +# return +# end +# @included_packages = [package_name] +# @java_aliases ||= {} +# +# def self.const_missing(constant) +# real_name = @java_aliases[constant] || constant +# +# java_class = nil +# last_error = nil +# +# @included_packages.each do |package| +# begin +# java_class = JavaUtilities.get_java_class(package + '.' + real_name.to_s) +# rescue NameError +# # we only rescue NameError, since other errors should bubble out +# last_error = $! +# end +# break if java_class +# end +# +# if java_class +# return JavaUtilities.create_proxy_class(constant, java_class, self) +# else +# # try to chain to super's const_missing +# begin +# return super +# rescue NameError +# # super didn't find anything either, raise our Java error +# raise NameError.new("#{constant} not found in packages #{@included_packages.join(', ')}; last error: #{last_error.message}") +# end +# end +# end +# end # Imports the package specified by +package_name+, first by trying to scan JAR resources # for the file in question, and failing that by adding a const_missing hook diff --git a/src/org/jruby/java/lookup/JavaPackageModule.java b/src/org/jruby/java/lookup/JavaPackageModule.java new file mode 100644 index 0000000..9a6967d --- /dev/null +++ b/src/org/jruby/java/lookup/JavaPackageModule.java @@ -0,0 +1,41 @@ +package org.jruby.java.lookup; + +import org.jruby.Ruby; +import org.jruby.RubyModule; +import org.jruby.javasupport.Java; +import org.jruby.javasupport.JavaClass; +import org.jruby.runtime.builtin.IRubyObject; + +public class JavaPackageModule extends RubyModule { + private final String pkg; + public JavaPackageModule(Ruby runtime, String pkg) { + super(runtime, runtime.getModule()); + this.pkg = pkg; + } + + @Override + protected IRubyObject constantTableFetch(String name) { + IRubyObject value = super.constantTableFetch(name); + + if (value == null) { + // try looking up as a Java class using our package + try { + Class cls = Class.forName(pkg + "." + name, true, getRuntime().getJRubyClassLoader()); + value = Java.getProxyClass(getRuntime(), JavaClass.get(getRuntime(), cls)); + constantTableStore(name, value); + } catch (ClassNotFoundException cnfe) { + } + } + + for (; value == UNDEF; value = constantTableFetch(name)) { + if (resolveUndefConstant(getRuntime(), name) == null) return UNDEF; + } + + return value; + } + + @Override + protected IRubyObject constantTableFastFetch(String name) { + return constantTableFetch(name); + } +} diff --git a/src/org/jruby/javasupport/Java.java b/src/org/jruby/javasupport/Java.java index d956b8f..82e669e 100644 --- a/src/org/jruby/javasupport/Java.java +++ b/src/org/jruby/javasupport/Java.java @@ -83,6 +83,7 @@ import org.jruby.internal.runtime.methods.JavaMethod.JavaMethodN; import org.jruby.internal.runtime.methods.JavaMethod.JavaMethodZero; import org.jruby.java.addons.ArrayJavaAddons; import org.jruby.java.addons.IOJavaAddons; +import org.jruby.java.addons.ModuleJavaAddons; import org.jruby.java.addons.StringJavaAddons; import org.jruby.java.codegen.RealClassGenerator; import org.jruby.java.dispatch.CallableSelector; @@ -156,6 +157,7 @@ public class Java implements Library { runtime.getKernel().defineAnnotatedMethods(KernelJavaAddons.class); runtime.getString().defineAnnotatedMethods(StringJavaAddons.class); runtime.getIO().defineAnnotatedMethods(IOJavaAddons.class); + runtime.getModule().defineAnnotatedMethods(ModuleJavaAddons.class); if (runtime.getObject().isConstantDefined("StringIO")) { ((RubyClass)runtime.getObject().getConstant("StringIO")).defineAnnotatedMethods(IOJavaAddons.AnyIO.class); -- 1.7.1