RubyModule.java

  1. /*
  2.  **** BEGIN LICENSE BLOCK *****
  3.  * Version: EPL 1.0/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Eclipse Public
  6.  * License Version 1.0 (the "License"); you may not use this file
  7.  * except in compliance with the License. You may obtain a copy of
  8.  * the License at http://www.eclipse.org/legal/epl-v10.html
  9.  *
  10.  * Software distributed under the License is distributed on an "AS
  11.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  12.  * implied. See the License for the specific language governing
  13.  * rights and limitations under the License.
  14.  *
  15.  * Copyright (C) 2001 Chad Fowler <chadfowler@chadfowler.com>
  16.  * Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
  17.  * Copyright (C) 2001-2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
  18.  * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
  19.  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
  20.  * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
  21.  * Copyright (C) 2004-2005 Charles O Nutter <headius@headius.com>
  22.  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
  23.  * Copyright (C) 2006-2007 Miguel Covarrubias <mlcovarrubias@gmail.com>
  24.  * Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com>
  25.  *
  26.  * Alternatively, the contents of this file may be used under the terms of
  27.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  28.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29.  * in which case the provisions of the GPL or the LGPL are applicable instead
  30.  * of those above. If you wish to allow use of your version of this file only
  31.  * under the terms of either the GPL or the LGPL, and not to allow others to
  32.  * use your version of this file under the terms of the EPL, indicate your
  33.  * decision by deleting the provisions above and replace them with the notice
  34.  * and other provisions required by the GPL or the LGPL. If you do not delete
  35.  * the provisions above, a recipient may use your version of this file under
  36.  * the terms of any one of the EPL, the GPL or the LGPL.
  37.  ***** END LICENSE BLOCK *****/
  38. package org.jruby;

  39. import org.jcodings.Encoding;
  40. import org.jruby.anno.AnnotationBinder;
  41. import org.jruby.anno.AnnotationHelper;
  42. import org.jruby.anno.JRubyClass;
  43. import org.jruby.anno.JRubyConstant;
  44. import org.jruby.anno.JRubyMethod;
  45. import org.jruby.anno.JavaMethodDescriptor;
  46. import org.jruby.anno.TypePopulator;
  47. import org.jruby.common.IRubyWarnings.ID;
  48. import org.jruby.common.RubyWarnings;
  49. import org.jruby.embed.Extension;
  50. import org.jruby.exceptions.RaiseException;
  51. import org.jruby.internal.runtime.methods.AliasMethod;
  52. import org.jruby.internal.runtime.methods.AttrReaderMethod;
  53. import org.jruby.internal.runtime.methods.AttrWriterMethod;
  54. import org.jruby.internal.runtime.methods.CacheableMethod;
  55. import org.jruby.internal.runtime.methods.CallConfiguration;
  56. import org.jruby.internal.runtime.methods.DynamicMethod;
  57. import org.jruby.internal.runtime.methods.Framing;
  58. import org.jruby.internal.runtime.methods.JavaMethod;
  59. import org.jruby.internal.runtime.methods.ProcMethod;
  60. import org.jruby.internal.runtime.methods.Scoping;
  61. import org.jruby.internal.runtime.methods.SynchronizedDynamicMethod;
  62. import org.jruby.internal.runtime.methods.UndefinedMethod;
  63. import org.jruby.internal.runtime.methods.WrapperMethod;
  64. import org.jruby.parser.StaticScope;
  65. import org.jruby.runtime.Arity;
  66. import org.jruby.runtime.Block;
  67. import org.jruby.runtime.CallSite;
  68. import org.jruby.runtime.ClassIndex;
  69. import org.jruby.runtime.Helpers;
  70. import org.jruby.runtime.MethodFactory;
  71. import org.jruby.runtime.MethodIndex;
  72. import org.jruby.runtime.ObjectAllocator;
  73. import org.jruby.runtime.ThreadContext;
  74. import org.jruby.runtime.Visibility;
  75. import org.jruby.runtime.builtin.IRubyObject;
  76. import org.jruby.runtime.builtin.Variable;
  77. import org.jruby.runtime.callsite.CacheEntry;
  78. import org.jruby.runtime.callsite.FunctionalCachingCallSite;
  79. import org.jruby.runtime.ivars.MethodData;
  80. import org.jruby.runtime.load.IAutoloadMethod;
  81. import org.jruby.runtime.marshal.MarshalStream;
  82. import org.jruby.runtime.marshal.UnmarshalStream;
  83. import org.jruby.runtime.opto.Invalidator;
  84. import org.jruby.runtime.opto.OptoFactory;
  85. import org.jruby.runtime.profile.MethodEnhancer;
  86. import org.jruby.util.ClassProvider;
  87. import org.jruby.util.IdUtil;
  88. import org.jruby.util.TypeConverter;
  89. import org.jruby.util.cli.Options;
  90. import org.jruby.util.collections.WeakHashSet;
  91. import org.jruby.util.log.Logger;
  92. import org.jruby.util.log.LoggerFactory;

  93. import java.lang.reflect.Field;
  94. import java.lang.reflect.Method;
  95. import java.lang.reflect.Modifier;
  96. import java.security.AccessControlException;
  97. import java.util.ArrayList;
  98. import java.util.Arrays;
  99. import java.util.Collection;
  100. import java.util.Collections;
  101. import java.util.HashMap;
  102. import java.util.HashSet;
  103. import java.util.List;
  104. import java.util.Map;
  105. import java.util.Set;
  106. import java.util.concurrent.ConcurrentHashMap;
  107. import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

  108. import static org.jruby.anno.FrameField.*;
  109. import static org.jruby.runtime.Visibility.*;


  110. /**
  111.  *
  112.  * @author  jpetersen
  113.  */
  114. @JRubyClass(name="Module")
  115. public class RubyModule extends RubyObject {

  116.     private static final Logger LOG = LoggerFactory.getLogger("RubyModule");

  117.     private static final boolean DEBUG = false;
  118.     protected static final String ERR_INSECURE_SET_CONSTANT  = "Insecure: can't modify constant";
  119.     protected static final String ERR_FROZEN_CONST_TYPE = "class/module ";

  120.     public static final ObjectAllocator MODULE_ALLOCATOR = new ObjectAllocator() {
  121.         @Override
  122.         public IRubyObject allocate(Ruby runtime, RubyClass klass) {
  123.             return new RubyModule(runtime, klass);
  124.         }
  125.     };
  126.    
  127.     public static RubyClass createModuleClass(Ruby runtime, RubyClass moduleClass) {
  128.         moduleClass.setClassIndex(ClassIndex.MODULE);
  129.         moduleClass.setReifiedClass(RubyModule.class);
  130.         moduleClass.kindOf = new RubyModule.JavaClassKindOf(RubyModule.class);
  131.        
  132.         moduleClass.defineAnnotatedMethods(RubyModule.class);
  133.         moduleClass.defineAnnotatedMethods(ModuleKernelMethods.class);

  134.         return moduleClass;
  135.     }

  136.     public void checkValidBindTargetFrom(ThreadContext context, RubyModule originModule) throws RaiseException {
  137.         if (!this.hasModuleInHierarchy(originModule)) {
  138.             if (originModule instanceof MetaClass) {
  139.                 throw context.runtime.newTypeError("can't bind singleton method to a different class");
  140.             } else {
  141.                 throw context.runtime.newTypeError("bind argument must be an instance of " + originModule.getName());
  142.             }
  143.         }
  144.     }
  145.    
  146.     /**
  147.      * Get the ClassIndex for this class. Will be NO_CLASS for non-core types.
  148.      */
  149.     public ClassIndex getClassIndex() {
  150.         return classIndex;
  151.     }

  152.     /**
  153.      * Set the ClassIndex for this core class. Only used at boot time for core
  154.      * types.
  155.      *
  156.      * @param classIndex the ClassIndex for this type
  157.      */
  158.     @SuppressWarnings("deprecated")
  159.     void setClassIndex(ClassIndex classIndex) {
  160.         this.classIndex = classIndex;
  161.         this.index = classIndex.ordinal();
  162.     }
  163.    
  164.     public static class ModuleKernelMethods {
  165.         @JRubyMethod
  166.         public static IRubyObject autoload(IRubyObject recv, IRubyObject arg0, IRubyObject arg1) {
  167.             return RubyKernel.autoload(recv, arg0, arg1);
  168.         }
  169.        
  170.         @JRubyMethod(name = "autoload?")
  171.         public static IRubyObject autoload_p(ThreadContext context, IRubyObject recv, IRubyObject arg0) {
  172.             return RubyKernel.autoload_p(context, recv, arg0);
  173.         }
  174.     }
  175.    
  176.     @Override
  177.     public ClassIndex getNativeClassIndex() {
  178.         return ClassIndex.MODULE;
  179.     }

  180.     @Override
  181.     public boolean isModule() {
  182.         return true;
  183.     }

  184.     @Override
  185.     public boolean isClass() {
  186.         return false;
  187.     }

  188.     public boolean isSingleton() {
  189.         return false;
  190.     }

  191.     public static class KindOf {
  192.         public static final KindOf DEFAULT_KIND_OF = new KindOf();
  193.         public boolean isKindOf(IRubyObject obj, RubyModule type) {
  194.             return obj.getMetaClass().hasModuleInHierarchy(type);
  195.         }
  196.     }

  197.     public static final class JavaClassKindOf extends RubyModule.KindOf {
  198.         private final Class klass;

  199.         public JavaClassKindOf(Class klass) {
  200.             this.klass = klass;
  201.         }

  202.         @Override
  203.         public boolean isKindOf(IRubyObject obj, RubyModule type) {
  204.             return klass.isInstance(obj);
  205.         }
  206.     }

  207.     public boolean isInstance(IRubyObject object) {
  208.         return kindOf.isKindOf(object, this);
  209.     }

  210.     public Map<String, ConstantEntry> getConstantMap() {
  211.         return constants;
  212.     }

  213.     public synchronized Map<String, ConstantEntry> getConstantMapForWrite() {
  214.         return constants == Collections.EMPTY_MAP ? constants = new ConcurrentHashMap<String, ConstantEntry>(4, 0.9f, 1) : constants;
  215.     }
  216.    
  217.     /**
  218.      * AutoloadMap must be accessed after checking ConstantMap. Checking UNDEF value in constantMap works as a guard.
  219.      * For looking up constant, check constantMap first then try to get an Autoload object from autoloadMap.
  220.      * For setting constant, update constantMap first and remove an Autoload object from autoloadMap.
  221.      */
  222.     private Map<String, Autoload> getAutoloadMap() {
  223.         return autoloads;
  224.     }
  225.    
  226.     private synchronized Map<String, Autoload> getAutoloadMapForWrite() {
  227.         return autoloads == Collections.EMPTY_MAP ? autoloads = new ConcurrentHashMap<String, Autoload>(4, 0.9f, 1) : autoloads;
  228.     }
  229.    
  230.     public void addIncludingHierarchy(IncludedModule hierarchy) {
  231.         synchronized (getRuntime().getHierarchyLock()) {
  232.             Set<RubyClass> oldIncludingHierarchies = includingHierarchies;
  233.             if (oldIncludingHierarchies == Collections.EMPTY_SET) includingHierarchies = oldIncludingHierarchies = new WeakHashSet(4);
  234.             oldIncludingHierarchies.add(hierarchy);
  235.         }
  236.     }

  237.     /** separate path for MetaClass construction
  238.      *
  239.      */
  240.     protected RubyModule(Ruby runtime, RubyClass metaClass, boolean objectSpace) {
  241.         super(runtime, metaClass, objectSpace);
  242.         id = runtime.allocModuleId();
  243.         runtime.addModule(this);
  244.         // if (parent == null) parent = runtime.getObject();
  245.         setFlag(USER7_F, !isClass());
  246.         generationObject = generation = runtime.getNextModuleGeneration();

  247.         if (runtime.getInstanceConfig().isProfiling()) {
  248.             cacheEntryFactory = new ProfilingCacheEntryFactory(runtime, NormalCacheEntryFactory);
  249.         } else {
  250.             cacheEntryFactory = NormalCacheEntryFactory;
  251.         }
  252.        
  253.         // set up an invalidator for use in new optimization strategies
  254.         methodInvalidator = OptoFactory.newMethodInvalidator(this);
  255.     }
  256.    
  257.     /** used by MODULE_ALLOCATOR and RubyClass constructors
  258.      *
  259.      */
  260.     protected RubyModule(Ruby runtime, RubyClass metaClass) {
  261.         this(runtime, metaClass, runtime.isObjectSpaceEnabled());
  262.     }
  263.    
  264.     /** standard path for Module construction
  265.      *
  266.      */
  267.     protected RubyModule(Ruby runtime) {
  268.         this(runtime, runtime.getModule());
  269.     }

  270.     public boolean needsImplementer() {
  271.         return getFlag(USER7_F);
  272.     }
  273.    
  274.     /** rb_module_new
  275.      *
  276.      */
  277.     public static RubyModule newModule(Ruby runtime) {
  278.         return new RubyModule(runtime);
  279.     }
  280.    
  281.     /** rb_module_new/rb_define_module_id/rb_name_class/rb_set_class_path
  282.      *
  283.      */
  284.     public static RubyModule newModule(Ruby runtime, String name, RubyModule parent, boolean setParent) {
  285.         RubyModule module = newModule(runtime);
  286.         module.setBaseName(name);
  287.         if (setParent) module.setParent(parent);
  288.         parent.setConstant(name, module);
  289.         return module;
  290.     }
  291.    
  292.     // synchronized method per JRUBY-1173 (unsafe Double-Checked Locking)
  293.     // FIXME: synchronization is still wrong in CP code
  294.     public synchronized void addClassProvider(ClassProvider provider) {
  295.         if (!classProviders.contains(provider)) {
  296.             Set<ClassProvider> cp = new HashSet<ClassProvider>(classProviders);
  297.             cp.add(provider);
  298.             classProviders = cp;
  299.         }
  300.     }

  301.     public synchronized void removeClassProvider(ClassProvider provider) {
  302.         Set<ClassProvider> cp = new HashSet<ClassProvider>(classProviders);
  303.         cp.remove(provider);
  304.         classProviders = cp;
  305.     }

  306.     private void checkForCyclicInclude(RubyModule m) throws RaiseException {
  307.         if (getNonIncludedClass() == m.getNonIncludedClass()) {
  308.             throw getRuntime().newArgumentError("cyclic include detected");
  309.         }
  310.     }

  311.     protected void checkForCyclicPrepend(RubyModule m) throws RaiseException {
  312.         if (getNonIncludedClass() == m.getNonIncludedClass()) {
  313.             throw getRuntime().newArgumentError(getName() + " cyclic prepend detected " + m.getName());
  314.         }
  315.     }

  316.     private RubyClass searchProvidersForClass(String name, RubyClass superClazz) {
  317.         RubyClass clazz;
  318.         for (ClassProvider classProvider: classProviders) {
  319.             if ((clazz = classProvider.defineClassUnder(this, name, superClazz)) != null) {
  320.                 return clazz;
  321.             }
  322.         }
  323.         return null;
  324.     }

  325.     private RubyModule searchProvidersForModule(String name) {
  326.         RubyModule module;
  327.         for (ClassProvider classProvider: classProviders) {
  328.             if ((module = classProvider.defineModuleUnder(this, name)) != null) {
  329.                 return module;
  330.             }
  331.         }
  332.         return null;
  333.     }

  334.     /** Getter for property superClass.
  335.      * @return Value of property superClass.
  336.      */
  337.     public RubyClass getSuperClass() {
  338.         return superClass;
  339.     }

  340.     public void setSuperClass(RubyClass superClass) {
  341.         // update superclass reference
  342.         this.superClass = superClass;
  343.         if (superClass != null && superClass.isSynchronized()) becomeSynchronized();
  344.     }

  345.     public RubyModule getParent() {
  346.         return parent;
  347.     }

  348.     public void setParent(RubyModule parent) {
  349.         this.parent = parent;
  350.     }

  351.     public RubyModule getMethodLocation() {
  352.         return methodLocation;
  353.     }

  354.     public void setMethodLocation(RubyModule module){
  355.         methodLocation = module;
  356.     }

  357.     public Map<String, DynamicMethod> getMethods() {
  358.         return this.methods;
  359.     }

  360.     public synchronized Map<String, DynamicMethod> getMethodsForWrite() {
  361.         Map<String, DynamicMethod> myMethods = this.methods;
  362.         return myMethods == Collections.EMPTY_MAP ?
  363.             this.methods = new ConcurrentHashMap<String, DynamicMethod>(0, 0.9f, 1) :
  364.             myMethods;
  365.     }
  366.    
  367.     // note that addMethod now does its own put, so any change made to
  368.     // functionality here should be made there as well
  369.     private void putMethod(String name, DynamicMethod method) {
  370.         if (hasPrepends()) method = new WrapperMethod(methodLocation, method, method.getVisibility());
  371.         methodLocation.getMethodsForWrite().put(name, method);

  372.         getRuntime().addProfiledMethod(name, method);
  373.     }

  374.     /**
  375.      * Is this module one that in an included one (e.g. an IncludedModuleWrapper).
  376.      */
  377.     public boolean isIncluded() {
  378.         return false;
  379.     }

  380.     public boolean isPrepended() {
  381.         return false;
  382.     }

  383.     public RubyModule getNonIncludedClass() {
  384.         return this;
  385.     }

  386.     public RubyModule getDelegate() {
  387.         return this;
  388.     }

  389.     public RubyModule getNonPrependedClass() {
  390.         return this;
  391.     }

  392.     /**
  393.      * Get the base name of this class, or null if it is an anonymous class.
  394.      *
  395.      * @return base name of the class
  396.      */
  397.     public String getBaseName() {
  398.         return baseName;
  399.     }

  400.     /**
  401.      * Set the base name of the class. If null, the class effectively becomes
  402.      * anonymous (though constants elsewhere may reference it).
  403.      * @param name the new base name of the class
  404.      */
  405.     public void setBaseName(String name) {
  406.         baseName = name;
  407.     }

  408.     /**
  409.      * Generate a fully-qualified class name or a #-style name for anonymous and singleton classes.
  410.      *
  411.      * Ruby C equivalent = "classname"
  412.      *
  413.      * @return The generated class name
  414.      */
  415.     public String getName() {
  416.         if (cachedName != null) return cachedName;
  417.         return calculateName();
  418.     }
  419.    
  420.     /**
  421.      * Get the "simple" name for the class, which is either the "base" name or
  422.      * the "anonymous" class name.
  423.      *
  424.      * @return the "simple" name of the class
  425.      */
  426.     public String getSimpleName() {
  427.         if (baseName != null) return baseName;
  428.         return calculateAnonymousName();
  429.     }

  430.     /**
  431.      * Recalculate the fully-qualified name of this class/module.
  432.      */
  433.     private String calculateName() {
  434.         boolean cache = true;

  435.         if (getBaseName() == null) {
  436.             // we are anonymous, use anonymous name
  437.             return calculateAnonymousName();
  438.         }
  439.        
  440.         Ruby runtime = getRuntime();
  441.        
  442.         String name = getBaseName();
  443.         RubyClass objectClass = runtime.getObject();
  444.        
  445.         // First, we count the parents
  446.         int parentCount = 0;
  447.         for (RubyModule p = getParent() ; p != null && p != objectClass ; p = p.getParent()) {
  448.             parentCount++;
  449.         }
  450.        
  451.         // Allocate a String array for all of their names and populate it
  452.         String[] parentNames = new String[parentCount];
  453.         int i = parentCount - 1;
  454.         int totalLength = name.length() + parentCount * 2; // name length + enough :: for all parents
  455.         for (RubyModule p = getParent() ; p != null && p != objectClass ; p = p.getParent(), i--) {
  456.             String pName = p.getBaseName();
  457.            
  458.             // This is needed when the enclosing class or module is a singleton.
  459.             // In that case, we generated a name such as null::Foo, which broke
  460.             // Marshalling, among others. The correct thing to do in this situation
  461.             // is to insert the generate the name of form #<Class:01xasdfasd> if
  462.             // it's a singleton module/class, which this code accomplishes.
  463.             if(pName == null) {
  464.                 cache = false;
  465.                 pName = p.getName();
  466.              }
  467.            
  468.             parentNames[i] = pName;
  469.             totalLength += pName.length();
  470.         }
  471.        
  472.         // Then build from the front using a StringBuilder
  473.         StringBuilder builder = new StringBuilder(totalLength);
  474.         for (String parentName : parentNames) {
  475.             builder.append(parentName).append("::");
  476.         }
  477.         builder.append(name);
  478.        
  479.         String fullName = builder.toString();

  480.         if (cache) cachedName = fullName;

  481.         return fullName;
  482.     }

  483.     private String calculateAnonymousName() {
  484.         if (anonymousName == null) {
  485.             // anonymous classes get the #<Class:0xdeadbeef> format
  486.             StringBuilder anonBase = new StringBuilder("#<" + metaClass.getRealClass().getName() + ":0x");
  487.             anonBase.append(Integer.toHexString(System.identityHashCode(this))).append('>');
  488.             anonymousName = anonBase.toString();
  489.         }
  490.         return anonymousName;
  491.     }

  492.     /**
  493.      * Create a wrapper to use for including the specified module into this one.
  494.      *
  495.      * Ruby C equivalent = "include_class_new"
  496.      *
  497.      * @return The module wrapper
  498.      */
  499.     @Deprecated
  500.     public IncludedModuleWrapper newIncludeClass(RubyClass superClazz) {
  501.         IncludedModuleWrapper includedModule = new IncludedModuleWrapper(getRuntime(), superClazz, this);

  502.         // include its parent (and in turn that module's parents)
  503.         if (getSuperClass() != null) {
  504.             includedModule.includeModule(getSuperClass());
  505.         }

  506.         return includedModule;
  507.     }
  508.     /**
  509.      * Finds a class that is within the current module (or class).
  510.      *
  511.      * @param name to be found in this module (or class)
  512.      * @return the class or null if no such class
  513.      */
  514.     public RubyClass getClass(String name) {
  515.         IRubyObject module;
  516.         if ((module = getConstantAt(name)) instanceof RubyClass) {
  517.             return (RubyClass)module;
  518.         }
  519.         return null;
  520.     }

  521.     @Deprecated
  522.     public RubyClass fastGetClass(String internedName) {
  523.         return getClass(internedName);
  524.     }

  525.     /**
  526.      * Prepend a new module to this module or class.
  527.      *
  528.      * @param arg The module to include
  529.      */
  530.     public synchronized void prependModule(IRubyObject arg) {
  531.         assert arg != null;

  532.         testFrozen("module");

  533.         if (!(arg instanceof RubyModule)) {
  534.             throw getRuntime().newTypeError("Wrong argument type " + arg.getMetaClass().getName() +
  535.                     " (expected Module).");
  536.         }

  537.         RubyModule module = (RubyModule) arg;

  538.         // Make sure the module we include does not already exist
  539.         checkForCyclicInclude(module);

  540.         if (hasModuleInHierarchy((RubyModule)arg)) {
  541.             invalidateCacheDescendants();
  542.             return;
  543.         }

  544.         infectBy(module);

  545.         doPrependModule(module);

  546.         invalidateCoreClasses();
  547.         invalidateCacheDescendants();
  548.         invalidateConstantCacheForModuleInclusion(module);
  549.     }

  550.     /**
  551.      * Include a new module in this module or class.
  552.      *
  553.      * @param arg The module to include
  554.      */
  555.     public synchronized void includeModule(IRubyObject arg) {
  556.         assert arg != null;

  557.         testFrozen("module");

  558.         if (!(arg instanceof RubyModule)) {
  559.             throw getRuntime().newTypeError("Wrong argument type " + arg.getMetaClass().getName() +
  560.                     " (expected Module).");
  561.         }

  562.         RubyModule module = (RubyModule) arg;

  563.         // Make sure the module we include does not already exist
  564.         checkForCyclicInclude(module);

  565.         if (hasModuleInPrepends(((RubyModule)arg).getNonIncludedClass())) {
  566.             invalidateCacheDescendants();
  567.             return;
  568.         }

  569.         infectBy(module);

  570.         doIncludeModule(module);
  571.         invalidateCoreClasses();
  572.         invalidateCacheDescendants();
  573.         invalidateConstantCacheForModuleInclusion(module);
  574.     }
  575.    
  576.     public void defineAnnotatedMethod(Class clazz, String name) {
  577.         // FIXME: This is probably not very efficient, since it loads all methods for each call
  578.         boolean foundMethod = false;
  579.         for (Method method : clazz.getDeclaredMethods()) {
  580.             if (method.getName().equals(name) && defineAnnotatedMethod(method, MethodFactory.createFactory(getRuntime().getJRubyClassLoader()))) {
  581.                 foundMethod = true;
  582.             }
  583.         }

  584.         if (!foundMethod) {
  585.             throw new RuntimeException("No JRubyMethod present for method " + name + "on class " + clazz.getName());
  586.         }
  587.     }
  588.    
  589.     public void defineAnnotatedConstants(Class clazz) {
  590.         Field[] declaredFields = clazz.getDeclaredFields();
  591.         for (Field field : declaredFields) {
  592.             if (Modifier.isStatic(field.getModifiers())) {
  593.                 defineAnnotatedConstant(field);
  594.             }
  595.         }
  596.     }

  597.     public boolean defineAnnotatedConstant(Field field) {
  598.         JRubyConstant jrubyConstant = field.getAnnotation(JRubyConstant.class);

  599.         if (jrubyConstant == null) return false;

  600.         String[] names = jrubyConstant.value();
  601.         if(names.length == 0) {
  602.             names = new String[]{field.getName()};
  603.         }

  604.         Class tp = field.getType();
  605.         IRubyObject realVal;

  606.         try {
  607.             if(tp == Integer.class || tp == Integer.TYPE || tp == Short.class || tp == Short.TYPE || tp == Byte.class || tp == Byte.TYPE) {
  608.                 realVal = RubyNumeric.int2fix(getRuntime(), field.getInt(null));
  609.             } else if(tp == Boolean.class || tp == Boolean.TYPE) {
  610.                 realVal = field.getBoolean(null) ? getRuntime().getTrue() : getRuntime().getFalse();
  611.             } else {
  612.                 realVal = getRuntime().getNil();
  613.             }
  614.         } catch(Exception e) {
  615.             realVal = getRuntime().getNil();
  616.         }

  617.        
  618.         for(String name : names) {
  619.             this.setConstant(name, realVal);
  620.         }

  621.         return true;
  622.     }

  623.     @Extension
  624.     public void defineAnnotatedMethods(Class clazz) {
  625.         defineAnnotatedMethodsIndividually(clazz);
  626.     }
  627.    
  628.     public static class MethodClumper {
  629.         Map<String, List<JavaMethodDescriptor>> annotatedMethods = new HashMap<String, List<JavaMethodDescriptor>>();
  630.         Map<String, List<JavaMethodDescriptor>> staticAnnotatedMethods = new HashMap<String, List<JavaMethodDescriptor>>();
  631.         Map<String, List<JavaMethodDescriptor>> allAnnotatedMethods = new HashMap<String, List<JavaMethodDescriptor>>();
  632.        
  633.         public void clump(Class cls) {
  634.             Method[] declaredMethods = cls.getDeclaredMethods();
  635.             for (Method method: declaredMethods) {
  636.                 JRubyMethod anno = method.getAnnotation(JRubyMethod.class);

  637.                 if (anno == null) continue;

  638.                 // skip bridge methods, as generated by JDK8 javac for e.g. return-value overloaded methods
  639.                 if (method.isBridge()) continue;
  640.                
  641.                 JavaMethodDescriptor desc = new JavaMethodDescriptor(method);
  642.                
  643.                 String name = anno.name().length == 0 ? method.getName() : anno.name()[0];
  644.                
  645.                 List<JavaMethodDescriptor> methodDescs;
  646.                 Map<String, List<JavaMethodDescriptor>> methodsHash;
  647.                 if (desc.isStatic) {
  648.                     methodsHash = staticAnnotatedMethods;
  649.                 } else {
  650.                     methodsHash = annotatedMethods;
  651.                 }

  652.                 // add to specific
  653.                 methodDescs = methodsHash.get(name);
  654.                 if (methodDescs == null) {
  655.                     methodDescs = new ArrayList<JavaMethodDescriptor>();
  656.                     methodsHash.put(name, methodDescs);
  657.                 } else {
  658.                     CompatVersion oldCompat = methodDescs.get(0).anno.compat();
  659.                     CompatVersion newCompat = desc.anno.compat();

  660.                     int comparison = newCompat.compareTo(oldCompat);
  661.                     if (comparison == 1) {
  662.                         // new method's compat is higher than old method's, so we throw old one away
  663.                         methodDescs = new ArrayList<JavaMethodDescriptor>();
  664.                         methodsHash.put(name, methodDescs);
  665.                     } else if (comparison == 0) {
  666.                         // same compat version, proceed to adding additional method
  667.                     } else {
  668.                         // lower compat, skip this method
  669.                         continue;
  670.                     }
  671.                 }
  672.                
  673.                 methodDescs.add(desc);

  674.                 // add to general
  675.                 methodDescs = allAnnotatedMethods.get(name);
  676.                 if (methodDescs == null) {
  677.                     methodDescs = new ArrayList<JavaMethodDescriptor>();
  678.                     allAnnotatedMethods.put(name, methodDescs);
  679.                 }

  680.                 methodDescs.add(desc);
  681.             }
  682.         }

  683.         public Map<String, List<JavaMethodDescriptor>> getAllAnnotatedMethods() {
  684.             return allAnnotatedMethods;
  685.         }

  686.         public Map<String, List<JavaMethodDescriptor>> getAnnotatedMethods() {
  687.             return annotatedMethods;
  688.         }

  689.         public Map<String, List<JavaMethodDescriptor>> getStaticAnnotatedMethods() {
  690.             return staticAnnotatedMethods;
  691.         }
  692.     }
  693.    
  694.     public void defineAnnotatedMethodsIndividually(Class clazz) {
  695.         TypePopulator populator;
  696.        
  697.         if (RubyInstanceConfig.FULL_TRACE_ENABLED || RubyInstanceConfig.REFLECTED_HANDLES) {
  698.             // we want reflected invokers or need full traces, use default (slow) populator
  699.             if (DEBUG) LOG.info("trace mode, using default populator");
  700.             populator = TypePopulator.DEFAULT;
  701.         } else {
  702.             try {
  703.                 String qualifiedName = "org.jruby.gen." + clazz.getCanonicalName().replace('.', '$');

  704.                 if (DEBUG) LOG.info("looking for " + qualifiedName + AnnotationBinder.POPULATOR_SUFFIX);

  705.                 Class populatorClass = Class.forName(qualifiedName + AnnotationBinder.POPULATOR_SUFFIX);
  706.                 populator = (TypePopulator)populatorClass.newInstance();
  707.             } catch (Throwable t) {
  708.                 if (DEBUG) LOG.info("Could not find it, using default populator");
  709.                 populator = TypePopulator.DEFAULT;
  710.             }
  711.         }
  712.        
  713.         populator.populate(this, clazz);
  714.     }
  715.    
  716.     public boolean defineAnnotatedMethod(String name, List<JavaMethodDescriptor> methods, MethodFactory methodFactory) {
  717.         JavaMethodDescriptor desc = methods.get(0);
  718.         if (methods.size() == 1) {
  719.             return defineAnnotatedMethod(name, desc, methodFactory);
  720.         } else {
  721.             DynamicMethod dynamicMethod = methodFactory.getAnnotatedMethod(this, methods);
  722.             define(this, desc, name, dynamicMethod);

  723.             return true;
  724.         }
  725.     }
  726.    
  727.     public boolean defineAnnotatedMethod(Method method, MethodFactory methodFactory) {
  728.         JRubyMethod jrubyMethod = method.getAnnotation(JRubyMethod.class);

  729.         if (jrubyMethod == null) return false;

  730.         JavaMethodDescriptor desc = new JavaMethodDescriptor(method);
  731.         DynamicMethod dynamicMethod = methodFactory.getAnnotatedMethod(this, desc);
  732.         define(this, desc, method.getName(), dynamicMethod);

  733.         return true;
  734.     }
  735.    
  736.     public boolean defineAnnotatedMethod(String name, JavaMethodDescriptor desc, MethodFactory methodFactory) {
  737.         JRubyMethod jrubyMethod = desc.anno;

  738.         if (jrubyMethod == null) return false;

  739.         DynamicMethod dynamicMethod = methodFactory.getAnnotatedMethod(this, desc);
  740.         define(this, desc, name, dynamicMethod);

  741.         return true;
  742.     }

  743.     public void undefineMethod(String name) {
  744.         methodLocation.addMethod(name, UndefinedMethod.getInstance());
  745.     }

  746.     /** rb_undef
  747.      *
  748.      */
  749.     public void undef(ThreadContext context, String name) {
  750.         Ruby runtime = context.runtime;

  751.         testFrozen("module");
  752.         if (name.equals("__id__") || name.equals("__send__") || name.equals("object_id")) {
  753.             runtime.getWarnings().warn(ID.UNDEFINING_BAD, "undefining `"+ name +"' may cause serious problem");
  754.         }

  755.         if (name.equals("method_missing")) {

  756.             try {
  757.                 removeMethod(context, name);
  758.             } catch (RaiseException t) {
  759.                 if(!(t.getException() instanceof RubyNameError)) {
  760.                     throw t;
  761.                 }
  762.             }
  763.             return;
  764.         }

  765.         DynamicMethod method = searchMethod(name);
  766.         if (method.isUndefined()) {
  767.             String s0 = " class";
  768.             RubyModule c = this;

  769.             if (c.isSingleton()) {
  770.                 IRubyObject obj = ((MetaClass)c).getAttached();

  771.                 if (obj != null && obj instanceof RubyModule) {
  772.                     c = (RubyModule) obj;
  773.                     s0 = "";
  774.                 }
  775.             } else if (c.isModule()) {
  776.                 s0 = " module";
  777.             }

  778.             throw runtime.newNameError("Undefined method " + name + " for" + s0 + " '" + c.getName() + "'", name);
  779.         }
  780.         methodLocation.addMethod(name, UndefinedMethod.getInstance());
  781.        
  782.         if (isSingleton()) {
  783.             IRubyObject singleton = ((MetaClass)this).getAttached();
  784.             singleton.callMethod(context, "singleton_method_undefined", runtime.newSymbol(name));
  785.         } else {
  786.             callMethod(context, "method_undefined", runtime.newSymbol(name));
  787.         }
  788.     }

  789.     @JRubyMethod(name = "include?", required = 1)
  790.     public IRubyObject include_p(ThreadContext context, IRubyObject arg) {
  791.         if (!arg.isModule()) {
  792.             throw context.runtime.newTypeError(arg, context.runtime.getModule());
  793.         }
  794.         RubyModule moduleToCompare = (RubyModule) arg;

  795.         // See if module is in chain...Cannot match against itself so start at superClass.
  796.         for (RubyModule p = getSuperClass(); p != null; p = p.getSuperClass()) {
  797.             if (p.isSame(moduleToCompare)) {
  798.                 return context.runtime.getTrue();
  799.             }
  800.         }

  801.         return context.runtime.getFalse();
  802.     }

  803.     @JRubyMethod(name = "singleton_class?")
  804.     public IRubyObject singleton_class_p(ThreadContext context) {
  805.         return context.runtime.newBoolean(isSingleton());
  806.     }

  807.     // TODO: Consider a better way of synchronizing
  808.     public void addMethod(String name, DynamicMethod method) {
  809.         testFrozen("class/module");

  810.         if (this instanceof MetaClass) {
  811.             // FIXME: Gross and not quite right. See MRI's rb_frozen_class_p logic
  812.             RubyBasicObject attached = (RubyBasicObject)((MetaClass)this).getAttached();
  813.             attached.testFrozen();
  814.         }

  815.         addMethodInternal(name, method);
  816.     }

  817.     public void addMethodInternal(String name, DynamicMethod method) {
  818.         synchronized(methodLocation.getMethodsForWrite()) {
  819.             addMethodAtBootTimeOnly(name, method);
  820.             invalidateCoreClasses();
  821.             invalidateCacheDescendants();
  822.         }
  823.     }

  824.     /**
  825.      * This method is not intended for use by normal users; it is a fast-path
  826.      * method that skips synchronization and hierarchy invalidation to speed
  827.      * boot-time method definition.
  828.      *
  829.      * @param name The name to which to bind the method
  830.      * @param method The method to bind
  831.      */
  832.     public void addMethodAtBootTimeOnly(String name, DynamicMethod method) {
  833.         if (hasPrepends()) method = new WrapperMethod(methodLocation, method, method.getVisibility());

  834.         methodLocation.getMethodsForWrite().put(name, method);

  835.         getRuntime().addProfiledMethod(name, method);
  836.     }

  837.     public void removeMethod(ThreadContext context, String name) {
  838.         Ruby runtime = context.runtime;

  839.         testFrozen("class/module");

  840.         if(name.equals("object_id") || name.equals("__send__") || name.equals("initialize")) {
  841.             runtime.getWarnings().warn(ID.UNDEFINING_BAD, "removing `" + name + "' may cause serious problems");
  842.         }

  843.         // We can safely reference methods here instead of doing getMethods() since if we
  844.         // are adding we are not using a IncludedModule.
  845.         synchronized(methodLocation.getMethodsForWrite()) {
  846.             DynamicMethod method = (DynamicMethod) methodLocation.getMethodsForWrite().remove(name);
  847.             if (method == null) {
  848.                 throw runtime.newNameError("method '" + name + "' not defined in " + getName(), name);
  849.             }

  850.             invalidateCoreClasses();
  851.             invalidateCacheDescendants();
  852.         }
  853.        
  854.         if (isSingleton()) {
  855.             IRubyObject singleton = ((MetaClass)this).getAttached();
  856.             singleton.callMethod(context, "singleton_method_removed", runtime.newSymbol(name));
  857.         } else {
  858.             callMethod(context, "method_removed", runtime.newSymbol(name));
  859.         }
  860.     }

  861.     /**
  862.      * Search through this module and supermodules for method definitions. Cache superclass definitions in this class.
  863.      *
  864.      * @param name The name of the method to search for
  865.      * @return The method, or UndefinedMethod if not found
  866.      */    
  867.     public DynamicMethod searchMethod(String name) {
  868.         return searchWithCache(name).method;
  869.     }

  870.     public CacheEntry searchWithCache(String name) {
  871.         return searchWithCache(name, true);
  872.     }
  873.        
  874.     /**
  875.      * Search through this module and supermodules for method definitions. Cache superclass definitions in this class.
  876.      *
  877.      * @param name The name of the method to search for
  878.      * @param cacheUndef Flag for caching UndefinedMethod. This should normally be true.
  879.      * @return The method, or UndefinedMethod if not found
  880.      */    
  881.     public CacheEntry searchWithCache(String name, boolean cacheUndef) {
  882.         CacheEntry entry = cacheHit(name);

  883.         if (entry != null) return entry;

  884.         // we grab serial number first; the worst that will happen is we cache a later
  885.         // update with an earlier serial number, which would just flush anyway
  886.         int token = getGeneration();
  887.         DynamicMethod method = searchMethodInner(name);

  888.         if (method instanceof CacheableMethod) {
  889.             method = ((CacheableMethod) method).getMethodForCaching();
  890.         }

  891.         return method != null ? addToCache(name, method, token) : cacheUndef ? addToCache(name, UndefinedMethod.getInstance(), token) : cacheEntryFactory.newCacheEntry(name, method, token);
  892.     }

  893.     @Deprecated
  894.     public final int getCacheToken() {
  895.         return generation;
  896.     }
  897.    
  898.     public final int getGeneration() {
  899.         return generation;
  900.     }

  901.     public final Integer getGenerationObject() {
  902.         return generationObject;
  903.     }

  904.     private final Map<String, CacheEntry> getCachedMethods() {
  905.         return this.cachedMethods;
  906.     }

  907.     private final Map<String, CacheEntry> getCachedMethodsForWrite() {
  908.         Map<String, CacheEntry> myCachedMethods = this.cachedMethods;
  909.         return myCachedMethods == Collections.EMPTY_MAP ?
  910.             this.cachedMethods = new ConcurrentHashMap<String, CacheEntry>(0, 0.75f, 1) :
  911.             myCachedMethods;
  912.     }
  913.    
  914.     private CacheEntry cacheHit(String name) {
  915.         CacheEntry cacheEntry = getCachedMethods().get(name);

  916.         if (cacheEntry != null) {
  917.             if (cacheEntry.token == getGeneration()) {
  918.                 return cacheEntry;
  919.             }
  920.         }
  921.        
  922.         return null;
  923.     }

  924.     private void invalidateConstantCacheForModuleInclusion(RubyModule module)
  925.     {
  926.         for (RubyModule mod : gatherModules(module)) {
  927.             for (String key : mod.getConstantMap().keySet()) {
  928.                 invalidateConstantCache(key);
  929.             }
  930.         }
  931.     }
  932.    
  933.     protected static abstract class CacheEntryFactory {
  934.         public abstract CacheEntry newCacheEntry(String name,DynamicMethod method, int token);

  935.         /**
  936.          * Test all WrapperCacheEntryFactory instances in the chain for assignability
  937.          * from the given class.
  938.          *
  939.          * @param cacheEntryFactoryClass the class from which to test assignability
  940.          * @return whether the given class is assignable from any factory in the chain
  941.          */
  942.         public boolean hasCacheEntryFactory(Class cacheEntryFactoryClass) {
  943.             CacheEntryFactory current = this;
  944.             while (current instanceof WrapperCacheEntryFactory) {
  945.                 if (cacheEntryFactoryClass.isAssignableFrom(current.getClass())) {
  946.                     return true;
  947.                 }
  948.                 current = ((WrapperCacheEntryFactory)current).getPrevious();
  949.             }

  950.             return cacheEntryFactoryClass.isAssignableFrom(current.getClass());
  951.         }
  952.     }

  953.     /**
  954.      * A wrapper CacheEntryFactory, for delegating cache entry creation along a chain.
  955.      */
  956.     protected static abstract class WrapperCacheEntryFactory extends CacheEntryFactory {
  957.         /** The CacheEntryFactory being wrapped. */
  958.         protected final CacheEntryFactory previous;

  959.         /**
  960.          * Construct a new WrapperCacheEntryFactory using the given CacheEntryFactory as
  961.          * the "previous" wrapped factory.
  962.          *
  963.          * @param previous the wrapped factory
  964.          */
  965.         public WrapperCacheEntryFactory(CacheEntryFactory previous) {
  966.             this.previous = previous;
  967.         }

  968.         public CacheEntryFactory getPrevious() {
  969.             return previous;
  970.         }
  971.     }

  972.     protected static final CacheEntryFactory NormalCacheEntryFactory = new CacheEntryFactory() {
  973.         @Override
  974.         public CacheEntry newCacheEntry(String name, DynamicMethod method, int token) {
  975.             return new CacheEntry(method, token);
  976.         }
  977.     };

  978.     protected static class SynchronizedCacheEntryFactory extends WrapperCacheEntryFactory {
  979.         public SynchronizedCacheEntryFactory(CacheEntryFactory previous) {
  980.             super(previous);
  981.         }
  982.         @Override
  983.         public CacheEntry newCacheEntry(String name,DynamicMethod method, int token) {
  984.             if (method.isUndefined()) {
  985.                 return new CacheEntry(method, token);
  986.             }
  987.             // delegate up the chain
  988.             CacheEntry delegated = previous.newCacheEntry(name,method, token);
  989.             return new CacheEntry(new SynchronizedDynamicMethod(delegated.method), delegated.token);
  990.         }
  991.     }

  992.     protected static class ProfilingCacheEntryFactory extends WrapperCacheEntryFactory {

  993.         private final MethodEnhancer enhancer;

  994.         public ProfilingCacheEntryFactory( Ruby runtime, CacheEntryFactory previous) {
  995.             super(previous);
  996.             this.enhancer = runtime.getProfilingService().newMethodEnhancer( runtime );
  997.         }

  998.         private MethodEnhancer getMethodEnhancer() {
  999.             return enhancer;
  1000.         }

  1001.         @Override
  1002.         public CacheEntry newCacheEntry(String name, DynamicMethod method, int token) {
  1003.             if (method.isUndefined()) {
  1004.                 return new CacheEntry(method, token);
  1005.             }
  1006.             CacheEntry delegated = previous.newCacheEntry(name, method, token);
  1007.             DynamicMethod enhancedMethod = getMethodEnhancer().enhance( name, delegated.method );
  1008.             return new CacheEntry( enhancedMethod, delegated.token );
  1009.         }
  1010.     }

  1011.     private volatile CacheEntryFactory cacheEntryFactory;

  1012.     // modifies this class only; used to make the Synchronized module synchronized
  1013.     public void becomeSynchronized() {
  1014.         cacheEntryFactory = new SynchronizedCacheEntryFactory(cacheEntryFactory);
  1015.     }

  1016.     public boolean isSynchronized() {
  1017.         return cacheEntryFactory.hasCacheEntryFactory(SynchronizedCacheEntryFactory.class);
  1018.     }

  1019.     private CacheEntry addToCache(String name, DynamicMethod method, int token) {
  1020.         CacheEntry entry = cacheEntryFactory.newCacheEntry(name, method, token);
  1021.         methodLocation.getCachedMethodsForWrite().put(name, entry);

  1022.         return entry;
  1023.     }
  1024.    
  1025.     public DynamicMethod searchMethodInner(String name) {
  1026.         // This flattens some of the recursion that would be otherwise be necessary.
  1027.         // Used to recurse up the class hierarchy which got messy with prepend.
  1028.         for (RubyModule module = this; module != null; module = module.getSuperClass()) {
  1029.             // Only recurs if module is an IncludedModuleWrapper.
  1030.             // This way only the recursion needs to be handled differently on
  1031.             // IncludedModuleWrapper.
  1032.             DynamicMethod method = module.searchMethodCommon(name);
  1033.             if (method != null) return method.isNull() ? null : method;
  1034.         }
  1035.         return null;
  1036.     }

  1037.     // The local method resolution logic. Overridden in IncludedModuleWrapper for recursion.
  1038.     protected DynamicMethod searchMethodCommon(String name) {
  1039.         return getMethods().get(name);
  1040.     }

  1041.     public void invalidateCacheDescendants() {
  1042.         if (DEBUG) LOG.debug("invalidating descendants: {}", baseName);

  1043.         if (includingHierarchies.isEmpty()) {
  1044.             // it's only us; just invalidate directly
  1045.             methodInvalidator.invalidate();
  1046.             return;
  1047.         }

  1048.         List<Invalidator> invalidators = new ArrayList<Invalidator>();
  1049.         invalidators.add(methodInvalidator);
  1050.        
  1051.         synchronized (getRuntime().getHierarchyLock()) {
  1052.             for (RubyClass includingHierarchy : includingHierarchies) {
  1053.                 includingHierarchy.addInvalidatorsAndFlush(invalidators);
  1054.             }
  1055.         }
  1056.        
  1057.         methodInvalidator.invalidateAll(invalidators);
  1058.     }
  1059.    
  1060.     protected void invalidateCoreClasses() {
  1061.         if (!getRuntime().isBootingCore()) {
  1062.             if (this == getRuntime().getFixnum()) {
  1063.                 getRuntime().reopenFixnum();
  1064.             } else if (this == getRuntime().getFloat()) {
  1065.                 getRuntime().reopenFloat();
  1066.             }
  1067.         }
  1068.     }
  1069.    
  1070.     public Invalidator getInvalidator() {
  1071.         return methodInvalidator;
  1072.     }
  1073.    
  1074.     public void updateGeneration() {
  1075.         generationObject = generation = getRuntime().getNextModuleGeneration();
  1076.     }

  1077.     @Deprecated
  1078.     protected void invalidateCacheDescendantsInner() {
  1079.         methodInvalidator.invalidate();
  1080.     }
  1081.    
  1082.     protected void invalidateConstantCache(String constantName) {
  1083.         getRuntime().getConstantInvalidator(constantName).invalidate();
  1084.     }    

  1085.     /**
  1086.      * Search through this module and supermodules for method definitions. Cache superclass definitions in this class.
  1087.      *
  1088.      * @param name The name of the method to search for
  1089.      * @return The method, or UndefinedMethod if not found
  1090.      */
  1091.     public DynamicMethod retrieveMethod(String name) {
  1092.         return getMethods().get(name);
  1093.     }

  1094.     /**
  1095.      * Find the given class in this hierarchy, considering modules along the way.
  1096.      *
  1097.      * @param clazz the class to find
  1098.      * @return The method, or UndefinedMethod if not found
  1099.      */
  1100.     public RubyModule findImplementer(RubyModule clazz) {
  1101.         for (RubyModule module = this; module != null; module = module.getSuperClass()) {
  1102.             if (module.isSame(clazz)) return module;
  1103.         }

  1104.         return null;
  1105.     }

  1106.     public void addModuleFunction(String name, DynamicMethod method) {
  1107.         addMethod(name, method);
  1108.         getSingletonClass().addMethod(name, method);
  1109.     }

  1110.     /** rb_alias
  1111.      *
  1112.      */
  1113.     public synchronized void defineAlias(String name, String oldName) {
  1114.         testFrozen("module");
  1115.         if (oldName.equals(name)) return;

  1116.         DynamicMethod method = searchForAliasMethod(getRuntime(), oldName);

  1117.         putMethod(name, new AliasMethod(this, method, oldName));

  1118.         methodLocation.invalidateCoreClasses();
  1119.         methodLocation.invalidateCacheDescendants();
  1120.     }

  1121.     public synchronized void defineAliases(List<String> aliases, String oldName) {
  1122.         testFrozen("module");
  1123.         DynamicMethod method = searchForAliasMethod(getRuntime(), oldName);

  1124.         for (String name: aliases) {
  1125.             if (oldName.equals(name)) continue;

  1126.             putMethod(name, new AliasMethod(this, method, oldName));
  1127.         }
  1128.        
  1129.         methodLocation.invalidateCoreClasses();
  1130.         methodLocation.invalidateCacheDescendants();
  1131.     }
  1132.    
  1133.     private DynamicMethod searchForAliasMethod(Ruby runtime, String name) {
  1134.         DynamicMethod method = deepMethodSearch(name, runtime);

  1135.         if (method instanceof JavaMethod) {
  1136.             // JRUBY-2435: Aliasing eval and other "special" methods should display a warning
  1137.             // We warn because we treat certain method names as "special" for purposes of
  1138.             // optimization. Hopefully this will be enough to convince people not to alias
  1139.             // them.
  1140.             CallConfiguration callerReq = ((JavaMethod)method).getCallerRequirement();

  1141.             if (callerReq.framing() != Framing.None ||
  1142.                     callerReq.scoping() != Scoping.None) {String baseName = getBaseName();
  1143.                 char refChar = '#';
  1144.                 String simpleName = getSimpleName();

  1145.                 if (baseName == null && this instanceof MetaClass) {
  1146.                     IRubyObject attached = ((MetaClass)this).getAttached();
  1147.                     if (attached instanceof RubyModule) {
  1148.                         simpleName = ((RubyModule)attached).getSimpleName();
  1149.                         refChar = '.';
  1150.                     }
  1151.                 }

  1152.                 runtime.getWarnings().warn(simpleName + refChar + name + " accesses caller's state and should not be aliased");
  1153.             }
  1154.         }

  1155.         return method;
  1156.     }

  1157.     /** this method should be used only by interpreter or compiler
  1158.      *
  1159.      */
  1160.     public RubyClass defineOrGetClassUnder(String name, RubyClass superClazz) {
  1161.         // This method is intended only for defining new classes in Ruby code,
  1162.         // so it uses the allocator of the specified superclass or default to
  1163.         // the Object allocator. It should NOT be used to define classes that require a native allocator.

  1164.         Ruby runtime = getRuntime();
  1165.         IRubyObject classObj = getConstantAtSpecial(name);
  1166.         RubyClass clazz;

  1167.         if (classObj != null) {
  1168.             if (!(classObj instanceof RubyClass)) throw runtime.newTypeError(name + " is not a class");
  1169.             clazz = (RubyClass)classObj;

  1170.             if (superClazz != null) {
  1171.                 RubyClass tmp = clazz.getSuperClass();
  1172.                 while (tmp != null && tmp.isIncluded()) tmp = tmp.getSuperClass(); // need to skip IncludedModuleWrappers
  1173.                 if (tmp != null) tmp = tmp.getRealClass();
  1174.                 if (tmp != superClazz) throw runtime.newTypeError("superclass mismatch for class " + name);
  1175.                 // superClazz = null;
  1176.             }
  1177.         } else if (classProviders != null && (clazz = searchProvidersForClass(name, superClazz)) != null) {
  1178.             // reopen a java class
  1179.         } else {
  1180.             if (superClazz == null) superClazz = runtime.getObject();
  1181.            
  1182.             ObjectAllocator allocator;
  1183.             if (superClazz == runtime.getObject()) {
  1184.                 if (RubyInstanceConfig.REIFY_RUBY_CLASSES) {
  1185.                     allocator = REIFYING_OBJECT_ALLOCATOR;
  1186.                 } else if (Options.REIFY_VARIABLES.load()) {
  1187.                     allocator = IVAR_INSPECTING_OBJECT_ALLOCATOR;
  1188.                 } else {
  1189.                     allocator = OBJECT_ALLOCATOR;
  1190.                 }
  1191.             } else {
  1192.                 allocator = superClazz.getAllocator();
  1193.             }
  1194.            
  1195.             clazz = RubyClass.newClass(runtime, superClazz, name, allocator, this, true);
  1196.         }

  1197.         return clazz;
  1198.     }

  1199.     /** this method should be used only by interpreter or compiler
  1200.      *
  1201.      */
  1202.     public RubyModule defineOrGetModuleUnder(String name) {
  1203.         // This method is intended only for defining new modules in Ruby code
  1204.         Ruby runtime = getRuntime();
  1205.         IRubyObject moduleObj = getConstantAtSpecial(name);
  1206.         RubyModule module;
  1207.         if (moduleObj != null) {
  1208.             if (!moduleObj.isModule()) throw runtime.newTypeError(name + " is not a module");
  1209.             module = (RubyModule)moduleObj;
  1210.         } else if (classProviders != null && (module = searchProvidersForModule(name)) != null) {
  1211.             // reopen a java module
  1212.         } else {
  1213.             module = RubyModule.newModule(runtime, name, this, true);
  1214.         }
  1215.         return module;
  1216.     }

  1217.     /** rb_define_class_under
  1218.      *  this method should be used only as an API to define/open nested classes
  1219.      */
  1220.     public RubyClass defineClassUnder(String name, RubyClass superClass, ObjectAllocator allocator) {
  1221.         return getRuntime().defineClassUnder(name, superClass, allocator, this);
  1222.     }

  1223.     /** rb_define_module_under
  1224.      *  this method should be used only as an API to define/open nested module
  1225.      */
  1226.     public RubyModule defineModuleUnder(String name) {
  1227.         return getRuntime().defineModuleUnder(name, this);
  1228.     }

  1229.     private void addAccessor(ThreadContext context, String internedName, Visibility visibility, boolean readable, boolean writeable) {
  1230.         assert internedName == internedName.intern() : internedName + " is not interned";

  1231.         final Ruby runtime = context.runtime;

  1232.         if (visibility == PRIVATE) {
  1233.             //FIXME warning
  1234.         } else if (visibility == MODULE_FUNCTION) {
  1235.             visibility = PRIVATE;
  1236.             // FIXME warning
  1237.         }

  1238.         if (!(IdUtil.isLocal(internedName) || IdUtil.isConstant(internedName))) {
  1239.             throw runtime.newNameError("invalid attribute name", internedName);
  1240.         }

  1241.         final String variableName = ("@" + internedName).intern();
  1242.         if (readable) {
  1243.             addMethod(internedName, new AttrReaderMethod(methodLocation, visibility, CallConfiguration.FrameNoneScopeNone, variableName));
  1244.             callMethod(context, "method_added", runtime.fastNewSymbol(internedName));
  1245.         }
  1246.         if (writeable) {
  1247.             internedName = (internedName + "=").intern();
  1248.             addMethod(internedName, new AttrWriterMethod(methodLocation, visibility, CallConfiguration.FrameNoneScopeNone, variableName));
  1249.             callMethod(context, "method_added", runtime.fastNewSymbol(internedName));
  1250.         }
  1251.     }

  1252.     /** set_method_visibility
  1253.      *
  1254.      */
  1255.     public void setMethodVisibility(IRubyObject[] methods, Visibility visibility) {
  1256.         for (int i = 0; i < methods.length; i++) {
  1257.             exportMethod(methods[i].asJavaString(), visibility);
  1258.         }
  1259.     }

  1260.     /** rb_export_method
  1261.      *
  1262.      */
  1263.     public void exportMethod(String name, Visibility visibility) {
  1264.         Ruby runtime = getRuntime();

  1265.         DynamicMethod method = deepMethodSearch(name, runtime);

  1266.         if (method.getVisibility() != visibility) {
  1267.             if (this == method.getImplementationClass()) {
  1268.                 method.setVisibility(visibility);
  1269.             } else {
  1270.                 // FIXME: Why was this using a FullFunctionCallbackMethod before that did callSuper?
  1271.                 methodLocation.addMethod(name, new WrapperMethod(this, method, visibility));
  1272.             }

  1273.             invalidateCoreClasses();
  1274.             invalidateCacheDescendants();
  1275.         }
  1276.     }

  1277.     private DynamicMethod deepMethodSearch(String name, Ruby runtime) {
  1278.         DynamicMethod method = searchMethod(name);

  1279.         if (method.isUndefined() && isModule()) {
  1280.             method = runtime.getObject().searchMethod(name);
  1281.         }

  1282.         if (method.isUndefined()) {
  1283.             throw runtime.newNameError("undefined method '" + name + "' for " +
  1284.                                 (isModule() ? "module" : "class") + " '" + getName() + "'", name);
  1285.         }
  1286.         return method;
  1287.     }

  1288.     /**
  1289.      * MRI: rb_method_boundp
  1290.      *
  1291.      */
  1292.     public boolean isMethodBound(String name, boolean checkVisibility) {
  1293.         DynamicMethod method = searchMethod(name);
  1294.         if (!method.isUndefined()) {
  1295.             return !(checkVisibility && method.getVisibility() == PRIVATE);
  1296.         }
  1297.         return false;
  1298.     }
  1299.    
  1300.     public boolean isMethodBound(String name, boolean checkVisibility, boolean checkRespondTo) {
  1301.         if (!checkRespondTo) return isMethodBound(name, checkVisibility);
  1302.         DynamicMethod method = searchMethod(name);
  1303.         if (!method.isUndefined() && !method.isNotImplemented()) {
  1304.             return !(checkVisibility && method.getVisibility() == PRIVATE);
  1305.         }
  1306.         return false;
  1307.     }

  1308.     public IRubyObject newMethod(IRubyObject receiver, String methodName, boolean bound, Visibility visibility) {
  1309.         return newMethod(receiver, methodName, bound, visibility, false, true);
  1310.     }

  1311.     public IRubyObject newMethod(IRubyObject receiver, final String methodName, boolean bound, Visibility visibility, boolean respondToMissing) {
  1312.         return newMethod(receiver, methodName, bound, visibility, respondToMissing, true);
  1313.     }

  1314.     public static class RespondToMissingMethod extends JavaMethod.JavaMethodNBlock {
  1315.         final CallSite site;
  1316.         public RespondToMissingMethod(RubyModule implClass, Visibility vis, String methodName) {
  1317.             super(implClass, vis);

  1318.             site = new FunctionalCachingCallSite(methodName);
  1319.         }
  1320.         @Override
  1321.         public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
  1322.             return site.call(context, self, self, args, block);
  1323.         }

  1324.         public boolean equals(Object other) {
  1325.             if (!(other instanceof RespondToMissingMethod)) return false;

  1326.             RespondToMissingMethod rtmm = (RespondToMissingMethod)other;

  1327.             return this.site.methodName.equals(rtmm.site.methodName) &&
  1328.                     isImplementedBy(rtmm.getImplementationClass());
  1329.         }
  1330.     }

  1331.     public IRubyObject newMethod(IRubyObject receiver, final String methodName, boolean bound, Visibility visibility, boolean respondToMissing, boolean priv) {
  1332.         DynamicMethod method = searchMethod(methodName);

  1333.         if (method.isUndefined() ||
  1334.             (visibility != null && method.getVisibility() != visibility)) {
  1335.             if (respondToMissing) { // 1.9 behavior
  1336.                 if (receiver.respondsToMissing(methodName, priv)) {
  1337.                     method = new RespondToMissingMethod(this, PUBLIC, methodName);
  1338.                 } else {
  1339.                     throw getRuntime().newNameError("undefined method `" + methodName +
  1340.                         "' for class `" + this.getName() + "'", methodName);
  1341.                 }
  1342.             } else {
  1343.                 throw getRuntime().newNameError("undefined method `" + methodName +
  1344.                     "' for class `" + this.getName() + "'", methodName);
  1345.             }
  1346.         }

  1347.         RubyModule implementationModule = method.getImplementationClass();
  1348.         RubyModule originModule = this;
  1349.         while (originModule != implementationModule && originModule.isSingleton()) {
  1350.             originModule = ((MetaClass)originModule).getRealClass();
  1351.         }

  1352.         RubyMethod newMethod;
  1353.         if (bound) {
  1354.             newMethod = RubyMethod.newMethod(implementationModule, methodName, originModule, methodName, method, receiver);
  1355.         } else {
  1356.             newMethod = RubyUnboundMethod.newUnboundMethod(implementationModule, methodName, originModule, methodName, method);
  1357.         }
  1358.         newMethod.infectBy(this);

  1359.         return newMethod;
  1360.     }

  1361.     @JRubyMethod(name = "define_method", visibility = PRIVATE, reads = VISIBILITY)
  1362.     public IRubyObject define_method(ThreadContext context, IRubyObject arg0, Block block) {
  1363.         Ruby runtime = context.runtime;
  1364.         String name = TypeConverter.convertToIdentifier(arg0);
  1365.         DynamicMethod newMethod = null;
  1366.         Visibility visibility = PUBLIC;

  1367.         // We need our identifier to be retrievable and creatable as a symbol.  This side-effect
  1368.         // populates this name into our symbol table so it will exist later if needed.  The
  1369.         // reason for this hack/side-effect is that symbols store their values as raw bytes.  We lose encoding
  1370.         // info so we need to make an entry so any accesses with raw bytes later gets proper symbol.
  1371.         RubySymbol nameSym = RubySymbol.newSymbol(runtime, arg0);
  1372.        
  1373.         if (!block.isGiven()) {
  1374.             throw getRuntime().newArgumentError("tried to create Proc object without a block");
  1375.         }

  1376.         block = block.cloneBlockAndFrame();
  1377.         RubyProc proc = runtime.newProc(Block.Type.LAMBDA, block);

  1378.         // a normal block passed to define_method changes to do arity checking; make it a lambda
  1379.         proc.getBlock().type = Block.Type.LAMBDA;
  1380.        
  1381.         newMethod = createProcMethod(name, visibility, proc);
  1382.        
  1383.         Helpers.addInstanceMethod(this, name, newMethod, visibility, context, runtime);

  1384.         return nameSym;
  1385.     }
  1386.    
  1387.     @JRubyMethod(name = "define_method", visibility = PRIVATE, reads = VISIBILITY)
  1388.     public IRubyObject define_method(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
  1389.         Ruby runtime = context.runtime;
  1390.         IRubyObject body;
  1391.         String name = TypeConverter.convertToIdentifier(arg0);
  1392.         DynamicMethod newMethod = null;
  1393.         Visibility visibility = PUBLIC;
  1394.        
  1395.         // We need our identifier to be retrievable and creatable as a symbol.  This side-effect
  1396.         // populates this name into our symbol table so it will exist later if needed.  The
  1397.         // reason for this hack/side-effect is that symbols store their values as raw bytes.  We lose encoding
  1398.         // info so we need to make an entry so any accesses with raw bytes later gets proper symbol.
  1399.         RubySymbol nameSym = RubySymbol.newSymbol(runtime, arg0);

  1400.         if (runtime.getProc().isInstance(arg1)) {
  1401.             // double-testing args.length here, but it avoids duplicating the proc-setup code in two places
  1402.             RubyProc proc = (RubyProc)arg1;
  1403.             body = proc;

  1404.             newMethod = createProcMethod(name, visibility, proc);
  1405.         } else if (runtime.getMethod().isInstance(arg1)) {
  1406.             RubyMethod method = (RubyMethod)arg1;
  1407.             body = method;
  1408.            
  1409.             checkValidBindTargetFrom(context, (RubyModule)method.owner(context));
  1410.            
  1411.             newMethod = method.unbind().getMethod().dup();
  1412.             newMethod.setImplementationClass(this);
  1413.         } else {
  1414.             throw runtime.newTypeError("wrong argument type " + arg1.getType().getName() + " (expected Proc/Method)");
  1415.         }
  1416.        
  1417.         Helpers.addInstanceMethod(this, name, newMethod, visibility, context, runtime);

  1418.         return nameSym;
  1419.     }
  1420.     @Deprecated
  1421.     public IRubyObject define_method(ThreadContext context, IRubyObject[] args, Block block) {
  1422.         switch (args.length) {
  1423.         case 1:
  1424.             return define_method(context, args[0], block);
  1425.         case 2:
  1426.             return define_method(context, args[0], args[1], block);
  1427.         default:
  1428.             throw context.runtime.newArgumentError("wrong number of arguments (" + args.length + " for 2)");
  1429.         }
  1430.     }
  1431.    
  1432.     private DynamicMethod createProcMethod(String name, Visibility visibility, RubyProc proc) {
  1433.         Block block = proc.getBlock();
  1434.         block.getBinding().getFrame().setKlazz(this);
  1435.         block.getBinding().getFrame().setName(name);
  1436.         block.getBinding().setMethod(name);
  1437.        
  1438.         StaticScope scope = block.getBody().getStaticScope();

  1439.         // for zsupers in define_method (blech!) we tell the proc scope to act as the "argument" scope
  1440.         scope.makeArgumentScope();

  1441.         Arity arity = block.arity();
  1442.         // just using required is broken...but no more broken than before zsuper refactoring
  1443.         scope.setRequiredArgs(arity.required());

  1444.         if(!arity.isFixed()) {
  1445.             scope.setRestArg(arity.required());
  1446.         }

  1447.         return new ProcMethod(this, proc, visibility);
  1448.     }

  1449.     public IRubyObject name() {
  1450.         return name19();
  1451.     }

  1452.     @JRubyMethod(name = "name")
  1453.     public IRubyObject name19() {
  1454.         Ruby runtime = getRuntime();
  1455.         if (getBaseName() == null) {
  1456.             return runtime.getNil();
  1457.         } else {
  1458.             return runtime.newString(getName());
  1459.         }
  1460.     }

  1461.     protected IRubyObject cloneMethods(RubyModule clone) {
  1462.         RubyModule realType = this.getNonIncludedClass();
  1463.         for (Map.Entry<String, DynamicMethod> entry : getMethods().entrySet()) {
  1464.             DynamicMethod method = entry.getValue();
  1465.             // Do not clone cached methods
  1466.             // FIXME: MRI copies all methods here
  1467.             if (method.isImplementedBy(realType) || method.isUndefined()) {
  1468.                
  1469.                 // A cloned method now belongs to a new class.  Set it.
  1470.                 // TODO: Make DynamicMethod immutable
  1471.                 DynamicMethod clonedMethod = method.dup();
  1472.                 clonedMethod.setImplementationClass(clone);
  1473.                 clone.putMethod(entry.getKey(), clonedMethod);
  1474.             }
  1475.         }

  1476.         return clone;
  1477.     }

  1478.     /** mri: rb_mod_init_copy
  1479.      *
  1480.      */
  1481.     @JRubyMethod(name = "initialize_copy", required = 1, visibility = Visibility.PRIVATE)
  1482.     @Override
  1483.     public IRubyObject initialize_copy(IRubyObject original) {
  1484.         if (this instanceof RubyClass) {
  1485.             checkSafeTypeToCopy((RubyClass) original);
  1486.         }
  1487.         super.initialize_copy(original);

  1488.         RubyModule originalModule = (RubyModule)original;

  1489.         if (!getMetaClass().isSingleton()) setMetaClass(originalModule.getSingletonClassClone());
  1490.         setSuperClass(originalModule.getSuperClass());
  1491.         if (originalModule.hasVariables()) syncVariables(originalModule);
  1492.         syncConstants(originalModule);

  1493.         originalModule.cloneMethods(this);

  1494.         return this;
  1495.     }

  1496.     // mri: class_init_copy_check
  1497.     private void checkSafeTypeToCopy(RubyClass original) {
  1498.         Ruby runtime = getRuntime();

  1499.         if (original == runtime.getBasicObject()) throw runtime.newTypeError("can't copy the root class");
  1500.         if (getSuperClass() == runtime.getBasicObject()) throw runtime.newTypeError("already initialized class");
  1501.         if (original.isSingleton()) throw runtime.newTypeError("can't copy singleton class");
  1502.     }

  1503.     public void syncConstants(RubyModule other) {
  1504.         if (other.getConstantMap() != Collections.EMPTY_MAP) {
  1505.             getConstantMapForWrite().putAll(other.getConstantMap());
  1506.         }
  1507.     }

  1508.     public void syncClassVariables(RubyModule other) {
  1509.         if (other.getClassVariablesForRead() != Collections.EMPTY_MAP) {
  1510.             getClassVariables().putAll(other.getClassVariablesForRead());
  1511.         }
  1512.     }

  1513.     /** rb_mod_included_modules
  1514.      *
  1515.      */
  1516.     @JRubyMethod(name = "included_modules")
  1517.     public RubyArray included_modules(ThreadContext context) {
  1518.         RubyArray ary = context.runtime.newArray();

  1519.         for (RubyModule p = getSuperClass(); p != null; p = p.getSuperClass()) {
  1520.             if (p.isIncluded()) {
  1521.                 ary.append(p.getNonIncludedClass());
  1522.             }
  1523.         }

  1524.         return ary;
  1525.     }

  1526.     public boolean hasPrepends() {
  1527.         return methodLocation != this;
  1528.     }

  1529.     /** rb_mod_ancestors
  1530.      *
  1531.      */
  1532.     @JRubyMethod(name = "ancestors")
  1533.     public RubyArray ancestors(ThreadContext context) {
  1534.         return context.runtime.newArray(getAncestorList());
  1535.     }
  1536.    
  1537.     @Deprecated
  1538.     public RubyArray ancestors() {
  1539.         return getRuntime().newArray(getAncestorList());
  1540.     }

  1541.     public List<IRubyObject> getAncestorList() {
  1542.         ArrayList<IRubyObject> list = new ArrayList<IRubyObject>();

  1543.         for (RubyModule module = this; module != null; module = module.getSuperClass()) {
  1544.             // FIXME this is silly. figure out how to delegate the getNonIncludedClass()
  1545.             // call to drop the getDelegate().
  1546.             if (module.methodLocation == module) list.add(module.getDelegate().getNonIncludedClass());
  1547.         }

  1548.         return list;
  1549.     }

  1550.     public boolean hasModuleInPrepends(RubyModule type) {
  1551.         for (RubyModule module = this; module != methodLocation; module = module.getSuperClass()) {
  1552.             if (type == module.getNonIncludedClass()) return true;
  1553.         }
  1554.         return false;
  1555.     }

  1556.     public boolean hasModuleInHierarchy(RubyModule type) {
  1557.         // XXX: This check previously used callMethod("==") to check for equality between classes
  1558.         // when scanning the hierarchy. However the == check may be safe; we should only ever have
  1559.         // one instance bound to a given type/constant. If it's found to be unsafe, examine ways
  1560.         // to avoid the == call.
  1561.         for (RubyModule module = this; module != null; module = module.getSuperClass()) {
  1562.             if (module.getNonIncludedClass() == type) return true;
  1563.         }

  1564.         return false;
  1565.     }

  1566.     @Override
  1567.     public int hashCode() {
  1568.         return id;
  1569.     }

  1570.     @JRubyMethod(name = "hash")
  1571.     @Override
  1572.     public RubyFixnum hash() {
  1573.         return getRuntime().newFixnum(id);
  1574.     }

  1575.     /** rb_mod_to_s
  1576.      *
  1577.      */
  1578.     @JRubyMethod(name = "to_s", alias = "inspect")
  1579.     @Override
  1580.     public IRubyObject to_s() {
  1581.         if(isSingleton()){            
  1582.             IRubyObject attached = ((MetaClass)this).getAttached();
  1583.             StringBuilder buffer = new StringBuilder("#<Class:");
  1584.             if (attached != null) { // FIXME: figure out why we getService null sometimes
  1585.                 if(attached instanceof RubyClass || attached instanceof RubyModule){
  1586.                     buffer.append(attached.inspect());
  1587.                 }else{
  1588.                     buffer.append(attached.anyToString());
  1589.                 }
  1590.             }
  1591.             buffer.append(">");
  1592.             return getRuntime().newString(buffer.toString());
  1593.         }
  1594.         return getRuntime().newString(getName());
  1595.     }

  1596.     /** rb_mod_eqq
  1597.      *
  1598.      */
  1599.     @JRubyMethod(name = "===", required = 1)
  1600.     @Override
  1601.     public RubyBoolean op_eqq(ThreadContext context, IRubyObject obj) {
  1602.         return context.runtime.newBoolean(isInstance(obj));
  1603.     }

  1604.     /**
  1605.      * We override equals here to provide a faster path, since equality for modules
  1606.      * is pretty cut and dried.
  1607.      * @param other The object to check for equality
  1608.      * @return true if reference equality, false otherwise
  1609.      */
  1610.     @Override
  1611.     public boolean equals(Object other) {
  1612.         return this == other;
  1613.     }

  1614.     @JRubyMethod(name = "==", required = 1)
  1615.     @Override
  1616.     public IRubyObject op_equal(ThreadContext context, IRubyObject other) {
  1617.         if(!(other instanceof RubyModule)) return context.runtime.getFalse();

  1618.         RubyModule otherModule = (RubyModule) other;
  1619.         if(otherModule.isIncluded()) {
  1620.             return context.runtime.newBoolean(otherModule.isSame(this));
  1621.         } else {
  1622.             return context.runtime.newBoolean(isSame(otherModule));
  1623.         }
  1624.     }

  1625.     /** rb_mod_freeze
  1626.      *
  1627.      */
  1628.     @JRubyMethod(name = "freeze")
  1629.     @Override
  1630.     public final IRubyObject freeze(ThreadContext context) {
  1631.         to_s();
  1632.         return super.freeze(context);
  1633.     }

  1634.     /** rb_mod_le
  1635.     *
  1636.     */
  1637.     @JRubyMethod(name = "<=", required = 1)
  1638.    public IRubyObject op_le(IRubyObject obj) {
  1639.         if (!(obj instanceof RubyModule)) {
  1640.             throw getRuntime().newTypeError("compared with non class/module");
  1641.         }

  1642.         if (isKindOfModule((RubyModule) obj)) return getRuntime().getTrue();
  1643.         if (((RubyModule) obj).isKindOfModule(this)) return getRuntime().getFalse();

  1644.         return getRuntime().getNil();
  1645.     }

  1646.     /** rb_mod_lt
  1647.     *
  1648.     */
  1649.     @JRubyMethod(name = "<", required = 1)
  1650.    public IRubyObject op_lt(IRubyObject obj) {
  1651.         return obj == this ? getRuntime().getFalse() : op_le(obj);
  1652.     }

  1653.     /** rb_mod_ge
  1654.     *
  1655.     */
  1656.     @JRubyMethod(name = ">=", required = 1)
  1657.    public IRubyObject op_ge(IRubyObject obj) {
  1658.         if (!(obj instanceof RubyModule)) {
  1659.             throw getRuntime().newTypeError("compared with non class/module");
  1660.         }

  1661.         return ((RubyModule) obj).op_le(this);
  1662.     }

  1663.     /** rb_mod_gt
  1664.     *
  1665.     */
  1666.     @JRubyMethod(name = ">", required = 1)
  1667.    public IRubyObject op_gt(IRubyObject obj) {
  1668.         return this == obj ? getRuntime().getFalse() : op_ge(obj);
  1669.     }

  1670.     /** rb_mod_cmp
  1671.     *
  1672.     */
  1673.     @JRubyMethod(name = "<=>", required = 1)
  1674.     public IRubyObject op_cmp(IRubyObject obj) {
  1675.         if (this == obj) return getRuntime().newFixnum(0);
  1676.         if (!(obj instanceof RubyModule)) return getRuntime().getNil();

  1677.         RubyModule module = (RubyModule) obj;

  1678.         if (module.isKindOfModule(this)) return getRuntime().newFixnum(1);
  1679.         if (this.isKindOfModule(module)) return getRuntime().newFixnum(-1);

  1680.         return getRuntime().getNil();
  1681.     }

  1682.     public boolean isKindOfModule(RubyModule type) {
  1683.         for (RubyModule module = this; module != null; module = module.getSuperClass()) {
  1684.             if (module.isSame(type)) return true;
  1685.         }

  1686.         return false;
  1687.     }

  1688.     protected boolean isSame(RubyModule module) {
  1689.         return this == module;
  1690.     }

  1691.     /** rb_mod_initialize
  1692.      *
  1693.      */
  1694.     @JRubyMethod(name = "initialize", visibility = PRIVATE)
  1695.     public IRubyObject initialize(ThreadContext context, Block block) {
  1696.         if (block.isGiven()) {
  1697.             module_exec(context, new IRubyObject[] {this}, block);
  1698.         }

  1699.         return getRuntime().getNil();
  1700.     }
  1701.    
  1702.     public void addReadWriteAttribute(ThreadContext context, String name) {
  1703.         addAccessor(context, name.intern(), PUBLIC, true, true);
  1704.     }
  1705.    
  1706.     public void addReadAttribute(ThreadContext context, String name) {
  1707.         addAccessor(context, name.intern(), PUBLIC, true, false);
  1708.     }
  1709.    
  1710.     public void addWriteAttribute(ThreadContext context, String name) {
  1711.         addAccessor(context, name.intern(), PUBLIC, false, true);
  1712.     }

  1713.     /** rb_mod_attr
  1714.      *
  1715.      */
  1716.     public IRubyObject attr(ThreadContext context, IRubyObject[] args) {
  1717.         return attr19(context, args);
  1718.     }
  1719.    
  1720.     @JRubyMethod(name = "attr", rest = true, visibility = PRIVATE, reads = VISIBILITY)
  1721.     public IRubyObject attr19(ThreadContext context, IRubyObject[] args) {
  1722.         Ruby runtime = context.runtime;

  1723.         if (args.length == 2 && (args[1] == runtime.getTrue() || args[1] == runtime.getFalse())) {
  1724.             runtime.getWarnings().warn(ID.OBSOLETE_ARGUMENT, "optional boolean argument is obsoleted");
  1725.             addAccessor(context, args[0].asJavaString().intern(), context.getCurrentVisibility(), args[0].isTrue(), args[1].isTrue());
  1726.             return runtime.getNil();
  1727.         }

  1728.         return attr_reader(context, args);
  1729.     }

  1730.     @Deprecated
  1731.     public IRubyObject attr_reader(IRubyObject[] args) {
  1732.         return attr_reader(getRuntime().getCurrentContext(), args);
  1733.     }
  1734.    
  1735.     /** rb_mod_attr_reader
  1736.      *
  1737.      */
  1738.     @JRubyMethod(name = "attr_reader", rest = true, visibility = PRIVATE, reads = VISIBILITY)
  1739.     public IRubyObject attr_reader(ThreadContext context, IRubyObject[] args) {
  1740.         // Check the visibility of the previous frame, which will be the frame in which the class is being eval'ed
  1741.         Visibility visibility = context.getCurrentVisibility();

  1742.         for (int i = 0; i < args.length; i++) {
  1743.             addAccessor(context, args[i].asJavaString().intern(), visibility, true, false);
  1744.         }

  1745.         return context.runtime.getNil();
  1746.     }

  1747.     /** rb_mod_attr_writer
  1748.      *
  1749.      */
  1750.     @JRubyMethod(name = "attr_writer", rest = true, visibility = PRIVATE, reads = VISIBILITY)
  1751.     public IRubyObject attr_writer(ThreadContext context, IRubyObject[] args) {
  1752.         // Check the visibility of the previous frame, which will be the frame in which the class is being eval'ed
  1753.         Visibility visibility = context.getCurrentVisibility();

  1754.         for (int i = 0; i < args.length; i++) {
  1755.             addAccessor(context, args[i].asJavaString().intern(), visibility, false, true);
  1756.         }

  1757.         return context.runtime.getNil();
  1758.     }


  1759.     @Deprecated
  1760.     public IRubyObject attr_accessor(IRubyObject[] args) {
  1761.         return attr_accessor(getRuntime().getCurrentContext(), args);
  1762.     }

  1763.     /** rb_mod_attr_accessor
  1764.      *  Note: this method should not be called from Java in most cases, since
  1765.      *  it depends on Ruby frame state for visibility. Use add[Read/Write]Attribute instead.
  1766.      */
  1767.     @JRubyMethod(name = "attr_accessor", rest = true, visibility = PRIVATE, reads = VISIBILITY)
  1768.     public IRubyObject attr_accessor(ThreadContext context, IRubyObject[] args) {
  1769.         // Check the visibility of the previous frame, which will be the frame in which the class is being eval'ed
  1770.         Visibility visibility = context.getCurrentVisibility();

  1771.         for (int i = 0; i < args.length; i++) {
  1772.             // This is almost always already interned, since it will be called with a symbol in most cases
  1773.             // but when created from Java code, we might getService an argument that needs to be interned.
  1774.             // addAccessor has as a precondition that the string MUST be interned
  1775.             addAccessor(context, args[i].asJavaString().intern(), visibility, true, true);
  1776.         }

  1777.         return context.runtime.getNil();
  1778.     }

  1779.     /**
  1780.      * Get a list of all instance methods names of the provided visibility unless not is true, then
  1781.      * getService all methods which are not the provided
  1782.      *
  1783.      * @param args passed into one of the Ruby instance_method methods
  1784.      * @param visibility to find matching instance methods against
  1785.      * @param not if true only find methods not matching supplied visibility
  1786.      * @return a RubyArray of instance method names
  1787.      */
  1788.     private RubyArray instance_methods(IRubyObject[] args, final Visibility visibility, boolean not, boolean useSymbols) {
  1789.         boolean includeSuper = args.length > 0 ? args[0].isTrue() : true;
  1790.         Ruby runtime = getRuntime();
  1791.         RubyArray ary = runtime.newArray();
  1792.         Set<String> seen = new HashSet<String>();

  1793.         populateInstanceMethodNames(seen, ary, visibility, not, useSymbols, includeSuper);

  1794.         return ary;
  1795.     }

  1796.     public void populateInstanceMethodNames(Set<String> seen, RubyArray ary, final Visibility visibility, boolean not, boolean useSymbols, boolean includeSuper) {
  1797.         Ruby runtime = getRuntime();

  1798.         for (RubyModule type = this; type != null; type = type.getSuperClass()) {
  1799.             RubyModule realType = type.getNonIncludedClass();
  1800.             for (Map.Entry entry : type.getMethods().entrySet()) {
  1801.                 String methodName = (String) entry.getKey();

  1802.                 if (! seen.contains(methodName)) {
  1803.                     seen.add(methodName);

  1804.                     DynamicMethod method = (DynamicMethod) entry.getValue();
  1805.                     if ((method.isImplementedBy(realType) || method.isImplementedBy(type)) &&
  1806.                         (!not && method.getVisibility() == visibility || (not && method.getVisibility() != visibility)) &&
  1807.                         ! method.isUndefined()) {

  1808.                         ary.append(useSymbols ? runtime.newSymbol(methodName) : runtime.newString(methodName));
  1809.                     }
  1810.                 }
  1811.             }

  1812.             if (!includeSuper && type == methodLocation) {
  1813.                 break;
  1814.             }
  1815.         }
  1816.     }

  1817.     public RubyArray instance_methods(IRubyObject[] args) {
  1818.         return instance_methods19(args);
  1819.     }

  1820.     @JRubyMethod(name = "instance_methods", optional = 1)
  1821.     public RubyArray instance_methods19(IRubyObject[] args) {
  1822.         return instance_methods(args, PRIVATE, true, true);
  1823.     }

  1824.     public RubyArray public_instance_methods(IRubyObject[] args) {
  1825.         return public_instance_methods19(args);
  1826.     }

  1827.     @JRubyMethod(name = "public_instance_methods", optional = 1)
  1828.     public RubyArray public_instance_methods19(IRubyObject[] args) {
  1829.         return instance_methods(args, PUBLIC, false, true);
  1830.     }

  1831.     @JRubyMethod(name = "instance_method", required = 1)
  1832.     public IRubyObject instance_method(IRubyObject symbol) {
  1833.         return newMethod(null, symbol.asJavaString(), false, null);
  1834.     }

  1835.     /** rb_class_protected_instance_methods
  1836.      *
  1837.      */
  1838.     public RubyArray protected_instance_methods(IRubyObject[] args) {
  1839.         return protected_instance_methods19(args);
  1840.     }

  1841.     @JRubyMethod(name = "protected_instance_methods", optional = 1)
  1842.     public RubyArray protected_instance_methods19(IRubyObject[] args) {
  1843.         return instance_methods(args, PROTECTED, false, true);
  1844.     }

  1845.     /** rb_class_private_instance_methods
  1846.      *
  1847.      */
  1848.     public RubyArray private_instance_methods(IRubyObject[] args) {
  1849.         return private_instance_methods19(args);
  1850.     }

  1851.     @JRubyMethod(name = "private_instance_methods", optional = 1)
  1852.     public RubyArray private_instance_methods19(IRubyObject[] args) {
  1853.         return instance_methods(args, PRIVATE, false, true);
  1854.     }

  1855.     /** rb_mod_prepend_features
  1856.      *
  1857.      */
  1858.     @JRubyMethod(name = "prepend_features", required = 1, visibility = PRIVATE)
  1859.     public RubyModule prepend_features(IRubyObject include) {
  1860.         if (!isModule()) {
  1861.             throw getRuntime().newTypeError(this, getRuntime().getModule());
  1862.         }
  1863.         if (!(include instanceof RubyModule)) {
  1864.             throw getRuntime().newTypeError(include, getRuntime().getModule());
  1865.         }

  1866.         if (!(include.isModule() || include.isClass())) {
  1867.             throw getRuntime().newTypeError(include, getRuntime().getModule());
  1868.         }

  1869.         ((RubyModule) include).prependModule(this);
  1870.         return this;
  1871.     }

  1872.     /** rb_mod_append_features
  1873.      *
  1874.      */
  1875.     @JRubyMethod(name = "append_features", required = 1, visibility = PRIVATE)
  1876.     public RubyModule append_features(IRubyObject include) {
  1877.         if (!isModule()) {
  1878.             throw getRuntime().newTypeError(this, getRuntime().getModule());
  1879.         }
  1880.         if (!(include instanceof RubyModule)) {
  1881.             throw getRuntime().newTypeError(include, getRuntime().getModule());
  1882.         }

  1883.         if (!(include.isModule() || include.isClass())) {
  1884.             throw getRuntime().newTypeError(include, getRuntime().getModule());
  1885.         }

  1886.         ((RubyModule) include).includeModule(this);
  1887.         return this;
  1888.     }

  1889.     /** rb_mod_extend_object
  1890.      *
  1891.      */
  1892.     @JRubyMethod(name = "extend_object", required = 1, visibility = PRIVATE)
  1893.     public IRubyObject extend_object(IRubyObject obj) {
  1894.         obj.getSingletonClass().includeModule(this);
  1895.         return obj;
  1896.     }

  1897.     /** rb_mod_include
  1898.      *
  1899.      */
  1900.     @JRubyMethod(name = "include", rest = true, visibility = PRIVATE)
  1901.     public RubyModule include(IRubyObject[] modules) {
  1902.         ThreadContext context = getRuntime().getCurrentContext();
  1903.         // MRI checks all types first:
  1904.         for (int i = modules.length; --i >= 0; ) {
  1905.             IRubyObject obj = modules[i];
  1906.             if (!obj.isModule()) {
  1907.                 throw context.runtime.newTypeError(obj, context.runtime.getModule());
  1908.             }
  1909.         }
  1910.         for (int i = modules.length - 1; i >= 0; i--) {
  1911.             modules[i].callMethod(context, "append_features", this);
  1912.             modules[i].callMethod(context, "included", this);
  1913.         }

  1914.         return this;
  1915.     }

  1916.     @JRubyMethod(name = "included", required = 1, visibility = PRIVATE)
  1917.     public IRubyObject included(ThreadContext context, IRubyObject other) {
  1918.         return context.runtime.getNil();
  1919.     }

  1920.     @JRubyMethod(name = "extended", required = 1, visibility = PRIVATE)
  1921.     public IRubyObject extended(ThreadContext context, IRubyObject other, Block block) {
  1922.         return context.runtime.getNil();
  1923.     }

  1924.     @JRubyMethod(name = "mix", visibility = PRIVATE)
  1925.     public IRubyObject mix(ThreadContext context, IRubyObject mod) {
  1926.         Ruby runtime = context.runtime;

  1927.         if (!mod.isModule()) {
  1928.             throw runtime.newTypeError(mod, runtime.getModule());
  1929.         }

  1930.         for (Map.Entry<String, DynamicMethod> entry : ((RubyModule)mod).methods.entrySet()) {
  1931.             if (methodLocation.getMethods().containsKey(entry.getKey())) {
  1932.                 throw runtime.newArgumentError("method would conflict - " + entry.getKey());
  1933.             }
  1934.         }

  1935.         for (Map.Entry<String, DynamicMethod> entry : ((RubyModule)mod).methods.entrySet()) {
  1936.             methodLocation.getMethodsForWrite().put(entry.getKey(), entry.getValue().dup());
  1937.         }

  1938.         return mod;
  1939.     }

  1940.     @JRubyMethod(name = "mix", visibility = PRIVATE)
  1941.     public IRubyObject mix(ThreadContext context, IRubyObject mod, IRubyObject hash0) {
  1942.         Ruby runtime = context.runtime;
  1943.         RubyHash methodNames = null;

  1944.         if (!mod.isModule()) {
  1945.             throw runtime.newTypeError(mod, runtime.getModule());
  1946.         }

  1947.         if (hash0 instanceof RubyHash) {
  1948.             methodNames = (RubyHash)hash0;
  1949.         } else {
  1950.             throw runtime.newTypeError(hash0, runtime.getHash());
  1951.         }
  1952.        
  1953.         for (Map.Entry<IRubyObject, IRubyObject> entry : (Set<Map.Entry<IRubyObject, IRubyObject>>)methodNames.directEntrySet()) {
  1954.             String name = entry.getValue().toString();
  1955.             if (methods.containsKey(entry.getValue().toString())) {
  1956.                 throw runtime.newArgumentError("constant would conflict - " + name);
  1957.             }
  1958.         }

  1959.         for (Map.Entry<String, DynamicMethod> entry : ((RubyModule)mod).methods.entrySet()) {
  1960.             if (methods.containsKey(entry.getKey())) {
  1961.                 throw runtime.newArgumentError("method would conflict - " + entry.getKey());
  1962.             }
  1963.         }

  1964.         for (Map.Entry<String, DynamicMethod> entry : ((RubyModule)mod).methods.entrySet()) {
  1965.             String name = entry.getKey();
  1966.             IRubyObject mapped = methodNames.fastARef(runtime.newSymbol(name));
  1967.             if (mapped == NEVER) {
  1968.                 // unmapped
  1969.             } else if (mapped == context.nil) {
  1970.                 // do not mix
  1971.                 continue;
  1972.             } else {
  1973.                 name = mapped.toString();
  1974.             }
  1975.             methodLocation.getMethodsForWrite().put(name, entry.getValue().dup());
  1976.         }

  1977.         return mod;
  1978.     }

  1979.     private void setVisibility(ThreadContext context, IRubyObject[] args, Visibility visibility) {
  1980.         if (args.length == 0) {
  1981.             // Note: we change current frames visibility here because the methods which call
  1982.             // this method are all "fast" (e.g. they do not created their own frame).
  1983.             context.setCurrentVisibility(visibility);
  1984.         } else {
  1985.             setMethodVisibility(args, visibility);
  1986.         }
  1987.     }

  1988.     /** rb_mod_public
  1989.      *
  1990.      */
  1991.     @JRubyMethod(name = "public", rest = true, visibility = PRIVATE, writes = VISIBILITY)
  1992.     public RubyModule rbPublic(ThreadContext context, IRubyObject[] args) {
  1993.         setVisibility(context, args, PUBLIC);
  1994.         return this;
  1995.     }

  1996.     /** rb_mod_protected
  1997.      *
  1998.      */
  1999.     @JRubyMethod(name = "protected", rest = true, visibility = PRIVATE, writes = VISIBILITY)
  2000.     public RubyModule rbProtected(ThreadContext context, IRubyObject[] args) {
  2001.         setVisibility(context, args, PROTECTED);
  2002.         return this;
  2003.     }

  2004.     /** rb_mod_private
  2005.      *
  2006.      */
  2007.     @JRubyMethod(name = "private", rest = true, visibility = PRIVATE, writes = VISIBILITY)
  2008.     public RubyModule rbPrivate(ThreadContext context, IRubyObject[] args) {
  2009.         setVisibility(context, args, PRIVATE);
  2010.         return this;
  2011.     }

  2012.     /** rb_mod_modfunc
  2013.      *
  2014.      */
  2015.     @JRubyMethod(name = "module_function", rest = true, visibility = PRIVATE, writes = VISIBILITY)
  2016.     public RubyModule module_function(ThreadContext context, IRubyObject[] args) {
  2017.         Ruby runtime = context.runtime;

  2018.         if (args.length == 0) {
  2019.             context.setCurrentVisibility(MODULE_FUNCTION);
  2020.         } else {
  2021.             setMethodVisibility(args, PRIVATE);

  2022.             for (int i = 0; i < args.length; i++) {
  2023.                 String name = args[i].asJavaString().intern();
  2024.                 DynamicMethod method = deepMethodSearch(name, runtime);
  2025.                 getSingletonClass().addMethod(name, new WrapperMethod(getSingletonClass(), method, PUBLIC));
  2026.                 callMethod(context, "singleton_method_added", context.runtime.fastNewSymbol(name));
  2027.             }
  2028.         }
  2029.         return this;
  2030.     }

  2031.     @JRubyMethod(name = "method_added", required = 1, visibility = PRIVATE)
  2032.     public IRubyObject method_added(ThreadContext context, IRubyObject nothing) {
  2033.         return context.runtime.getNil();
  2034.     }

  2035.     @JRubyMethod(name = "method_removed", required = 1, visibility = PRIVATE)
  2036.     public IRubyObject method_removed(ThreadContext context, IRubyObject nothing) {
  2037.         return context.runtime.getNil();
  2038.     }

  2039.     @JRubyMethod(name = "method_undefined", required = 1, visibility = PRIVATE)
  2040.     public IRubyObject method_undefined(ThreadContext context, IRubyObject nothing) {
  2041.         return context.runtime.getNil();
  2042.     }
  2043.    
  2044.     @JRubyMethod(name = "method_defined?", required = 1)
  2045.     public RubyBoolean method_defined_p(ThreadContext context, IRubyObject symbol) {
  2046.         return isMethodBound(symbol.asJavaString(), true) ? context.runtime.getTrue() : context.runtime.getFalse();
  2047.     }

  2048.     @JRubyMethod(name = "public_method_defined?", required = 1)
  2049.     public IRubyObject public_method_defined(ThreadContext context, IRubyObject symbol) {
  2050.         DynamicMethod method = searchMethod(symbol.asJavaString());

  2051.         return context.runtime.newBoolean(!method.isUndefined() && method.getVisibility() == PUBLIC);
  2052.     }

  2053.     @JRubyMethod(name = "protected_method_defined?", required = 1)
  2054.     public IRubyObject protected_method_defined(ThreadContext context, IRubyObject symbol) {
  2055.         DynamicMethod method = searchMethod(symbol.asJavaString());

  2056.         return context.runtime.newBoolean(!method.isUndefined() && method.getVisibility() == PROTECTED);
  2057.     }
  2058.    
  2059.     @JRubyMethod(name = "private_method_defined?", required = 1)
  2060.     public IRubyObject private_method_defined(ThreadContext context, IRubyObject symbol) {
  2061.         DynamicMethod method = searchMethod(symbol.asJavaString());

  2062.         return context.runtime.newBoolean(!method.isUndefined() && method.getVisibility() == PRIVATE);
  2063.     }

  2064.     @JRubyMethod(name = "public_class_method", rest = true)
  2065.     public RubyModule public_class_method(IRubyObject[] args) {
  2066.         getSingletonClass().setMethodVisibility(args, PUBLIC);
  2067.         return this;
  2068.     }

  2069.     @JRubyMethod(name = "private_class_method", rest = true)
  2070.     public RubyModule private_class_method(IRubyObject[] args) {
  2071.         getSingletonClass().setMethodVisibility(args, PRIVATE);
  2072.         return this;
  2073.     }

  2074.     @JRubyMethod(name = "alias_method", required = 2, visibility = PRIVATE)
  2075.     public RubyModule alias_method(ThreadContext context, IRubyObject newId, IRubyObject oldId) {
  2076.         String newName = newId.asJavaString();
  2077.         defineAlias(newName, oldId.asJavaString());
  2078.         RubySymbol newSym = newId instanceof RubySymbol ? (RubySymbol)newId :
  2079.             context.runtime.newSymbol(newName);
  2080.         if (isSingleton()) {
  2081.             ((MetaClass)this).getAttached().callMethod(context, "singleton_method_added", newSym);
  2082.         } else {
  2083.             callMethod(context, "method_added", newSym);
  2084.         }
  2085.         return this;
  2086.     }

  2087.     @JRubyMethod(name = "undef_method", rest = true, visibility = PRIVATE)
  2088.     public RubyModule undef_method(ThreadContext context, IRubyObject[] args) {
  2089.         for (int i=0; i<args.length; i++) {
  2090.             undef(context, args[i].asJavaString());
  2091.         }
  2092.         return this;
  2093.     }

  2094.     @JRubyMethod(name = {"module_eval", "class_eval"},
  2095.             reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE},
  2096.             writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE})
  2097.     public IRubyObject module_eval(ThreadContext context, Block block) {
  2098.         return specificEval(context, this, block, EvalType.MODULE_EVAL);
  2099.     }
  2100.     @JRubyMethod(name = {"module_eval", "class_eval"},
  2101.             reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE},
  2102.             writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE})
  2103.     public IRubyObject module_eval(ThreadContext context, IRubyObject arg0, Block block) {
  2104.         return specificEval(context, this, arg0, block, EvalType.MODULE_EVAL);
  2105.     }
  2106.     @JRubyMethod(name = {"module_eval", "class_eval"},
  2107.             reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE},
  2108.             writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE})
  2109.     public IRubyObject module_eval(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
  2110.         return specificEval(context, this, arg0, arg1, block, EvalType.MODULE_EVAL);
  2111.     }
  2112.     @JRubyMethod(name = {"module_eval", "class_eval"},
  2113.             reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE},
  2114.             writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE})
  2115.     public IRubyObject module_eval(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
  2116.         return specificEval(context, this, arg0, arg1, arg2, block, EvalType.MODULE_EVAL);
  2117.     }
  2118.     @Deprecated
  2119.     public IRubyObject module_eval(ThreadContext context, IRubyObject[] args, Block block) {
  2120.         return specificEval(context, this, args, block, EvalType.MODULE_EVAL);
  2121.     }

  2122.     @JRubyMethod(name = {"module_exec", "class_exec"},
  2123.             reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE},
  2124.             writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE})
  2125.     public IRubyObject module_exec(ThreadContext context, Block block) {
  2126.         if (block.isGiven()) {
  2127.             return yieldUnder(context, this, IRubyObject.NULL_ARRAY, block, EvalType.MODULE_EVAL);
  2128.         } else {
  2129.             throw context.runtime.newLocalJumpErrorNoBlock();
  2130.         }
  2131.     }

  2132.     @JRubyMethod(name = {"module_exec", "class_exec"}, rest = true,
  2133.             reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE},
  2134.             writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, JUMPTARGET, CLASS, FILENAME, SCOPE})
  2135.     public IRubyObject module_exec(ThreadContext context, IRubyObject[] args, Block block) {
  2136.         if (block.isGiven()) {
  2137.             return yieldUnder(context, this, args, block, EvalType.MODULE_EVAL);
  2138.         } else {
  2139.             throw context.runtime.newLocalJumpErrorNoBlock();
  2140.         }
  2141.     }

  2142.     @JRubyMethod(name = "remove_method", rest = true, visibility = PRIVATE)
  2143.     public RubyModule remove_method(ThreadContext context, IRubyObject[] args) {
  2144.         for(int i=0;i<args.length;i++) {
  2145.             removeMethod(context, args[i].asJavaString());
  2146.         }
  2147.         return this;
  2148.     }

  2149.     public static void marshalTo(RubyModule module, MarshalStream output) throws java.io.IOException {
  2150.         output.registerLinkTarget(module);
  2151.         output.writeString(MarshalStream.getPathFromClass(module));
  2152.     }

  2153.     public static RubyModule unmarshalFrom(UnmarshalStream input) throws java.io.IOException {
  2154.         String name = RubyString.byteListToString(input.unmarshalString());
  2155.         RubyModule result = UnmarshalStream.getModuleFromPath(input.getRuntime(), name);
  2156.         input.registerLinkTarget(result);
  2157.         return result;
  2158.     }

  2159.     /* Module class methods */
  2160.    
  2161.     /**
  2162.      * Return an array of nested modules or classes.
  2163.      */
  2164.     @JRubyMethod(name = "nesting", reads = SCOPE, meta = true)
  2165.     public static RubyArray nesting(ThreadContext context, IRubyObject recv, Block block) {
  2166.         Ruby runtime = context.runtime;
  2167.         RubyModule object = runtime.getObject();
  2168.         StaticScope scope = context.getCurrentScope().getStaticScope();
  2169.         RubyArray result = runtime.newArray();
  2170.        
  2171.         for (StaticScope current = scope; current.getModule() != object; current = current.getPreviousCRefScope()) {
  2172.             result.append(current.getModule());
  2173.         }
  2174.        
  2175.         return result;
  2176.     }

  2177.     /**
  2178.      * Include the given module and all related modules into the hierarchy above
  2179.      * this module/class. Inspects the hierarchy to ensure the same module isn't
  2180.      * included twice, and selects an appropriate insertion point for each incoming
  2181.      * module.
  2182.      *
  2183.      * @param baseModule The module to include, along with any modules it itself includes
  2184.      */
  2185.     private void doIncludeModule(RubyModule baseModule) {
  2186.         List<RubyModule> modulesToInclude = gatherModules(baseModule);
  2187.        
  2188.         RubyModule currentInclusionPoint = methodLocation;
  2189.         ModuleLoop: for (RubyModule nextModule : modulesToInclude) {
  2190.             checkForCyclicInclude(nextModule);

  2191.             boolean superclassSeen = false;

  2192.             // nextClass.isIncluded() && nextClass.getNonIncludedClass() == nextModule.getNonIncludedClass();
  2193.             // scan class hierarchy for module
  2194.             for (RubyClass nextClass = methodLocation.getSuperClass(); nextClass != null; nextClass = nextClass.getSuperClass()) {
  2195.                 if (doesTheClassWrapTheModule(nextClass, nextModule)) {
  2196.                     // next in hierarchy is an included version of the module we're attempting,
  2197.                     // so we skip including it

  2198.                     // if we haven't encountered a real superclass, use the found module as the new inclusion point
  2199.                     if (!superclassSeen) currentInclusionPoint = nextClass;

  2200.                     continue ModuleLoop;
  2201.                 } else {
  2202.                     superclassSeen = true;
  2203.                 }
  2204.             }

  2205.             currentInclusionPoint = proceedWithInclude(currentInclusionPoint, nextModule.getDelegate());
  2206.         }
  2207.     }

  2208.     /**
  2209.      * Prepend the given module and all related modules into the hierarchy above
  2210.      * this module/class. Inspects the hierarchy to ensure the same module isn't
  2211.      * included twice, and selects an appropriate insertion point for each incoming
  2212.      * module.
  2213.      *
  2214.      * @param baseModule The module to prepend, along with any modules it itself includes
  2215.      */
  2216.     private void doPrependModule(RubyModule baseModule) {
  2217.         List<RubyModule> modulesToInclude = gatherModules(baseModule);

  2218.         RubyClass insertBelowSuperClass = null;
  2219.         if (methodLocation == this) {
  2220.             // In the current logic, if we getService here we know that module is not an
  2221.             // IncludedModule, so there's no need to fish out the delegate. But just
  2222.             // in case the logic should change later, let's do it anyway
  2223.             RubyClass prep = new PrependedModule(getRuntime(), getSuperClass(), this);

  2224.             // if the insertion point is a class, update subclass lists
  2225.             if (this instanceof RubyClass) {
  2226.                 RubyClass insertBelowClass = (RubyClass)this;

  2227.                 // if there's a non-null superclass, we're including into a normal class hierarchy;
  2228.                 // update subclass relationships to avoid stale parent/child relationships
  2229.                 if (insertBelowClass.getSuperClass() != null) {
  2230.                     insertBelowClass.getSuperClass().replaceSubclass(insertBelowClass, prep);
  2231.                 }

  2232.                 prep.addSubclass(insertBelowClass);
  2233.             }
  2234.             setSuperClass(prep);
  2235.         }

  2236.         RubyModule currentInclusionPoint = this;
  2237.         ModuleLoop: for (RubyModule nextModule : modulesToInclude) {
  2238.             checkForCyclicInclude(nextModule);

  2239.             boolean superclassSeen = false;

  2240.             // scan class hierarchy for module
  2241.             for (RubyClass nextClass = this.getSuperClass(); nextClass != null; nextClass = nextClass.getSuperClass()) {
  2242.                 if (doesTheClassWrapTheModule(nextClass, nextModule)) {
  2243.                     // next in hierarchy is an included version of the module we're attempting,
  2244.                     // so we skip including it

  2245.                     // if we haven't encountered a real superclass, use the found module as the new inclusion point
  2246.                     if (!superclassSeen) currentInclusionPoint = nextClass;

  2247.                     continue ModuleLoop;
  2248.                 } else {
  2249.                     superclassSeen = true;
  2250.                 }
  2251.             }

  2252.             currentInclusionPoint = proceedWithPrepend(currentInclusionPoint, nextModule);
  2253.         }
  2254.     }

  2255.     /**
  2256.      * Is the given class a wrapper for the specified module?
  2257.      *
  2258.      * @param theClass The class to inspect
  2259.      * @param theModule The module we're looking for
  2260.      * @return true if the class is a wrapper for the module, false otherwise
  2261.      */
  2262.     private boolean doesTheClassWrapTheModule(RubyClass theClass, RubyModule theModule) {
  2263.         return theClass.isIncluded() &&
  2264.                 theClass.getDelegate() == theModule.getDelegate();
  2265.     }

  2266.     /**
  2267.      * Gather all modules that would be included by including the given module.
  2268.      * The resulting list contains the given module and its (zero or more)
  2269.      * module-wrapping superclasses.
  2270.      *
  2271.      * @param baseModule The base module from which to aggregate modules
  2272.      * @return A list of all modules that would be included by including the given module
  2273.      */
  2274.     private List<RubyModule> gatherModules(RubyModule baseModule) {
  2275.         // build a list of all modules to consider for inclusion
  2276.         List<RubyModule> modulesToInclude = new ArrayList<RubyModule>();
  2277.         while (baseModule != null) {
  2278.             modulesToInclude.add(baseModule.getDelegate());
  2279.             baseModule = baseModule.getSuperClass();
  2280.         }

  2281.         return modulesToInclude;
  2282.     }

  2283.     /**
  2284.      * Actually proceed with including the specified module above the given target
  2285.      * in a hierarchy. Return the new module wrapper.
  2286.      *
  2287.      * @param insertAbove The hierarchy target above which to include the wrapped module
  2288.      * @param moduleToInclude The module to wrap and include
  2289.      * @return The new module wrapper resulting from this include
  2290.      */
  2291.     private RubyModule proceedWithInclude(RubyModule insertAbove, RubyModule moduleToInclude) {
  2292.         // In the current logic, if we getService here we know that module is not an
  2293.         // IncludedModuleWrapper, so there's no need to fish out the delegate. But just
  2294.         // in case the logic should change later, let's do it anyway
  2295.         RubyClass wrapper = new IncludedModuleWrapper(getRuntime(), insertAbove.getSuperClass(), moduleToInclude);

  2296.         // if the insertion point is a class, update subclass lists
  2297.         if (insertAbove instanceof RubyClass) {
  2298.             RubyClass insertAboveClass = (RubyClass)insertAbove;

  2299.             // if there's a non-null superclass, we're including into a normal class hierarchy;
  2300.             // update subclass relationships to avoid stale parent/child relationships
  2301.             if (insertAboveClass.getSuperClass() != null) {
  2302.                 insertAboveClass.getSuperClass().replaceSubclass(insertAboveClass, wrapper);
  2303.             }

  2304.             wrapper.addSubclass(insertAboveClass);
  2305.         }

  2306.         insertAbove.setSuperClass(wrapper);
  2307.         insertAbove = insertAbove.getSuperClass();
  2308.         return insertAbove;
  2309.     }

  2310.     /**
  2311.      * Actually proceed with prepending the specified module below the given target
  2312.      * in a hierarchy. Return the new module wrapper.
  2313.      *
  2314.      * @param insertBelow The hierarchy target below which to include the wrapped module
  2315.      * @param moduleToPrepend The module to wrap and prepend
  2316.      * @return The new module wrapper resulting from this prepend
  2317.      */
  2318.     private RubyModule proceedWithPrepend(RubyModule insertBelow, RubyModule moduleToPrepend) {
  2319.         if (!moduleToPrepend.isPrepended()) moduleToPrepend = moduleToPrepend.getNonIncludedClass();

  2320.         RubyModule newInclusionPoint = proceedWithInclude(insertBelow, moduleToPrepend);

  2321.         return newInclusionPoint;
  2322.     }


  2323.     //
  2324.     ////////////////// CLASS VARIABLE RUBY METHODS ////////////////
  2325.     //

  2326.     @JRubyMethod(name = "class_variable_defined?", required = 1)
  2327.     public IRubyObject class_variable_defined_p(ThreadContext context, IRubyObject var) {
  2328.         String internedName = validateClassVariable(var.asJavaString().intern());
  2329.         RubyModule module = this;
  2330.         do {
  2331.             if (module.hasClassVariable(internedName)) {
  2332.                 return context.runtime.getTrue();
  2333.             }
  2334.         } while ((module = module.getSuperClass()) != null);

  2335.         return context.runtime.getFalse();
  2336.     }

  2337.     /** rb_mod_cvar_get
  2338.      *
  2339.      */
  2340.     public IRubyObject class_variable_get(IRubyObject var) {
  2341.         return getClassVar(validateClassVariable(var.asJavaString()).intern());
  2342.     }

  2343.     @JRubyMethod(name = "class_variable_get")
  2344.     public IRubyObject class_variable_get19(IRubyObject var) {
  2345.         return class_variable_get(var);
  2346.     }

  2347.     /** rb_mod_cvar_set
  2348.      *
  2349.      */
  2350.     public IRubyObject class_variable_set(IRubyObject var, IRubyObject value) {
  2351.         return setClassVar(validateClassVariable(var.asJavaString()).intern(), value);
  2352.     }

  2353.     @JRubyMethod(name = "class_variable_set")
  2354.     public IRubyObject class_variable_set19(IRubyObject var, IRubyObject value) {
  2355.         return class_variable_set(var, value);
  2356.     }

  2357.     /** rb_mod_remove_cvar
  2358.      *
  2359.      */
  2360.     public IRubyObject remove_class_variable(ThreadContext context, IRubyObject name) {
  2361.         return removeClassVariable(name.asJavaString());
  2362.     }

  2363.     @JRubyMethod(name = "remove_class_variable")
  2364.     public IRubyObject remove_class_variable19(ThreadContext context, IRubyObject name) {
  2365.         return remove_class_variable(context, name);
  2366.     }

  2367.     /** rb_mod_class_variables
  2368.      *
  2369.      */
  2370.     public RubyArray class_variables(ThreadContext context) {
  2371.         return class_variables19(context);
  2372.     }

  2373.     @JRubyMethod(name = "class_variables")
  2374.     public RubyArray class_variables19(ThreadContext context) {
  2375.         Ruby runtime = context.runtime;
  2376.         RubyArray ary = runtime.newArray();
  2377.        
  2378.         Collection<String> names = classVariablesCommon();
  2379.         for (String name : names) {
  2380.             ary.add(runtime.newSymbol(name));
  2381.         }
  2382.         return ary;
  2383.     }

  2384.     private Collection<String> classVariablesCommon() {
  2385.         Set<String> names = new HashSet<String>();
  2386.         for (RubyModule p = this; p != null; p = p.getSuperClass()) {
  2387.             names.addAll(p.getClassVariableNameList());
  2388.         }
  2389.         return names;
  2390.     }


  2391.     //
  2392.     ////////////////// CONSTANT RUBY METHODS ////////////////
  2393.     //

  2394.     /** rb_mod_const_defined
  2395.      *
  2396.      */
  2397.     public RubyBoolean const_defined_p(ThreadContext context, IRubyObject symbol) {
  2398.         return const_defined_p19(context, new IRubyObject[]{symbol});
  2399.     }

  2400.     @JRubyMethod(name = "const_defined?", required = 1, optional = 1)
  2401.     public RubyBoolean const_defined_p19(ThreadContext context, IRubyObject[] args) {
  2402.         IRubyObject symbol = args[0];
  2403.         boolean inherit = args.length == 1 || (!args[1].isNil() && args[1].isTrue());

  2404.         // Note: includes part of fix for JRUBY-1339
  2405.         return context.runtime.newBoolean(fastIsConstantDefined19(validateConstant(symbol).intern(), inherit));
  2406.     }

  2407.     /** rb_mod_const_get
  2408.      *
  2409.      */
  2410.     public IRubyObject const_get(IRubyObject symbol) {
  2411.         return const_get_2_0(getRuntime().getCurrentContext(), new IRubyObject[]{symbol});
  2412.     }

  2413.     public IRubyObject const_get_1_9(ThreadContext context, IRubyObject[] args) {
  2414.         return const_get_2_0(context, args);
  2415.     }

  2416.     @JRubyMethod(name = "const_get", required = 1, optional = 1)
  2417.     public IRubyObject const_get_2_0(ThreadContext context, IRubyObject[] args) {
  2418.         String fullName = args[0].asJavaString();
  2419.         String symbol = fullName;
  2420.         boolean inherit = args.length == 1 || (!args[1].isNil() && args[1].isTrue());

  2421.         RubyModule mod = this;
  2422.         int sep;
  2423.         while((sep = symbol.indexOf("::")) != -1) {
  2424.             String segment = symbol.substring(0, sep);
  2425.             symbol = symbol.substring(sep + 2);
  2426.             IRubyObject obj = mod.getConstant(validateConstant(segment, args[0]), inherit, inherit);
  2427.             if(obj instanceof RubyModule) {
  2428.                 mod = (RubyModule)obj;
  2429.             } else {
  2430.                 throw context.runtime.newTypeError(segment + " does not refer to class/module");
  2431.             }
  2432.         }

  2433.         return mod.getConstant(validateConstant(symbol, args[0]), inherit, inherit);
  2434.     }

  2435.     /** rb_mod_const_set
  2436.      *
  2437.      */
  2438.     @JRubyMethod(name = "const_set", required = 2)
  2439.     public IRubyObject const_set(IRubyObject symbol, IRubyObject value) {
  2440.         IRubyObject constant = setConstant(validateConstant(symbol).intern(), value);

  2441.         if (constant instanceof RubyModule) {
  2442.             ((RubyModule)constant).calculateName();
  2443.         }
  2444.         return constant;
  2445.     }

  2446.     @JRubyMethod(name = "remove_const", required = 1, visibility = PRIVATE)
  2447.     public IRubyObject remove_const(ThreadContext context, IRubyObject rubyName) {
  2448.         String name = validateConstant(rubyName);
  2449.         IRubyObject value;
  2450.         if ((value = deleteConstant(name)) != null) {
  2451.             invalidateConstantCache(name);
  2452.             if (value != UNDEF) {
  2453.                 return value;
  2454.             }
  2455.             removeAutoload(name);
  2456.             // FIXME: I'm not sure this is right, but the old code returned
  2457.             // the undef, which definitely isn't right...
  2458.             return context.runtime.getNil();
  2459.         }

  2460.         if (hasConstantInHierarchy(name)) {
  2461.             throw cannotRemoveError(name);
  2462.         }

  2463.         throw context.runtime.newNameError("constant " + name + " not defined for " + getName(), name);
  2464.     }

  2465.     private boolean hasConstantInHierarchy(final String name) {
  2466.         for (RubyModule p = this; p != null; p = p.getSuperClass()) {
  2467.             if (p.hasConstant(name)) {
  2468.                 return true;
  2469.             }
  2470.         }
  2471.         return false;
  2472.     }
  2473.    
  2474.     /**
  2475.      * Base implementation of Module#const_missing, throws NameError for specific missing constant.
  2476.      *
  2477.      * @param rubyName The constant name which was found to be missing
  2478.      * @return Nothing! Absolutely nothing! (though subclasses might choose to return something)
  2479.      */
  2480.     @JRubyMethod(name = "const_missing", required = 1)
  2481.     public IRubyObject const_missing(ThreadContext context, IRubyObject rubyName, Block block) {
  2482.         Ruby runtime = context.runtime;
  2483.         String name;
  2484.        
  2485.         if (this != runtime.getObject()) {
  2486.             name = getName() + "::" + rubyName.asJavaString();
  2487.         } else {
  2488.             name = rubyName.asJavaString();
  2489.         }

  2490.         throw runtime.newNameErrorObject("uninitialized constant " + name, runtime.newSymbol(name));
  2491.     }

  2492.     public RubyArray constants(ThreadContext context) {
  2493.         return constants19(context);
  2494.     }

  2495.     @JRubyMethod(name = "constants")
  2496.     public RubyArray constants19(ThreadContext context) {
  2497.         return constantsCommon19(context, true, true);
  2498.     }

  2499.     @JRubyMethod(name = "constants")
  2500.     public RubyArray constants19(ThreadContext context, IRubyObject allConstants) {
  2501.         return constantsCommon19(context, false, allConstants.isTrue());
  2502.     }
  2503.    
  2504.     public RubyArray constantsCommon19(ThreadContext context, boolean replaceModule, boolean allConstants) {
  2505.         Ruby runtime = context.runtime;
  2506.         RubyArray array = runtime.newArray();
  2507.        
  2508.         Collection<String> constantNames = constantsCommon(runtime, replaceModule, allConstants, false);
  2509.        
  2510.         for (String name : constantNames) {
  2511.             array.add(runtime.newSymbol(name));
  2512.         }
  2513.         return array;
  2514.     }

  2515.     /** rb_mod_constants
  2516.      *
  2517.      */
  2518.     public Collection<String> constantsCommon(Ruby runtime, boolean replaceModule, boolean allConstants) {
  2519.         return constantsCommon(runtime, replaceModule, allConstants, true);
  2520.     }


  2521.     public Collection<String> constantsCommon(Ruby runtime, boolean replaceModule, boolean allConstants, boolean includePrivate) {
  2522.         RubyModule objectClass = runtime.getObject();

  2523.         Collection<String> constantNames = new HashSet<String>();
  2524.         if (allConstants) {
  2525.             if ((replaceModule && runtime.getModule() == this) || objectClass == this) {
  2526.                 constantNames = objectClass.getConstantNames(includePrivate);
  2527.             } else {
  2528.                 Set<String> names = new HashSet<String>();
  2529.                 for (RubyModule module = this; module != null && module != objectClass; module = module.getSuperClass()) {
  2530.                     names.addAll(module.getConstantNames(includePrivate));
  2531.                 }
  2532.                 constantNames = names;
  2533.             }
  2534.         } else {
  2535.             if ((replaceModule && runtime.getModule() == this) || objectClass == this) {
  2536.                 constantNames = objectClass.getConstantNames(includePrivate);
  2537.             } else {
  2538.                 constantNames = getConstantNames(includePrivate);
  2539.             }
  2540.         }

  2541.         return constantNames;
  2542.     }

  2543.     @JRubyMethod
  2544.     public IRubyObject private_constant(ThreadContext context, IRubyObject rubyName) {
  2545.         String name = validateConstant(rubyName);

  2546.         setConstantVisibility(context, name, true);
  2547.         invalidateConstantCache(name);

  2548.         return this;
  2549.     }

  2550.     @JRubyMethod(required = 1, rest = true)
  2551.     public IRubyObject private_constant(ThreadContext context, IRubyObject[] rubyNames) {
  2552.         for (IRubyObject rubyName : rubyNames) {
  2553.             String name = validateConstant(rubyName);

  2554.             setConstantVisibility(context, name, true);
  2555.             invalidateConstantCache(name);
  2556.         }
  2557.         return this;
  2558.     }

  2559.     @JRubyMethod
  2560.     public IRubyObject public_constant(ThreadContext context, IRubyObject rubyName) {
  2561.         String name = validateConstant(rubyName);

  2562.         setConstantVisibility(context, name, false);
  2563.         invalidateConstantCache(name);
  2564.         return this;
  2565.     }

  2566.     @JRubyMethod(required = 1, rest = true)
  2567.     public IRubyObject public_constant(ThreadContext context, IRubyObject[] rubyNames) {
  2568.         for (IRubyObject rubyName : rubyNames) {
  2569.             String name = validateConstant(rubyName);
  2570.             setConstantVisibility(context, name, false);
  2571.             invalidateConstantCache(name);
  2572.         }
  2573.         return this;
  2574.     }

  2575.     @JRubyMethod(name = "prepend", rest = true, visibility = PUBLIC)
  2576.     public IRubyObject prepend(ThreadContext context, IRubyObject[] modules) {
  2577.         // MRI checks all types first:
  2578.         for (int i = modules.length; --i >= 0; ) {
  2579.             IRubyObject obj = modules[i];
  2580.             if (!obj.isModule()) {
  2581.                 throw context.runtime.newTypeError(obj, context.runtime.getModule());
  2582.             }
  2583.         }
  2584.         for (int i = modules.length - 1; i >= 0; i--) {
  2585.             modules[i].callMethod(context, "prepend_features", this);
  2586.             modules[i].callMethod(context, "prepended", this);
  2587.         }

  2588.         return this;
  2589.     }

  2590.     @JRubyMethod(name = "prepended", required = 1, visibility = PRIVATE)
  2591.     public IRubyObject prepended(ThreadContext context, IRubyObject other) {
  2592.         return context.runtime.getNil();
  2593.     }

  2594.     private void setConstantVisibility(ThreadContext context, String name, boolean hidden) {
  2595.         ConstantEntry entry = getConstantMap().get(name);

  2596.         if (entry == null) {
  2597.             throw context.runtime.newNameError("constant " + getName() + "::" + name + " not defined", name);
  2598.         }

  2599.         getConstantMapForWrite().put(name, new ConstantEntry(entry.value, hidden));
  2600.     }

  2601.     //
  2602.     ////////////////// CLASS VARIABLE API METHODS ////////////////
  2603.     //

  2604.     /**
  2605.      * Set the named class variable to the given value, provided taint and freeze allow setting it.
  2606.      *
  2607.      * Ruby C equivalent = "rb_cvar_set"
  2608.      *
  2609.      * @param name The variable name to set
  2610.      * @param value The value to set it to
  2611.      */
  2612.     public IRubyObject setClassVar(String name, IRubyObject value) {
  2613.         RubyModule module = this;
  2614.         do {
  2615.             if (module.hasClassVariable(name)) {
  2616.                 return module.storeClassVariable(name, value);
  2617.             }
  2618.         } while ((module = module.getSuperClass()) != null);
  2619.        
  2620.         return storeClassVariable(name, value);
  2621.     }

  2622.     @Deprecated
  2623.     public IRubyObject fastSetClassVar(final String internedName, final IRubyObject value) {
  2624.         return setClassVar(internedName, value);
  2625.     }

  2626.     /**
  2627.      * Retrieve the specified class variable, searching through this module, included modules, and supermodules.
  2628.      *
  2629.      * Ruby C equivalent = "rb_cvar_get"
  2630.      *
  2631.      * @param name The name of the variable to retrieve
  2632.      * @return The variable's value, or throws NameError if not found
  2633.      */
  2634.     public IRubyObject getClassVar(String name) {
  2635.         assert IdUtil.isClassVariable(name);
  2636.         Object value;
  2637.         RubyModule module = this;

  2638.         do {
  2639.             if ((value = module.fetchClassVariable(name)) != null) return (IRubyObject)value;
  2640.         } while ((module = module.getSuperClass()) != null);

  2641.         throw getRuntime().newNameError("uninitialized class variable " + name + " in " + getName(), name);
  2642.     }

  2643.     @Deprecated
  2644.     public IRubyObject fastGetClassVar(String internedName) {
  2645.         return getClassVar(internedName);
  2646.     }

  2647.     /**
  2648.      * Is class var defined?
  2649.      *
  2650.      * Ruby C equivalent = "rb_cvar_defined"
  2651.      *
  2652.      * @param name The class var to determine "is defined?"
  2653.      * @return true if true, false if false
  2654.      */
  2655.     public boolean isClassVarDefined(String name) {
  2656.         RubyModule module = this;
  2657.         do {
  2658.             if (module.hasClassVariable(name)) return true;
  2659.         } while ((module = module.getSuperClass()) != null);

  2660.         return false;
  2661.     }

  2662.     @Deprecated
  2663.     public boolean fastIsClassVarDefined(String internedName) {
  2664.         return isClassVarDefined(internedName);
  2665.     }
  2666.    
  2667.     /** rb_mod_remove_cvar
  2668.      *
  2669.      * @deprecated - use {@link #removeClassVariable(String)}
  2670.      */
  2671.     @Deprecated
  2672.     public IRubyObject removeCvar(IRubyObject name) {
  2673.         return removeClassVariable(name.asJavaString());
  2674.     }

  2675.     public IRubyObject removeClassVariable(String name) {
  2676.         String javaName = validateClassVariable(name);
  2677.         IRubyObject value;

  2678.         if ((value = deleteClassVariable(javaName)) != null) {
  2679.             return value;
  2680.         }

  2681.         if (isClassVarDefined(javaName)) {
  2682.             throw cannotRemoveError(javaName);
  2683.         }

  2684.         throw getRuntime().newNameError("class variable " + javaName + " not defined for " + getName(), javaName);
  2685.     }


  2686.     //
  2687.     ////////////////// CONSTANT API METHODS ////////////////
  2688.     //

  2689.     /**
  2690.      * This version searches superclasses if we're starting with Object. This
  2691.      * corresponds to logic in rb_const_defined_0 that recurses for Object only.
  2692.      *
  2693.      * @param name the constant name to find
  2694.      * @return the constant, or null if it was not found
  2695.      */
  2696.     public IRubyObject getConstantAtSpecial(String name) {
  2697.         IRubyObject value;
  2698.         if (this == getRuntime().getObject()) {
  2699.             value = getConstantNoConstMissing(name);
  2700.         } else {
  2701.             value = fetchConstant(name);
  2702.         }
  2703.        
  2704.         return value == UNDEF ? resolveUndefConstant(name) : value;
  2705.     }

  2706.     public IRubyObject getConstantAt(String name) {
  2707.         return getConstantAt(name, true);
  2708.     }
  2709.    
  2710.     public IRubyObject getConstantAt(String name, boolean includePrivate) {
  2711.         IRubyObject value = fetchConstant(name, includePrivate);

  2712.         return value == UNDEF ? resolveUndefConstant(name) : value;
  2713.     }

  2714.     @Deprecated
  2715.     public IRubyObject fastGetConstantAt(String internedName) {
  2716.         return getConstantAt(internedName);
  2717.     }

  2718.     /**
  2719.      * Retrieve the named constant, invoking 'const_missing' should that be appropriate.
  2720.      *
  2721.      * @param name The constant to retrieve
  2722.      * @return The value for the constant, or null if not found
  2723.      */
  2724.     public IRubyObject getConstant(String name) {
  2725.         return getConstant(name, true);
  2726.     }

  2727.     public IRubyObject getConstant(String name, boolean inherit) {
  2728.         return getConstant(name, inherit, true);
  2729.     }

  2730.     public IRubyObject getConstant(String name, boolean inherit, boolean includeObject) {
  2731.         IRubyObject value = getConstantNoConstMissing(name, inherit, includeObject);
  2732.         Ruby runtime = getRuntime();

  2733.         return value == null ? callMethod(runtime.getCurrentContext(), "const_missing",
  2734.                 runtime.newSymbol(name)) : value;
  2735.     }

  2736.     @Deprecated
  2737.     public IRubyObject fastGetConstant(String internedName) {
  2738.         return getConstant(internedName);
  2739.     }

  2740.     @Deprecated
  2741.     public IRubyObject fastGetConstant(String internedName, boolean inherit) {
  2742.         return getConstant(internedName, inherit);
  2743.     }

  2744.     public IRubyObject getConstantNoConstMissing(String name) {
  2745.         return getConstantNoConstMissing(name, true);
  2746.     }

  2747.     public IRubyObject getConstantNoConstMissing(String name, boolean inherit) {
  2748.         return getConstantNoConstMissing(name, inherit, true);
  2749.     }

  2750.     public IRubyObject getConstantNoConstMissing(String name, boolean inherit, boolean includeObject) {
  2751.         assert IdUtil.isConstant(name);

  2752.         IRubyObject constant = iterateConstantNoConstMissing(name, this, inherit);

  2753.         if (constant == null && !isClass() && includeObject) {
  2754.             constant = iterateConstantNoConstMissing(name, getRuntime().getObject(), inherit);
  2755.         }

  2756.         return constant;
  2757.     }

  2758.     private IRubyObject iterateConstantNoConstMissing(String name, RubyModule init, boolean inherit) {
  2759.         for (RubyModule p = init; p != null; p = p.getSuperClass()) {
  2760.             IRubyObject value = p.getConstantAt(name);

  2761.             if (value != null) return value == UNDEF ? null : value;
  2762.             if (!inherit) break;
  2763.         }
  2764.         return null;
  2765.     }

  2766.     // not actually called anywhere (all known uses call the fast version)
  2767.     public IRubyObject getConstantFrom(String name) {
  2768.         IRubyObject value = getConstantFromNoConstMissing(name);

  2769.         return value != null ? value : getConstantFromConstMissing(name);
  2770.     }
  2771.    
  2772.     @Deprecated
  2773.     public IRubyObject fastGetConstantFrom(String internedName) {
  2774.         return getConstantFrom(internedName);
  2775.     }

  2776.     public IRubyObject getConstantFromNoConstMissing(String name) {
  2777.         return getConstantFromNoConstMissing(name, true);
  2778.     }

  2779.     public IRubyObject getConstantFromNoConstMissing(String name, boolean includePrivate) {
  2780.         assert name == name.intern() : name + " is not interned";
  2781.         assert IdUtil.isConstant(name);
  2782.         Ruby runtime = getRuntime();
  2783.         RubyClass objectClass = runtime.getObject();
  2784.         IRubyObject value;

  2785.         RubyModule p = this;

  2786.         while (p != null) {
  2787.             if ((value = p.fetchConstant(name, false)) != null) {
  2788.                 if (value == UNDEF) {
  2789.                     return p.resolveUndefConstant(name);
  2790.                 }

  2791.                 if (p == objectClass && this != objectClass) {
  2792.                     String badCName = getName() + "::" + name;
  2793.                     runtime.getWarnings().warn(ID.CONSTANT_BAD_REFERENCE, "toplevel constant " +
  2794.                             name + " referenced by " + badCName);
  2795.                 }

  2796.                 return value;
  2797.             }
  2798.             p = p.getSuperClass();
  2799.         }
  2800.         return null;
  2801.     }
  2802.    
  2803.     @Deprecated
  2804.     public IRubyObject fastGetConstantFromNoConstMissing(String internedName) {
  2805.         return getConstantFromNoConstMissing(internedName);
  2806.     }

  2807.     public IRubyObject getConstantFromConstMissing(String name) {
  2808.         return callMethod(getRuntime().getCurrentContext(),
  2809.                 "const_missing", getRuntime().fastNewSymbol(name));
  2810.     }

  2811.     @Deprecated
  2812.     public IRubyObject fastGetConstantFromConstMissing(String internedName) {
  2813.         return getConstantFromConstMissing(internedName);
  2814.     }

  2815.     public IRubyObject resolveUndefConstant(String name) {
  2816.         return getAutoloadConstant(name);
  2817.     }

  2818.     /**
  2819.      * Set the named constant on this module. Also, if the value provided is another Module and
  2820.      * that module has not yet been named, assign it the specified name. This version does not
  2821.      * warn if the constant has already been set.
  2822.      *
  2823.      * @param name The name to assign
  2824.      * @param value The value to assign to it; if an unnamed Module, also set its basename to name
  2825.      * @return The result of setting the variable.
  2826.      */
  2827.     public IRubyObject setConstantQuiet(String name, IRubyObject value) {
  2828.         return setConstantCommon(name, value, false);
  2829.     }

  2830.     /**
  2831.      * Set the named constant on this module. Also, if the value provided is another Module and
  2832.      * that module has not yet been named, assign it the specified name.
  2833.      *
  2834.      * @param name The name to assign
  2835.      * @param value The value to assign to it; if an unnamed Module, also set its basename to name
  2836.      * @return The result of setting the variable.
  2837.      */
  2838.     public IRubyObject setConstant(String name, IRubyObject value) {
  2839.         return setConstantCommon(name, value, true);
  2840.     }

  2841.     /**
  2842.      * Set the named constant on this module. Also, if the value provided is another Module and
  2843.      * that module has not yet been named, assign it the specified name.
  2844.      *
  2845.      * @param name The name to assign
  2846.      * @param value The value to assign to it; if an unnamed Module, also set its basename to name
  2847.      * @return The result of setting the variable.
  2848.      */
  2849.     private IRubyObject setConstantCommon(String name, IRubyObject value, boolean warn) {
  2850.         IRubyObject oldValue = fetchConstant(name);
  2851.         if (oldValue != null) {
  2852.             if (oldValue == UNDEF) {
  2853.                 setAutoloadConstant(name, value);
  2854.             } else {
  2855.                 if (warn) {
  2856.                     getRuntime().getWarnings().warn(ID.CONSTANT_ALREADY_INITIALIZED, "already initialized constant " + name);
  2857.                 }
  2858.                 storeConstant(name, value);
  2859.             }
  2860.         } else {
  2861.             storeConstant(name, value);
  2862.         }

  2863.         invalidateConstantCache(name);
  2864.        
  2865.         // if adding a module under a constant name, set that module's basename to the constant name
  2866.         if (value instanceof RubyModule) {
  2867.             RubyModule module = (RubyModule)value;
  2868.             if (module != this && module.getBaseName() == null) {
  2869.                 module.setBaseName(name);
  2870.                 module.setParent(this);
  2871.             }
  2872.         }
  2873.         return value;
  2874.     }

  2875.     @Deprecated
  2876.     public IRubyObject fastSetConstant(String internedName, IRubyObject value) {
  2877.         return setConstant(internedName, value);
  2878.     }
  2879.    
  2880.     /** rb_define_const
  2881.      *
  2882.      */
  2883.     @Extension
  2884.     public void defineConstant(String name, IRubyObject value) {
  2885.         assert value != null;

  2886.         if (!IdUtil.isValidConstantName(name)) {
  2887.             throw getRuntime().newNameError("bad constant name " + name, name);
  2888.         }

  2889.         setConstant(name, value);
  2890.     }

  2891.     // Fix for JRUBY-1339 - search hierarchy for constant
  2892.     /** rb_const_defined_at
  2893.      *
  2894.      */
  2895.     public boolean isConstantDefined(String name) {
  2896.         assert IdUtil.isConstant(name);
  2897.         boolean isObject = this == getRuntime().getObject();

  2898.         RubyModule module = this;

  2899.         do {
  2900.             Object value;
  2901.             if ((value = module.constantTableFetch(name)) != null) {
  2902.                 if (value != UNDEF) return true;
  2903.                 return getAutoloadMap().get(name) != null;
  2904.             }

  2905.         } while (isObject && (module = module.getSuperClass()) != null );

  2906.         return false;
  2907.     }

  2908.     public boolean fastIsConstantDefined(String internedName) {
  2909.         assert internedName.equals(internedName.intern()) : internedName + " is not interned";
  2910.         assert IdUtil.isConstant(internedName);
  2911.         boolean isObject = this == getRuntime().getObject();

  2912.         RubyModule module = this;

  2913.         do {
  2914.             Object value;
  2915.             if ((value = module.constantTableFetch(internedName)) != null) {
  2916.                 if (value != UNDEF) return true;
  2917.                 return getAutoloadMap().get(internedName) != null;
  2918.             }

  2919.         } while (isObject && (module = module.getSuperClass()) != null );

  2920.         return false;
  2921.     }

  2922.     public boolean fastIsConstantDefined19(String internedName) {
  2923.         return fastIsConstantDefined19(internedName, true);
  2924.     }

  2925.     public boolean fastIsConstantDefined19(String internedName, boolean inherit) {
  2926.         assert internedName.equals(internedName.intern()) : internedName + " is not interned";
  2927.         assert IdUtil.isConstant(internedName);

  2928.         for (RubyModule module = this; module != null; module = module.getSuperClass()) {
  2929.             Object value;
  2930.             if ((value = module.constantTableFetch(internedName)) != null) {
  2931.                 if (value != UNDEF) return true;
  2932.                 return getAutoloadMap().get(internedName) != null;
  2933.             }
  2934.             if (!inherit) {
  2935.                 break;
  2936.             }
  2937.         }

  2938.         return false;
  2939.     }

  2940.     //
  2941.     ////////////////// COMMON CONSTANT / CVAR METHODS ////////////////
  2942.     //

  2943.     private RaiseException cannotRemoveError(String id) {
  2944.         return getRuntime().newNameError("cannot remove " + id + " for " + getName(), id);
  2945.     }


  2946.     //
  2947.     ////////////////// INTERNAL MODULE VARIABLE API METHODS ////////////////
  2948.     //
  2949.    
  2950.     /**
  2951.      * Behaves similarly to {@link #getClassVar(String)}. Searches this
  2952.      * class/module <em>and its ancestors</em> for the specified internal
  2953.      * variable.
  2954.      *
  2955.      * @param name the internal variable name
  2956.      * @return the value of the specified internal variable if found, else null
  2957.      * @see #setInternalModuleVariable(String, IRubyObject)
  2958.      */
  2959.     public boolean hasInternalModuleVariable(final String name) {
  2960.         for (RubyModule module = this; module != null; module = module.getSuperClass()) {
  2961.             if (module.hasInternalVariable(name)) return true;
  2962.         }

  2963.         return false;
  2964.     }
  2965.     /**
  2966.      * Behaves similarly to {@link #getClassVar(String)}. Searches this
  2967.      * class/module <em>and its ancestors</em> for the specified internal
  2968.      * variable.
  2969.      *
  2970.      * @param name the internal variable name
  2971.      * @return the value of the specified internal variable if found, else null
  2972.      * @see #setInternalModuleVariable(String, IRubyObject)
  2973.      */
  2974.     public IRubyObject searchInternalModuleVariable(final String name) {
  2975.         for (RubyModule module = this; module != null; module = module.getSuperClass()) {
  2976.             IRubyObject value = (IRubyObject)module.getInternalVariable(name);
  2977.             if (value != null) return value;
  2978.         }

  2979.         return null;
  2980.     }

  2981.     /**
  2982.      * Behaves similarly to {@link #setClassVar(String, IRubyObject)}. If the
  2983.      * specified internal variable is found in this class/module <em>or an ancestor</em>,
  2984.      * it is set where found.  Otherwise it is set in this module.
  2985.      *
  2986.      * @param name the internal variable name
  2987.      * @param value the internal variable value
  2988.      * @see #searchInternalModuleVariable(String)
  2989.      */
  2990.     public void setInternalModuleVariable(final String name, final IRubyObject value) {
  2991.         for (RubyModule module = this; module != null; module = module.getSuperClass()) {
  2992.             if (module.hasInternalVariable(name)) {
  2993.                 module.setInternalVariable(name, value);
  2994.                 return;
  2995.             }
  2996.         }

  2997.         setInternalVariable(name, value);
  2998.     }

  2999.     //
  3000.     ////////////////// LOW-LEVEL CLASS VARIABLE INTERFACE ////////////////
  3001.     //
  3002.     // fetch/store/list class variables for this module
  3003.     //

  3004.     protected Map<String, IRubyObject> getClassVariables() {
  3005.         if (CLASSVARS_UPDATER == null) {
  3006.             return getClassVariablesForWriteSynchronized();
  3007.         } else {
  3008.             return getClassVariablesForWriteAtomic();
  3009.         }
  3010.     }

  3011.     /**
  3012.      * Get the class variables for write. If it is not set or not of the right size,
  3013.      * synchronize against the object and prepare it accordingly.
  3014.      *
  3015.      * @return the class vars map, ready for assignment
  3016.      */
  3017.     private Map<String,IRubyObject> getClassVariablesForWriteSynchronized() {
  3018.         Map myClassVars = classVariables;
  3019.         if (myClassVars == Collections.EMPTY_MAP) {
  3020.             synchronized (this) {
  3021.                 myClassVars = classVariables;

  3022.                 if (myClassVars == Collections.EMPTY_MAP) {
  3023.                     return classVariables = new ConcurrentHashMap<String, IRubyObject>(4, 0.75f, 2);
  3024.                 } else {
  3025.                     return myClassVars;
  3026.                 }
  3027.             }
  3028.         }

  3029.         return myClassVars;
  3030.     }


  3031.     /**
  3032.      * Get the class variables for write. If it is not set or not of the right size,
  3033.      * atomically update it with an appropriate value.
  3034.      *
  3035.      * @return the class vars map, ready for assignment
  3036.      */
  3037.     private Map<String,IRubyObject> getClassVariablesForWriteAtomic() {
  3038.         while (true) {
  3039.             Map myClassVars = classVariables;
  3040.             Map newClassVars;

  3041.             if (myClassVars == Collections.EMPTY_MAP) {
  3042.                 newClassVars = new ConcurrentHashMap<String, IRubyObject>(4, 0.75f, 2);
  3043.             } else {
  3044.                 return myClassVars;
  3045.             }

  3046.             // proceed with atomic update of table, or retry
  3047.             if (CLASSVARS_UPDATER.compareAndSet(this, myClassVars, newClassVars)) {
  3048.                 return newClassVars;
  3049.             }
  3050.         }
  3051.     }

  3052.     protected Map<String, IRubyObject> getClassVariablesForRead() {
  3053.         return classVariables;
  3054.     }
  3055.    
  3056.     public boolean hasClassVariable(String name) {
  3057.         assert IdUtil.isClassVariable(name);
  3058.         return getClassVariablesForRead().containsKey(name);
  3059.     }

  3060.     @Deprecated
  3061.     public boolean fastHasClassVariable(String internedName) {
  3062.         return hasClassVariable(internedName);
  3063.     }

  3064.     public IRubyObject fetchClassVariable(String name) {
  3065.         assert IdUtil.isClassVariable(name);
  3066.         return getClassVariablesForRead().get(name);
  3067.     }

  3068.     @Deprecated
  3069.     public IRubyObject fastFetchClassVariable(String internedName) {
  3070.         return fetchClassVariable(internedName);
  3071.     }

  3072.     public IRubyObject storeClassVariable(String name, IRubyObject value) {
  3073.         assert IdUtil.isClassVariable(name) && value != null;
  3074.         ensureClassVariablesSettable();
  3075.         getClassVariables().put(name, value);
  3076.         return value;
  3077.     }

  3078.     @Deprecated
  3079.     public IRubyObject fastStoreClassVariable(String internedName, IRubyObject value) {
  3080.         return storeClassVariable(internedName, value);
  3081.     }

  3082.     public IRubyObject deleteClassVariable(String name) {
  3083.         assert IdUtil.isClassVariable(name);
  3084.         ensureClassVariablesSettable();
  3085.         return getClassVariablesForRead().remove(name);
  3086.     }

  3087.     public List<String> getClassVariableNameList() {
  3088.         return new ArrayList<String>(getClassVariablesForRead().keySet());
  3089.     }

  3090.     protected static final String ERR_INSECURE_SET_CLASS_VAR = "Insecure: can't modify class variable";
  3091.     protected static final String ERR_FROZEN_CVAR_TYPE = "class/module ";
  3092.    
  3093.     protected final String validateClassVariable(String name) {
  3094.         if (IdUtil.isValidClassVariableName(name)) {
  3095.             return name;
  3096.         }
  3097.         throw getRuntime().newNameError("`" + name + "' is not allowed as a class variable name", name);
  3098.     }

  3099.     protected final void ensureClassVariablesSettable() {
  3100.         Ruby runtime = getRuntime();
  3101.        
  3102.         if (!isFrozen()) {
  3103.             return;
  3104.         }

  3105.         if (this instanceof RubyModule) {
  3106.             throw runtime.newFrozenError(ERR_FROZEN_CONST_TYPE);
  3107.         } else {
  3108.             throw runtime.newFrozenError("");
  3109.         }
  3110.     }

  3111.     //
  3112.     ////////////////// LOW-LEVEL CONSTANT INTERFACE ////////////////
  3113.     //
  3114.     // fetch/store/list constants for this module
  3115.     //

  3116.     public boolean hasConstant(String name) {
  3117.         assert IdUtil.isConstant(name);
  3118.         return constantTableContains(name);
  3119.     }

  3120.     @Deprecated
  3121.     public boolean fastHasConstant(String internedName) {
  3122.         return hasConstant(internedName);
  3123.     }

  3124.     // returns the stored value without processing undefs (autoloads)
  3125.     public IRubyObject fetchConstant(String name) {
  3126.         return fetchConstant(name, true);
  3127.     }

  3128.     public IRubyObject fetchConstant(String name, boolean includePrivate) {
  3129.         assert IdUtil.isConstant(name);
  3130.         ConstantEntry entry = constantEntryFetch(name);

  3131.         if (entry == null) return null;

  3132.         if (entry.hidden && !includePrivate) {
  3133.             throw getRuntime().newNameError("private constant " + getName() + "::" + name + " referenced", name);
  3134.         }

  3135.         return entry.value;
  3136.     }

  3137.     @Deprecated
  3138.     public IRubyObject fastFetchConstant(String internedName) {
  3139.         return fetchConstant(internedName);
  3140.     }

  3141.     public IRubyObject storeConstant(String name, IRubyObject value) {
  3142.         assert IdUtil.isConstant(name) : name + " is not a valid constant name";
  3143.         assert value != null : "value is null";
  3144.        
  3145.         ensureConstantsSettable();
  3146.         return constantTableStore(name, value);
  3147.     }

  3148.     @Deprecated
  3149.     public IRubyObject fastStoreConstant(String internedName, IRubyObject value) {
  3150.         return storeConstant(internedName, value);
  3151.     }

  3152.     // removes and returns the stored value without processing undefs (autoloads)
  3153.     public IRubyObject deleteConstant(String name) {
  3154.         assert IdUtil.isConstant(name);
  3155.         ensureConstantsSettable();
  3156.         return constantTableRemove(name);
  3157.     }
  3158.    
  3159.     @Deprecated
  3160.     public List<Variable<IRubyObject>> getStoredConstantList() {
  3161.         return null;
  3162.     }

  3163.     @Deprecated
  3164.     public List<String> getStoredConstantNameList() {
  3165.         return new ArrayList<String>(getConstantMap().keySet());
  3166.     }

  3167.     /**
  3168.      * @return a list of constant names that exists at time this was called
  3169.      */
  3170.     public Collection<String> getConstantNames() {
  3171.         return getConstantMap().keySet();
  3172.     }

  3173.     public Collection<String> getConstantNames(boolean includePrivate) {
  3174.         if (includePrivate) return getConstantNames();

  3175.         if (getConstantMap().size() == 0) {
  3176.             return Collections.EMPTY_SET;
  3177.         }

  3178.         HashSet<String> publicNames = new HashSet<String>(getConstantMap().size());
  3179.        
  3180.         for (Map.Entry<String, ConstantEntry> entry : getConstantMap().entrySet()) {
  3181.             if (entry.getValue().hidden) continue;
  3182.             publicNames.add(entry.getKey());
  3183.         }
  3184.         return publicNames;
  3185.     }
  3186.    
  3187.     protected final String validateConstant(IRubyObject name) {
  3188.         return validateConstant(name.asJavaString(), name);
  3189.     }

  3190.     protected final String validateConstant(String name, IRubyObject errorName) {
  3191.         if (IdUtil.isValidConstantName19(name)) return name;

  3192.         Ruby runtime = getRuntime();

  3193.         Encoding resultEncoding = runtime.getDefaultInternalEncoding();
  3194.         if (resultEncoding == null) resultEncoding = runtime.getDefaultExternalEncoding();

  3195.         // MRI is more complicated than this and distinguishes between ID and non-ID.
  3196.         RubyString nameString = errorName.asString();

  3197.         // MRI does strlen to check for \0 vs Ruby string length.
  3198.         if ((nameString.getEncoding() != resultEncoding && !nameString.isAsciiOnly()) ||
  3199.                 nameString.toString().contains("\0")) {
  3200.             nameString = (RubyString) nameString.inspect();
  3201.         }

  3202.         throw getRuntime().newNameError("wrong constant name " + nameString, name);
  3203.     }

  3204.     protected final void ensureConstantsSettable() {
  3205.         if (isFrozen()) throw getRuntime().newFrozenError(ERR_FROZEN_CONST_TYPE);
  3206.     }

  3207.     protected boolean constantTableContains(String name) {
  3208.         return getConstantMap().containsKey(name);
  3209.     }
  3210.    
  3211.     protected IRubyObject constantTableFetch(String name) {
  3212.         ConstantEntry entry = getConstantMap().get(name);
  3213.         if (entry == null) return null;
  3214.         return entry.value;
  3215.     }

  3216.     protected ConstantEntry constantEntryFetch(String name) {
  3217.         return getConstantMap().get(name);
  3218.     }
  3219.    
  3220.     protected IRubyObject constantTableStore(String name, IRubyObject value) {
  3221.         Map<String, ConstantEntry> constMap = getConstantMapForWrite();
  3222.         boolean hidden = false;

  3223.         ConstantEntry entry = constMap.get(name);
  3224.         if (entry != null) hidden = entry.hidden;

  3225.         constMap.put(name, new ConstantEntry(value, hidden));
  3226.         return value;
  3227.     }
  3228.    
  3229.     protected IRubyObject constantTableRemove(String name) {
  3230.         ConstantEntry entry = getConstantMapForWrite().remove(name);
  3231.         if (entry == null) return null;
  3232.         return entry.value;
  3233.     }
  3234.    
  3235.     /**
  3236.      * Define an autoload. ConstantMap holds UNDEF for the name as an autoload marker.
  3237.      */
  3238.     protected void defineAutoload(String name, IAutoloadMethod loadMethod) {
  3239.         Autoload existingAutoload = getAutoloadMap().get(name);
  3240.         if (existingAutoload == null || existingAutoload.getValue() == null) {
  3241.             storeConstant(name, RubyObject.UNDEF);
  3242.             getAutoloadMapForWrite().put(name, new Autoload(loadMethod));
  3243.         }
  3244.     }
  3245.    
  3246.     /**
  3247.      * Extract an Object which is defined by autoload thread from autoloadMap and define it as a constant.
  3248.      */
  3249.     protected IRubyObject finishAutoload(String name) {
  3250.         Autoload autoload = getAutoloadMap().get(name);
  3251.         if (autoload != null) {
  3252.             IRubyObject value = autoload.getValue();
  3253.             if (value != null) {
  3254.                 storeConstant(name, value);
  3255.             }
  3256.             removeAutoload(name);
  3257.             return value;
  3258.         }
  3259.         return null;
  3260.     }

  3261.     /**
  3262.      * Get autoload constant.
  3263.      * If it's first resolution for the constant, it tries to require the defined feature and returns the defined value.
  3264.      * Multi-threaded accesses are blocked and processed sequentially except if the caller is the autoloading thread.
  3265.      */
  3266.     public IRubyObject getAutoloadConstant(String name) {
  3267.         Autoload autoload = getAutoloadMap().get(name);
  3268.         if (autoload == null) {
  3269.             return null;
  3270.         }
  3271.         return autoload.getConstant(getRuntime().getCurrentContext());
  3272.     }
  3273.    
  3274.     /**
  3275.      * Set an Object as a defined constant in autoloading.
  3276.      */
  3277.     private void setAutoloadConstant(String name, IRubyObject value) {
  3278.         Autoload autoload = getAutoloadMap().get(name);
  3279.         if (autoload != null) {
  3280.             if (!autoload.setConstant(getRuntime().getCurrentContext(), value)) {
  3281.                 storeConstant(name, value);
  3282.                 removeAutoload(name);
  3283.             }
  3284.         } else {
  3285.             storeConstant(name, value);
  3286.         }
  3287.     }
  3288.    
  3289.     /**
  3290.      * Removes an Autoload object from autoloadMap. ConstantMap must be updated before calling this.
  3291.      */
  3292.     private void removeAutoload(String name) {
  3293.         getAutoloadMapForWrite().remove(name);
  3294.     }
  3295.    
  3296.     protected String getAutoloadFile(String name) {
  3297.         Autoload autoload = getAutoloadMap().get(name);
  3298.         if (autoload != null) {
  3299.             return autoload.getFile();
  3300.         }
  3301.         return null;
  3302.     }

  3303.     private static void define(RubyModule module, JavaMethodDescriptor desc, String simpleName, DynamicMethod dynamicMethod) {
  3304.         JRubyMethod jrubyMethod = desc.anno;
  3305.         // check for frame field reads or writes
  3306.         CallConfiguration needs = CallConfiguration.valueOf(AnnotationHelper.getCallerCallConfigNameByAnno(jrubyMethod));

  3307.         if (needs.framing() == Framing.Full) {
  3308.             Set<String> frameAwareMethods = new HashSet<String>();
  3309.             AnnotationHelper.addMethodNamesToSet(frameAwareMethods, jrubyMethod, simpleName);
  3310.             MethodIndex.FRAME_AWARE_METHODS.addAll(frameAwareMethods);
  3311.         }
  3312.         if (needs.scoping() == Scoping.Full) {
  3313.             Set<String> scopeAwareMethods = new HashSet<String>();
  3314.             AnnotationHelper.addMethodNamesToSet(scopeAwareMethods, jrubyMethod, simpleName);
  3315.             MethodIndex.SCOPE_AWARE_METHODS.addAll(scopeAwareMethods);
  3316.         }
  3317.        
  3318.         RubyModule singletonClass;

  3319.         if (jrubyMethod.meta()) {
  3320.             singletonClass = module.getSingletonClass();
  3321.             dynamicMethod.setImplementationClass(singletonClass);

  3322.             String baseName;
  3323.             if (jrubyMethod.name().length == 0) {
  3324.                 baseName = desc.name;
  3325.                 singletonClass.addMethod(baseName, dynamicMethod);
  3326.             } else {
  3327.                 baseName = jrubyMethod.name()[0];
  3328.                 for (String name : jrubyMethod.name()) {
  3329.                     singletonClass.addMethod(name, dynamicMethod);
  3330.                 }
  3331.             }

  3332.             if (jrubyMethod.alias().length > 0) {
  3333.                 for (String alias : jrubyMethod.alias()) {
  3334.                     singletonClass.defineAlias(alias, baseName);
  3335.                 }
  3336.             }
  3337.         } else {
  3338.             String baseName;
  3339.             if (jrubyMethod.name().length == 0) {
  3340.                 baseName = desc.name;
  3341.                 module.getMethodLocation().addMethod(baseName, dynamicMethod);
  3342.             } else {
  3343.                 baseName = jrubyMethod.name()[0];
  3344.                 for (String name : jrubyMethod.name()) {
  3345.                     module.getMethodLocation().addMethod(name, dynamicMethod);
  3346.                 }
  3347.             }

  3348.             if (jrubyMethod.alias().length > 0) {
  3349.                 for (String alias : jrubyMethod.alias()) {
  3350.                     module.defineAlias(alias, baseName);
  3351.                 }
  3352.             }

  3353.             if (jrubyMethod.module()) {
  3354.                 singletonClass = module.getSingletonClass();
  3355.                 // module/singleton methods are all defined public
  3356.                 DynamicMethod moduleMethod = dynamicMethod.dup();
  3357.                 moduleMethod.setVisibility(PUBLIC);

  3358.                 if (jrubyMethod.name().length == 0) {
  3359.                     baseName = desc.name;
  3360.                     singletonClass.addMethod(desc.name, moduleMethod);
  3361.                 } else {
  3362.                     baseName = jrubyMethod.name()[0];
  3363.                     for (String name : jrubyMethod.name()) {
  3364.                         singletonClass.addMethod(name, moduleMethod);
  3365.                     }
  3366.                 }

  3367.                 if (jrubyMethod.alias().length > 0) {
  3368.                     for (String alias : jrubyMethod.alias()) {
  3369.                         singletonClass.defineAlias(alias, baseName);
  3370.                     }
  3371.                 }
  3372.             }
  3373.         }
  3374.     }
  3375.    
  3376.     @Deprecated
  3377.     public IRubyObject initialize(Block block) {
  3378.         return initialize(getRuntime().getCurrentContext());
  3379.     }

  3380.     public KindOf kindOf = KindOf.DEFAULT_KIND_OF;

  3381.     public final int id;

  3382.     /**
  3383.      * The class/module within whose namespace this class/module resides.
  3384.      */
  3385.     public RubyModule parent;

  3386.     /**
  3387.      * The base name of this class/module, excluding nesting. If null, this is
  3388.      * an anonymous class.
  3389.      */
  3390.     protected String baseName;
  3391.    
  3392.     /**
  3393.      * The cached anonymous class name, since it never changes and has a nonzero
  3394.      * cost to calculate.
  3395.      */
  3396.     private String anonymousName;

  3397.     /**
  3398.      * The cached name, only cached once this class and all containing classes are non-anonymous
  3399.      */
  3400.     private String cachedName;

  3401.     private volatile Map<String, ConstantEntry> constants = Collections.EMPTY_MAP;

  3402.     /**
  3403.      * Represents a constant value, possibly hidden (private).
  3404.      */
  3405.     public static class ConstantEntry {
  3406.         public final IRubyObject value;
  3407.         public final boolean hidden;

  3408.         public ConstantEntry(IRubyObject value, boolean hidden) {
  3409.             this.value = value;
  3410.             this.hidden = hidden;
  3411.         }
  3412.        
  3413.         public ConstantEntry dup() {
  3414.             return new ConstantEntry(value, hidden);
  3415.         }
  3416.     }
  3417.    
  3418.     /**
  3419.      * Objects for holding autoload state for the defined constant.
  3420.      *
  3421.      * 'Module#autoload' creates this object and stores it in autoloadMap.
  3422.      * This object can be shared with multiple threads so take care to change volatile and synchronized definitions.
  3423.      */
  3424.     private class Autoload {
  3425.         // A ThreadContext which is executing autoload.
  3426.         private volatile ThreadContext ctx;
  3427.         // The lock for test-and-set the ctx.
  3428.         private final Object ctxLock = new Object();
  3429.         // An object defined for the constant while autoloading.
  3430.         private volatile IRubyObject value;
  3431.         // A method which actually requires a defined feature.
  3432.         private final IAutoloadMethod loadMethod;

  3433.         Autoload(IAutoloadMethod loadMethod) {
  3434.             this.ctx = null;
  3435.             this.value = null;
  3436.             this.loadMethod = loadMethod;
  3437.         }

  3438.         // Returns an object for the constant if the caller is the autoloading thread.
  3439.         // Otherwise, try to start autoloading and returns the defined object by autoload.
  3440.         IRubyObject getConstant(ThreadContext ctx) {
  3441.             synchronized (ctxLock) {
  3442.                 if (this.ctx == null) {
  3443.                     this.ctx = ctx;
  3444.                 } else if (isSelf(ctx)) {
  3445.                     return getValue();
  3446.                 }
  3447.                 // This method needs to be synchronized for removing Autoload
  3448.                 // from autoloadMap when it's loaded.
  3449.                 getLoadMethod().load(ctx.runtime);
  3450.             }
  3451.             return getValue();
  3452.         }
  3453.        
  3454.         // Update an object for the constant if the caller is the autoloading thread.
  3455.         boolean setConstant(ThreadContext ctx, IRubyObject newValue) {
  3456.             synchronized(ctxLock) {
  3457.                 boolean isSelf = isSelf(ctx);
  3458.                
  3459.                 if (isSelf) value = newValue;
  3460.                
  3461.                 return isSelf;
  3462.             }
  3463.         }
  3464.        
  3465.         // Returns an object for the constant defined by autoload.
  3466.         IRubyObject getValue() {
  3467.             return value;
  3468.         }
  3469.        
  3470.         // Returns the assigned feature.
  3471.         String getFile() {
  3472.             return getLoadMethod().file();
  3473.         }

  3474.         private IAutoloadMethod getLoadMethod() {
  3475.             return loadMethod;
  3476.         }

  3477.         private boolean isSelf(ThreadContext rhs) {
  3478.             return ctx != null && ctx.getThread() == rhs.getThread();
  3479.         }
  3480.     }
  3481.    
  3482.     /**
  3483.      * Set whether this class is associated with (i.e. a proxy for) a normal
  3484.      * Java class or interface.
  3485.      */
  3486.     public void setJavaProxy(boolean javaProxy) {
  3487.         this.javaProxy = javaProxy;
  3488.     }
  3489.    
  3490.     /**
  3491.      * Get whether this class is associated with (i.e. a proxy for) a normal
  3492.      * Java class or interface.
  3493.      */
  3494.     public boolean getJavaProxy() {
  3495.         return javaProxy;
  3496.     }

  3497.     /**
  3498.      * Get whether this Java proxy class should try to keep its instances idempotent
  3499.      * and alive using the ObjectProxyCache.
  3500.      */
  3501.     public boolean getCacheProxy() {
  3502.         return getFlag(USER0_F);
  3503.     }

  3504.     /**
  3505.      * Set whether this Java proxy class should try to keep its instances idempotent
  3506.      * and alive using the ObjectProxyCache.
  3507.      */
  3508.     public void setCacheProxy(boolean cacheProxy) {
  3509.         setFlag(USER0_F, cacheProxy);
  3510.     }
  3511.    
  3512.     public Set<String> discoverInstanceVariables() {
  3513.         HashSet<String> set = new HashSet();
  3514.         RubyModule cls = this;
  3515.         while (cls != null) {
  3516.             for (DynamicMethod method : cls.getNonIncludedClass().getMethodLocation().getMethods().values()) {
  3517.                 MethodData methodData = method.getMethodData();
  3518.                 set.addAll(methodData.getIvarNames());
  3519.             }
  3520.            
  3521.             if (cls instanceof RubyClass) {
  3522.                 cls = ((RubyClass)cls).getSuperClass();
  3523.             } else {
  3524.                 break;
  3525.             }
  3526.         }
  3527.         return set;
  3528.     }

  3529.     /**
  3530.      * Return true if the given method is defined on this class and is a builtin
  3531.      * (defined in Java at boot).
  3532.      *
  3533.      * @param methodName
  3534.      * @return
  3535.      */
  3536.     public boolean isMethodBuiltin(String methodName) {
  3537.         DynamicMethod method = searchMethodInner(methodName);

  3538.         return method != null && method.isBuiltin();
  3539.     }
  3540.    
  3541.     private volatile Map<String, Autoload> autoloads = Collections.EMPTY_MAP;
  3542.     protected volatile Map<String, DynamicMethod> methods = Collections.EMPTY_MAP;
  3543.     protected Map<String, CacheEntry> cachedMethods = Collections.EMPTY_MAP;
  3544.     protected int generation;
  3545.     protected Integer generationObject;

  3546.     protected volatile Set<RubyClass> includingHierarchies = Collections.EMPTY_SET;
  3547.     protected volatile RubyModule methodLocation = this;

  3548.     // ClassProviders return Java class/module (in #defineOrGetClassUnder and
  3549.     // #defineOrGetModuleUnder) when class/module is opened using colon syntax.
  3550.     private transient volatile Set<ClassProvider> classProviders = Collections.EMPTY_SET;

  3551.     // superClass may be null.
  3552.     protected RubyClass superClass;

  3553.     /**
  3554.      * The index of this class in the ClassIndex. Only non-zero for native JRuby
  3555.      * classes that have a corresponding entry in ClassIndex.
  3556.      *
  3557.      * @see ClassIndex
  3558.      * @deprecated use RubyModule#getClassIndex()
  3559.      */
  3560.     @Deprecated
  3561.     public int index;

  3562.     @Deprecated
  3563.     public static final Set<String> SCOPE_CAPTURING_METHODS = new HashSet<String>(Arrays.asList(
  3564.             "eval",
  3565.             "module_eval",
  3566.             "class_eval",
  3567.             "instance_eval",
  3568.             "module_exec",
  3569.             "class_exec",
  3570.             "instance_exec",
  3571.             "binding",
  3572.             "local_variables"
  3573.     ));
  3574.    
  3575.     protected ClassIndex classIndex = ClassIndex.NO_INDEX;

  3576.     private volatile Map<String, IRubyObject> classVariables = Collections.EMPTY_MAP;

  3577.     private static final AtomicReferenceFieldUpdater CLASSVARS_UPDATER;

  3578.     static {
  3579.         AtomicReferenceFieldUpdater updater = null;
  3580.         try {
  3581.             updater = AtomicReferenceFieldUpdater.newUpdater(RubyModule.class, Map.class, "classVariables");
  3582.         } catch (RuntimeException re) {
  3583.             if (re.getCause() instanceof AccessControlException) {
  3584.                 // security prevented creation; fall back on synchronized assignment
  3585.             } else {
  3586.                 throw re;
  3587.             }
  3588.         }
  3589.         CLASSVARS_UPDATER = updater;
  3590.     }
  3591.    
  3592.     // Invalidator used for method caches
  3593.     protected final Invalidator methodInvalidator;

  3594.     /** Whether this class proxies a normal Java class */
  3595.     private boolean javaProxy = false;
  3596. }