1 37 package org.jruby; 38 39 import org.jruby.ast.Node; 40 import org.jruby.evaluator.EvaluationState; 41 import org.jruby.exceptions.JumpException; 42 import org.jruby.internal.runtime.methods.DynamicMethod; 43 import org.jruby.lexer.yacc.ISourcePosition; 44 import org.jruby.runtime.Arity; 45 import org.jruby.runtime.Block; 46 import org.jruby.runtime.CallType; 47 import org.jruby.runtime.ThreadContext; 48 import org.jruby.runtime.Visibility; 49 import org.jruby.runtime.builtin.IRubyObject; 50 import org.jruby.runtime.callback.Callback; 51 import org.jruby.util.IdUtil; 52 import org.jruby.util.PrintfFormat; 53 import org.jruby.util.collections.SinglyLinkedList; 54 import java.util.ArrayList ; 55 import java.util.Collections ; 56 import java.util.HashMap ; 57 import java.util.Iterator ; 58 import java.util.Map ; 59 import org.jruby.runtime.ClassIndex; 60 61 65 public class RubyObject implements Cloneable , IRubyObject { 66 67 private RubyClass metaClass; 69 70 protected Map instanceVariables; 72 73 private boolean frozen; 75 private boolean taint; 76 77 public RubyObject(Ruby runtime, RubyClass metaClass) { 78 this(runtime, metaClass, runtime.isObjectSpaceEnabled()); 79 } 80 81 public RubyObject(Ruby runtime, RubyClass metaClass, boolean useObjectSpace) { 82 this.metaClass = metaClass; 83 this.frozen = false; 84 this.taint = false; 85 86 if (useObjectSpace && !isImmediate()) { 88 runtime.getObjectSpace().add(this); 89 } 90 91 taint |= runtime.getSafeLevel() >= 3; 94 } 95 96 public void attachToObjectSpace() { 97 getRuntime().getObjectSpace().add(this); 98 } 99 100 104 public int getNativeTypeIndex() { 105 return ClassIndex.OBJECT; 106 } 107 108 111 public boolean isImmediate() { 112 return false; 113 } 114 115 120 public RubyClass makeMetaClass(RubyClass superClass, SinglyLinkedList parentCRef) { 121 RubyClass klass = new MetaClass(getRuntime(), superClass, getMetaClass().getAllocator(), parentCRef); 122 setMetaClass(klass); 123 124 klass.setInstanceVariable("__attached__", this); 125 126 if (this instanceof RubyClass && isSingleton()) { klass.setMetaClass(klass); 128 klass.setSuperClass(((RubyClass)this).getSuperClass().getRealClass().getMetaClass()); 129 } else { 130 klass.setMetaClass(superClass.getRealClass().getMetaClass()); 131 } 132 133 klass.index = superClass.index; 135 return klass; 136 } 137 138 public boolean isSingleton() { 139 return false; 140 } 141 142 public Class getJavaClass() { 143 return IRubyObject.class; 144 } 145 146 public static void puts(Object obj) { 147 System.out.println(obj.toString()); 148 } 149 150 155 public boolean equals(Object other) { 156 return other == this || other instanceof IRubyObject && callMethod(getRuntime().getCurrentContext(), "==", (IRubyObject) other).isTrue(); 157 } 158 159 public String toString() { 160 return callMethod(getRuntime().getCurrentContext(), "to_s").toString(); 161 } 162 163 166 public Ruby getRuntime() { 167 return metaClass.getRuntime(); 168 } 169 170 public boolean safeHasInstanceVariables() { 171 return instanceVariables != null && instanceVariables.size() > 0; 172 } 173 174 public Map safeGetInstanceVariables() { 175 return instanceVariables == null ? null : getInstanceVariablesSnapshot(); 176 } 177 178 public IRubyObject removeInstanceVariable(String name) { 179 return (IRubyObject) getInstanceVariables().remove(name); 180 } 181 182 186 public Map getInstanceVariablesSnapshot() { 187 synchronized(getInstanceVariables()) { 188 return Collections.unmodifiableMap(new HashMap (getInstanceVariables())); 189 } 190 } 191 192 public Map getInstanceVariables() { 193 if (instanceVariables == null) { 195 synchronized (this) { 196 if (instanceVariables == null) { 197 instanceVariables = Collections.synchronizedMap(new HashMap ()); 198 } 199 } 200 } 201 return instanceVariables; 202 } 203 204 public void setInstanceVariables(Map instanceVariables) { 205 this.instanceVariables = Collections.synchronizedMap(instanceVariables); 206 } 207 208 212 public RubyClass getMetaClass() { 213 return metaClass; 214 } 215 216 public void setMetaClass(RubyClass metaClass) { 217 this.metaClass = metaClass; 218 } 219 220 224 public boolean isFrozen() { 225 return frozen; 226 } 227 228 232 public void setFrozen(boolean frozen) { 233 this.frozen = frozen; 234 } 235 236 239 protected void testFrozen(String message) { 240 if (isFrozen()) { 241 throw getRuntime().newFrozenError(message + getMetaClass().getName()); 242 } 243 } 244 245 protected void checkFrozen() { 246 testFrozen("can't modify frozen "); 247 } 248 249 253 public boolean isTaint() { 254 return taint; 255 } 256 257 261 public void setTaint(boolean taint) { 262 this.taint = taint; 263 } 264 265 public boolean isNil() { 266 return false; 267 } 268 269 public boolean isTrue() { 270 return !isNil(); 271 } 272 273 public boolean isFalse() { 274 return isNil(); 275 } 276 277 public boolean respondsTo(String name) { 278 return getMetaClass().isMethodBound(name, false); 279 } 280 281 283 public int checkArgumentCount(IRubyObject[] args, int min, int max) { 284 if (args.length < min) { 285 throw getRuntime().newArgumentError("wrong number of arguments (" + args.length + " for " + min + ")"); 286 } 287 if (max > -1 && args.length > max) { 288 throw getRuntime().newArgumentError("wrong number of arguments (" + args.length + " for " + max + ")"); 289 } 290 return args.length; 291 } 292 293 public boolean isKindOf(RubyModule type) { 294 return getMetaClass().hasModuleInHierarchy(type); 295 } 296 297 300 public RubyClass getSingletonClass() { 301 RubyClass klass; 302 303 if (getMetaClass().isSingleton() && getMetaClass().getInstanceVariable("__attached__") == this) { 304 klass = getMetaClass(); 305 } else { 306 klass = makeMetaClass(getMetaClass(), getMetaClass().getCRef()); 307 } 308 309 klass.setTaint(isTaint()); 310 klass.setFrozen(isFrozen()); 311 312 return klass; 313 } 314 315 318 public RubyClass getSingletonClassClone() { 319 RubyClass klass = getMetaClass(); 320 321 if (!klass.isSingleton()) { 322 return klass; 323 } 324 325 MetaClass clone = new MetaClass(getRuntime(), klass.getSuperClass(), getMetaClass().getAllocator(), getMetaClass().getCRef()); 326 clone.setFrozen(klass.isFrozen()); 327 clone.setTaint(klass.isTaint()); 328 329 if (this instanceof RubyClass) { 330 clone.setMetaClass(clone); 331 } else { 332 clone.setMetaClass(klass.getSingletonClassClone()); 333 } 334 335 if (klass.safeHasInstanceVariables()) { 336 clone.setInstanceVariables(new HashMap (klass.getInstanceVariables())); 337 } 338 339 klass.cloneMethods(clone); 340 341 clone.getMetaClass().setInstanceVariable("__attached__", clone); 342 343 return clone; 344 } 345 346 349 public void defineSingletonMethod(String name, Callback method) { 350 getSingletonClass().defineMethod(name, method); 351 } 352 353 356 public void initCopy(IRubyObject original) { 357 assert original != null; 358 assert !isFrozen() : "frozen object (" + getMetaClass().getName() + ") allocated"; 359 360 setInstanceVariables(new HashMap (original.getInstanceVariables())); 361 362 callMethod(getRuntime().getCurrentContext(), "initialize_copy", original); 363 } 364 365 368 public IRubyObject infectBy(IRubyObject obj) { 369 setTaint(isTaint() || obj.isTaint()); 370 371 return this; 372 } 373 374 377 public IRubyObject callMethod(ThreadContext context, String name, IRubyObject[] args) { 378 return callMethod(context, getMetaClass(), name, args, CallType.FUNCTIONAL, Block.NULL_BLOCK); 379 } 380 381 public IRubyObject callMethod(ThreadContext context, String name, IRubyObject[] args, Block block) { 382 return callMethod(context, getMetaClass(), name, args, CallType.FUNCTIONAL, block); 383 } 384 385 388 public IRubyObject callMethod(ThreadContext context, String name, 389 IRubyObject[] args, CallType callType) { 390 return callMethod(context, getMetaClass(), name, args, callType, Block.NULL_BLOCK); 391 } 392 393 public IRubyObject callMethod(ThreadContext context, String name, 394 IRubyObject[] args, CallType callType, Block block) { 395 return callMethod(context, getMetaClass(), name, args, callType, block); 396 } 397 398 public IRubyObject callMethod(ThreadContext context, byte methodIndex, String name, 399 IRubyObject arg) { 400 return callMethod(context,methodIndex,name,new IRubyObject[]{arg},CallType.FUNCTIONAL, Block.NULL_BLOCK); 401 } 402 403 public IRubyObject callMethod(ThreadContext context, byte methodIndex, String name, 404 IRubyObject[] args) { 405 return callMethod(context,methodIndex,name,args,CallType.FUNCTIONAL, Block.NULL_BLOCK); 406 } 407 408 public IRubyObject callMethod(ThreadContext context, byte methodIndex, String name, 409 IRubyObject[] args, CallType callType) { 410 return callMethod(context,methodIndex,name,args,callType, Block.NULL_BLOCK); 411 } 412 415 public IRubyObject callMethod(ThreadContext context, byte methodIndex, String name, 416 IRubyObject[] args, CallType callType, Block block) { 417 RubyModule module = getMetaClass(); 418 419 if (module.index != 0) { 420 return callMethod(context, module, getRuntime().getSelectorTable().table[module.index][methodIndex], name, args, callType, block); 421 } 422 423 return callMethod(context, module, name, args, callType, block); 424 } 425 426 429 public IRubyObject callMethod(ThreadContext context, RubyModule rubyclass, byte switchvalue, String name, 430 IRubyObject[] args, CallType callType) { 431 return callMethod(context, rubyclass, name, args, callType, Block.NULL_BLOCK); 432 } 433 434 437 public IRubyObject callMethod(ThreadContext context, RubyModule rubyclass, byte switchvalue, String name, 438 IRubyObject[] args, CallType callType, Block block) { 439 return callMethod(context, rubyclass, name, args, callType, block); 440 } 441 442 445 public IRubyObject callMethod(ThreadContext context, RubyModule rubyclass, String name, 446 IRubyObject[] args, CallType callType, Block block) { 447 assert args != null; 448 DynamicMethod method = null; 449 method = rubyclass.searchMethod(name); 450 if (method.isUndefined() || 451 !(name.equals("method_missing") || 452 method.isCallableFrom(context.getFrameSelf(), callType))) { 453 454 if (callType == CallType.SUPER) { 455 throw getRuntime().newNameError("super: no superclass method '" + name + "'", name); 456 } 457 458 context.setLastCallStatus(method.getVisibility(), callType); 460 461 if (name.equals("method_missing")) { 462 return RubyKernel.method_missing(this, args, block); 463 } 464 465 466 IRubyObject[] newArgs = new IRubyObject[args.length + 1]; 467 System.arraycopy(args, 0, newArgs, 1, args.length); 468 newArgs[0] = RubySymbol.newSymbol(getRuntime(), name); 469 470 return callMethod(context, "method_missing", newArgs, block); 471 } 472 473 RubyModule implementer = null; 474 if (method.needsImplementer()) { 475 implementer = rubyclass.findImplementer(method.getImplementationClass()); 477 } else { 478 implementer = method.getImplementationClass(); 480 } 481 482 String originalName = method.getOriginalName(); 483 if (originalName != null) { 484 name = originalName; 485 } 486 487 return method.call(context, this, implementer, name, args, false, block); 488 } 489 490 public IRubyObject callMethod(ThreadContext context, String name) { 491 return callMethod(context, name, IRubyObject.NULL_ARRAY, null, Block.NULL_BLOCK); 492 } 493 494 public IRubyObject callMethod(ThreadContext context, String name, Block block) { 495 return callMethod(context, name, IRubyObject.NULL_ARRAY, null, block); 496 } 497 498 502 public IRubyObject callMethod(ThreadContext context, String name, IRubyObject arg) { 503 return callMethod(context, name, new IRubyObject[] { arg }); 504 } 505 506 public IRubyObject instance_variable_get(IRubyObject var) { 507 String varName = var.asSymbol(); 508 509 if (!IdUtil.isInstanceVariable(varName)) { 510 throw getRuntime().newNameError("`" + varName + "' is not allowable as an instance variable name", varName); 511 } 512 513 IRubyObject variable = getInstanceVariable(varName); 514 515 return variable == null ? getRuntime().getNil() : variable; 517 } 518 519 public IRubyObject getInstanceVariable(String name) { 520 return (IRubyObject) getInstanceVariables().get(name); 521 } 522 523 public IRubyObject instance_variable_set(IRubyObject var, IRubyObject value) { 524 String varName = var.asSymbol(); 525 526 if (!IdUtil.isInstanceVariable(varName)) { 527 throw getRuntime().newNameError("`" + varName + "' is not allowable as an instance variable name", varName); 528 } 529 530 return setInstanceVariable(var.asSymbol(), value); 531 } 532 533 public IRubyObject setInstanceVariable(String name, IRubyObject value, 534 String taintError, String freezeError) { 535 if (isTaint() && getRuntime().getSafeLevel() >= 4) { 536 throw getRuntime().newSecurityError(taintError); 537 } 538 testFrozen(freezeError); 539 540 getInstanceVariables().put(name, value); 541 542 return value; 543 } 544 545 548 public IRubyObject setInstanceVariable(String name, IRubyObject value) { 549 return setInstanceVariable(name, value, 550 "Insecure: can't modify instance variable", ""); 551 } 552 553 public Iterator instanceVariableNames() { 554 return getInstanceVariables().keySet().iterator(); 555 } 556 557 560 public IRubyObject eval(Node n) { 561 return EvaluationState.eval(getRuntime(), getRuntime().getCurrentContext(), n, this, Block.NULL_BLOCK); 564 } 565 566 public void callInit(IRubyObject[] args, Block block) { 567 callMethod(getRuntime().getCurrentContext(), "initialize", args, block); 568 } 569 570 public void extendObject(RubyModule module) { 571 getSingletonClass().includeModule(module); 572 } 573 574 577 public String asSymbol() { 578 throw getRuntime().newTypeError(inspect().toString() + " is not a symbol"); 579 } 580 581 584 public IRubyObject convertToTypeWithCheck(String targetType, String convertMethod) { 585 if (targetType.equals(getMetaClass().getName())) { 586 return this; 587 } 588 589 IRubyObject value = convertToType(targetType, convertMethod, false); 590 if (value.isNil()) { 591 return value; 592 } 593 594 if (!targetType.equals(value.getMetaClass().getName())) { 595 throw getRuntime().newTypeError(value.getMetaClass().getName() + "#" + convertMethod + 596 "should return " + targetType); 597 } 598 599 return value; 600 } 601 602 605 public IRubyObject convertToType(String targetType, String convertMethod, boolean raise) { 606 if (targetType.equals(getMetaClass().getName())) { 609 return this; 610 } 611 612 if (!respondsTo(convertMethod)) { 613 if (raise) { 614 throw getRuntime().newTypeError( 615 "can't convert " + trueFalseNil(getMetaClass().getName()) + " into " + trueFalseNil(targetType)); 616 } 617 618 return getRuntime().getNil(); 619 } 620 return callMethod(getRuntime().getCurrentContext(), convertMethod); 621 } 622 623 public static String trueFalseNil(IRubyObject v) { 624 return trueFalseNil(v.getMetaClass().getName()); 625 } 626 627 public static String trueFalseNil(String v) { 628 if("TrueClass".equals(v)) { 629 return "true"; 630 } else if("FalseClass".equals(v)) { 631 return "false"; 632 } else if("NilClass".equals(v)) { 633 return "nil"; 634 } 635 return v; 636 } 637 638 public RubyArray convertToArray() { 639 return (RubyArray) convertToType("Array", "to_ary", true); 640 } 641 642 public RubyFloat convertToFloat() { 643 return (RubyFloat) convertToType("Float", "to_f", true); 644 } 645 646 public RubyInteger convertToInteger() { 647 return (RubyInteger) convertToType("Integer", "to_int", true); 648 } 649 650 public RubyString convertToString() { 651 return (RubyString) convertToType("String", "to_str", true); 652 } 653 654 656 public RubyString objAsString() { 657 if (this instanceof RubyString) return (RubyString) this; 658 659 IRubyObject str = this.callMethod(getRuntime().getCurrentContext(), "to_s"); 660 661 if (!(str instanceof RubyString)) str = anyToString(); 662 663 return (RubyString) str; 664 } 665 666 669 public IRubyObject convertType(Class type, String targetType, String convertMethod) { 670 if (type.isAssignableFrom(getClass())) { 671 return this; 672 } 673 674 IRubyObject result = convertToType(targetType, convertMethod, true); 675 676 if (!type.isAssignableFrom(result.getClass())) { 677 throw getRuntime().newTypeError( 678 getMetaClass().getName() + "#" + convertMethod + " should return " + targetType + "."); 679 } 680 681 return result; 682 } 683 684 687 public IRubyObject checkStringType() { 688 IRubyObject str = convertToTypeWithCheck("String","to_str"); 689 if(!str.isNil() && !(str instanceof RubyString)) { 690 str = getRuntime().newString(""); 691 } 692 return str; 693 } 694 695 698 public IRubyObject checkArrayType() { 699 return convertToTypeWithCheck("Array","to_ary"); 700 } 701 702 public void checkSafeString() { 703 if (getRuntime().getSafeLevel() > 0 && isTaint()) { 704 ThreadContext tc = getRuntime().getCurrentContext(); 705 if (tc.getFrameName() != null) { 706 throw getRuntime().newSecurityError("Insecure operation - " + tc.getFrameName()); 707 } 708 throw getRuntime().newSecurityError("Insecure operation: -r"); 709 } 710 getRuntime().secure(4); 711 if (!(this instanceof RubyString)) { 712 throw getRuntime().newTypeError( 713 "wrong argument type " + getMetaClass().getName() + " (expected String)"); 714 } 715 } 716 717 720 public IRubyObject specificEval(RubyModule mod, IRubyObject[] args, Block block) { 721 if (block.isGiven()) { 722 if (args.length > 0) throw getRuntime().newArgumentError(args.length, 0); 723 724 return yieldUnder(mod, block); 725 } 726 ThreadContext tc = getRuntime().getCurrentContext(); 727 728 if (args.length == 0) { 729 throw getRuntime().newArgumentError("block not supplied"); 730 } else if (args.length > 3) { 731 String lastFuncName = tc.getFrameName(); 732 throw getRuntime().newArgumentError( 733 "wrong # of arguments: " + lastFuncName + "(src) or " + lastFuncName + "{..}"); 734 } 735 742 743 args[0].convertToString(); 745 746 IRubyObject file = args.length > 1 ? args[1] : getRuntime().newString("(eval)"); 747 IRubyObject line = args.length > 2 ? args[2] : RubyFixnum.one(getRuntime()); 748 749 Visibility savedVisibility = tc.getCurrentVisibility(); 750 tc.setCurrentVisibility(Visibility.PUBLIC); 751 try { 752 return evalUnder(mod, args[0], file, line); 753 } finally { 754 tc.setCurrentVisibility(savedVisibility); 755 } 756 } 757 758 public IRubyObject evalUnder(RubyModule under, IRubyObject src, IRubyObject file, IRubyObject line) { 759 766 return under.executeUnder(new Callback() { 767 public IRubyObject execute(IRubyObject self, IRubyObject[] args, Block block) { 768 IRubyObject source = args[1]; 769 IRubyObject filename = args[2]; 770 773 return args[0].evalSimple(source.getRuntime().getCurrentContext(), 774 source, ((RubyString) filename).toString()); 775 } 776 777 public Arity getArity() { 778 return Arity.optional(); 779 } 780 }, new IRubyObject[] { this, src, file, line }, Block.NULL_BLOCK); 781 } 782 783 private IRubyObject yieldUnder(RubyModule under, Block block) { 784 return under.executeUnder(new Callback() { 785 public IRubyObject execute(IRubyObject self, IRubyObject[] args, Block block) { 786 ThreadContext context = getRuntime().getCurrentContext(); 787 788 Visibility savedVisibility = block.getVisibility(); 789 790 block.setVisibility(Visibility.PUBLIC); 791 try { 792 IRubyObject valueInYield = args[0]; 793 IRubyObject selfInYield = args[0]; 794 return block.yield(context, valueInYield, selfInYield, context.getRubyClass(), false); 795 } catch (JumpException je) { 797 if (je.getJumpType() == JumpException.JumpType.BreakJump) { 798 return (IRubyObject) je.getValue(); 799 } 800 801 throw je; 802 } finally { 803 block.setVisibility(savedVisibility); 804 } 805 } 806 807 public Arity getArity() { 808 return Arity.optional(); 809 } 810 }, new IRubyObject[] { this }, block); 811 } 812 813 816 public IRubyObject evalWithBinding(ThreadContext context, IRubyObject src, IRubyObject scope, String file) { 817 assert !scope.isNil(); 819 assert file != null; 820 821 ThreadContext threadContext = getRuntime().getCurrentContext(); 822 823 ISourcePosition savedPosition = threadContext.getPosition(); 824 IRubyObject result = getRuntime().getNil(); 825 826 IRubyObject newSelf = null; 827 828 if (!(scope instanceof RubyBinding)) { 829 if (scope instanceof RubyProc) { 830 scope = ((RubyProc) scope).binding(); 831 } else { 832 throw getRuntime().newTypeError("wrong argument type " + scope.getMetaClass() + " (expected Proc/Binding)"); 834 } 835 } 836 837 Block blockOfBinding = ((RubyBinding)scope).getBlock(); 838 try { 839 threadContext.preEvalWithBinding(blockOfBinding); 841 newSelf = threadContext.getFrameSelf(); 842 843 result = EvaluationState.eval(getRuntime(), threadContext, getRuntime().parse(src.toString(), file, blockOfBinding.getDynamicScope()), newSelf, blockOfBinding); 844 } catch (JumpException je) { 845 if (je.getJumpType() == JumpException.JumpType.ReturnJump) { 846 throw getRuntime().newLocalJumpError("unexpected return"); 847 } else if (je.getJumpType() == JumpException.JumpType.BreakJump) { 848 throw getRuntime().newLocalJumpError("unexpected break"); 849 } 850 throw je; 851 } finally { 852 threadContext.postEvalWithBinding(); 853 854 threadContext.setPosition(savedPosition); 856 } 857 return result; 858 } 859 860 863 public IRubyObject evalSimple(ThreadContext context, IRubyObject src, String file) { 864 assert file != null; 866 867 ISourcePosition savedPosition = context.getPosition(); 868 869 try { 871 return EvaluationState.eval(getRuntime(), context, getRuntime().parse(src.toString(), file, context.getCurrentScope()), this, Block.NULL_BLOCK); 872 } catch (JumpException je) { 873 if (je.getJumpType() == JumpException.JumpType.ReturnJump) { 874 throw getRuntime().newLocalJumpError("unexpected return"); 875 } else if (je.getJumpType() == JumpException.JumpType.BreakJump) { 876 throw getRuntime().newLocalJumpError("unexpected break"); 877 } 878 throw je; 879 } finally { 880 context.setPosition(savedPosition); 882 } 883 } 884 885 887 890 public IRubyObject obj_equal(IRubyObject obj) { 891 return this == obj ? getRuntime().getTrue() : getRuntime().getFalse(); 892 } 897 898 public IRubyObject same(IRubyObject other) { 899 return this == other ? getRuntime().getTrue() : getRuntime().getFalse(); 900 } 901 902 903 906 public IRubyObject initialize_copy(IRubyObject original) { 907 if (this == original) return this; 908 909 checkFrozen(); 910 911 if (getMetaClass().getRealClass() != original.getMetaClass().getRealClass()) { 912 throw getRuntime().newTypeError("initialize_copy should take same class object"); 913 } 914 915 return this; 916 } 917 918 927 public RubyBoolean respond_to(IRubyObject[] args) { 928 checkArgumentCount(args, 1, 2); 929 930 String name = args[0].asSymbol(); 931 boolean includePrivate = args.length > 1 ? args[1].isTrue() : false; 932 933 return getRuntime().newBoolean(getMetaClass().isMethodBound(name, !includePrivate)); 934 } 935 936 941 public synchronized RubyFixnum id() { 942 return getRuntime().newFixnum(getRuntime().getObjectSpace().idOf(this)); 943 } 944 945 public synchronized RubyFixnum id_deprecated() { 946 getRuntime().getWarnings().warn("Object#id will be deprecated; use Object#object_id"); 947 return getRuntime().newFixnum(getRuntime().getObjectSpace().idOf(this)); 948 } 949 950 public RubyFixnum hash() { 951 return getRuntime().newFixnum(System.identityHashCode(this)); 952 } 953 954 public int hashCode() { 955 IRubyObject hashValue = callMethod(getRuntime().getCurrentContext(), "hash"); 956 957 if (hashValue instanceof RubyFixnum) return (int) RubyNumeric.fix2long(hashValue); 958 959 return System.identityHashCode(this); 960 } 961 962 965 public RubyClass type() { 966 return getMetaClass().getRealClass(); 967 } 968 969 public RubyClass type_deprecated() { 970 getRuntime().getWarnings().warn("Object#type is deprecated; use Object#class"); 971 return type(); 972 } 973 974 977 public IRubyObject rbClone() { 978 if (isImmediate()) { throw getRuntime().newTypeError("can't clone " + getMetaClass().getName()); 980 } 981 982 IRubyObject clone = doClone(); 983 clone.setMetaClass(getSingletonClassClone()); 984 clone.setTaint(isTaint()); 985 clone.initCopy(this); 986 clone.setFrozen(isFrozen()); 987 return clone; 988 } 989 990 protected IRubyObject doClone() { 993 RubyClass realClass = getMetaClass().getRealClass(); 994 return realClass.getAllocator().allocate(getRuntime(), realClass); 995 } 996 997 public IRubyObject display(IRubyObject[] args) { 998 IRubyObject port = args.length == 0 999 ? getRuntime().getGlobalVariables().get("$>") : args[0]; 1000 1001 port.callMethod(getRuntime().getCurrentContext(), "write", this); 1002 1003 return getRuntime().getNil(); 1004 } 1005 1006 1009 public IRubyObject dup() { 1010 if (isImmediate()) { 1011 throw getRuntime().newTypeError("can't dup " + getMetaClass().getName()); 1012 } 1013 1014 IRubyObject dup = doClone(); 1015 1016 dup.setMetaClass(type()); 1017 dup.setFrozen(false); 1018 dup.setTaint(isTaint()); 1019 1020 dup.initCopy(this); 1021 1022 return dup; 1023 } 1024 1025 1028 public RubyBoolean tainted() { 1029 return getRuntime().newBoolean(isTaint()); 1030 } 1031 1032 1035 public IRubyObject taint() { 1036 getRuntime().secure(4); 1037 if (!isTaint()) { 1038 testFrozen("object"); 1039 setTaint(true); 1040 } 1041 return this; 1042 } 1043 1044 1047 public IRubyObject untaint() { 1048 getRuntime().secure(3); 1049 if (isTaint()) { 1050 testFrozen("object"); 1051 setTaint(false); 1052 } 1053 return this; 1054 } 1055 1056 1061 public IRubyObject freeze() { 1062 if (getRuntime().getSafeLevel() >= 4 && isTaint()) { 1063 throw getRuntime().newSecurityError("Insecure: can't freeze object"); 1064 } 1065 setFrozen(true); 1066 return this; 1067 } 1068 1069 1072 public RubyBoolean frozen() { 1073 return getRuntime().newBoolean(isFrozen()); 1074 } 1075 1076 1079 public IRubyObject inspect() { 1080 if ((!isImmediate()) && 1081 !(this instanceof RubyClass) && 1083 this != getRuntime().getObject() && 1084 this != getRuntime().getClass("Module") && 1085 !(this instanceof RubyModule) && 1086 safeHasInstanceVariables()) { 1087 1088 StringBuffer part = new StringBuffer (); 1089 String cname = getMetaClass().getRealClass().getName(); 1090 part.append("#<").append(cname).append(":0x"); 1091 part.append(Integer.toHexString(System.identityHashCode(this))); 1092 if(!getRuntime().registerInspecting(this)) { 1093 1094 part.append(" ...>"); 1095 return getRuntime().newString(part.toString()); 1096 } 1097 try { 1098 String sep = ""; 1099 Map iVars = getInstanceVariablesSnapshot(); 1100 for (Iterator iter = iVars.keySet().iterator(); iter.hasNext();) { 1101 String name = (String ) iter.next(); 1102 if(IdUtil.isInstanceVariable(name)) { 1103 part.append(sep); 1104 part.append(" "); 1105 part.append(name); 1106 part.append("="); 1107 part.append(((IRubyObject)(iVars.get(name))).callMethod(getRuntime().getCurrentContext(), "inspect")); 1108 sep = ","; 1109 } 1110 } 1111 part.append(">"); 1112 return getRuntime().newString(part.toString()); 1113 } finally { 1114 getRuntime().unregisterInspecting(this); 1115 } 1116 } 1117 return callMethod(getRuntime().getCurrentContext(), "to_s"); 1118 } 1119 1120 1123 public RubyBoolean instance_of(IRubyObject type) { 1124 return getRuntime().newBoolean(type() == type); 1125 } 1126 1127 1128 public RubyArray instance_variables() { 1129 ArrayList names = new ArrayList (); 1130 for(Iterator iter = getInstanceVariablesSnapshot().keySet().iterator();iter.hasNext();) { 1131 String name = (String ) iter.next(); 1132 1133 if (IdUtil.isInstanceVariable(name)) { 1135 names.add(getRuntime().newString(name)); 1136 } 1137 } 1138 return getRuntime().newArray(names); 1139 } 1140 1141 1144 public RubyBoolean kind_of(IRubyObject type) { 1145 if (!type.isKindOf(getRuntime().getClass("Module"))) { 1147 throw getRuntime().newTypeError(type, getRuntime().getClass("Module")); 1149 } 1150 1151 return getRuntime().newBoolean(isKindOf((RubyModule)type)); 1152 } 1153 1154 1157 public IRubyObject methods(IRubyObject[] args) { 1158 checkArgumentCount(args, 0, 1); 1159 1160 if (args.length == 0) { 1161 args = new IRubyObject[] { getRuntime().getTrue() }; 1162 } 1163 1164 return getMetaClass().instance_methods(args); 1165 } 1166 1167 public IRubyObject public_methods(IRubyObject[] args) { 1168 return getMetaClass().public_instance_methods(args); 1169 } 1170 1171 1174 public IRubyObject protected_methods() { 1175 return getMetaClass().protected_instance_methods(new IRubyObject[] { getRuntime().getTrue()}); 1176 } 1177 1178 1181 public IRubyObject private_methods() { 1182 return getMetaClass().private_instance_methods(new IRubyObject[] { getRuntime().getTrue()}); 1183 } 1184 1185 1188 public RubyArray singleton_methods(IRubyObject[] args) { 1190 boolean all = true; 1191 if(checkArgumentCount(args,0,1) == 1) { 1192 all = args[0].isTrue(); 1193 } 1194 1195 RubyArray result = getRuntime().newArray(); 1196 1197 for (RubyClass type = getMetaClass(); type != null && ((type instanceof MetaClass) || (all && type.isIncluded())); 1198 type = type.getSuperClass()) { 1199 for (Iterator iter = type.getMethods().entrySet().iterator(); iter.hasNext(); ) { 1200 Map.Entry entry = (Map.Entry ) iter.next(); 1201 DynamicMethod method = (DynamicMethod) entry.getValue(); 1202 1203 if (method.getImplementationClass() != type && !(all && type.isIncluded())) { 1205 continue; 1206 } 1207 1208 RubyString methodName = getRuntime().newString((String ) entry.getKey()); 1209 if (method.getVisibility().isPublic() && ! result.includes(methodName)) { 1210 result.append(methodName); 1211 } 1212 } 1213 } 1214 1215 return result; 1216 } 1217 1218 public IRubyObject method(IRubyObject symbol) { 1219 return getMetaClass().newMethod(this, symbol.asSymbol(), true); 1220 } 1221 1222 public IRubyObject anyToString() { 1223 String cname = getMetaClass().getRealClass().getName(); 1224 1225 RubyString str = getRuntime().newString("#<" + cname + ":0x" + Integer.toHexString(System.identityHashCode(this)) + ">"); 1226 str.setTaint(isTaint()); 1227 return str; 1228 } 1229 1230 public IRubyObject to_s() { 1231 return anyToString(); 1232 } 1233 1234 public IRubyObject instance_eval(IRubyObject[] args, Block block) { 1235 return specificEval(getSingletonClass(), args, block); 1236 } 1237 1238 public IRubyObject extend(IRubyObject[] args) { 1239 checkArgumentCount(args, 1, -1); 1240 1241 RubyClass module = getRuntime().getClass("Module"); 1243 for (int i = 0; i < args.length; i++) { 1244 if (!args[i].isKindOf(module)) { 1245 throw getRuntime().newTypeError(args[i], module); 1246 } 1247 } 1248 1249 for (int i = 0; i < args.length; i++) { 1250 args[i].callMethod(getRuntime().getCurrentContext(), "extend_object", this); 1251 args[i].callMethod(getRuntime().getCurrentContext(), "extended", this); 1252 } 1253 return this; 1254 } 1255 1256 public IRubyObject inherited(IRubyObject arg, Block block) { 1257 return getRuntime().getNil(); 1258 } 1259 public IRubyObject initialize(IRubyObject[] args, Block block) { 1260 return getRuntime().getNil(); 1261 } 1262 1263 public IRubyObject method_missing(IRubyObject[] args, Block block) { 1264 if (args.length == 0) { 1265 throw getRuntime().newArgumentError("no id given"); 1266 } 1267 1268 String name = args[0].asSymbol(); 1269 String description = null; 1270 if("inspect".equals(name) || "to_s".equals(name)) { 1271 description = anyToString().toString(); 1272 } else { 1273 description = inspect().toString(); 1274 } 1275 boolean noClass = description.length() > 0 && description.charAt(0) == '#'; 1276 ThreadContext tc = getRuntime().getCurrentContext(); 1277 Visibility lastVis = tc.getLastVisibility(); 1278 if(null == lastVis) { 1279 lastVis = Visibility.PUBLIC; 1280 } 1281 CallType lastCallType = tc.getLastCallType(); 1282 String format = lastVis.errorMessageFormat(lastCallType, name); 1283 String msg = new PrintfFormat(format).sprintf(new Object [] { name, description, 1284 noClass ? "" : ":", noClass ? "" : getType().getName()}, null); 1285 1286 if (lastCallType == CallType.VARIABLE) { 1287 throw getRuntime().newNameError(msg, name); 1288 } 1289 throw getRuntime().newNoMethodError(msg, name); 1290 } 1291 1292 1312 public IRubyObject send(IRubyObject[] args, Block block) { 1313 if (args.length < 1) { 1314 throw getRuntime().newArgumentError("no method name given"); 1315 } 1316 String name = args[0].asSymbol(); 1317 1318 IRubyObject[] newArgs = new IRubyObject[args.length - 1]; 1319 System.arraycopy(args, 1, newArgs, 0, newArgs.length); 1320 1321 return callMethod(getRuntime().getCurrentContext(), name, newArgs, CallType.FUNCTIONAL, block); 1322 } 1323 1324 public IRubyObject nil_p() { 1325 return getRuntime().getFalse(); 1326 } 1327 1328 public IRubyObject match(IRubyObject arg) { 1329 return getRuntime().getFalse(); 1330 } 1331 1332 public IRubyObject remove_instance_variable(IRubyObject name, Block block) { 1333 String id = name.asSymbol(); 1334 1335 if (!IdUtil.isInstanceVariable(id)) { 1336 throw getRuntime().newNameError("wrong instance variable name " + id, id); 1337 } 1338 if (!isTaint() && getRuntime().getSafeLevel() >= 4) { 1339 throw getRuntime().newSecurityError("Insecure: can't remove instance variable"); 1340 } 1341 testFrozen("class/module"); 1342 1343 IRubyObject variable = removeInstanceVariable(id); 1344 if (variable != null) { 1345 return variable; 1346 } 1347 1348 throw getRuntime().newNameError("instance variable " + id + " not defined", id); 1349 } 1350 1351 1354 public RubyClass getType() { 1355 return type(); 1356 } 1357 1358 1361 public IRubyObject[] scanArgs(IRubyObject[] args, int required, int optional) { 1362 int total = required+optional; 1363 int real = checkArgumentCount(args,required,total); 1364 IRubyObject[] narr = new IRubyObject[total]; 1365 System.arraycopy(args,0,narr,0,real); 1366 for(int i=real; i<total; i++) { 1367 narr[i] = getRuntime().getNil(); 1368 } 1369 return narr; 1370 } 1371 1372 private transient Object dataStruct; 1373 1374 1377 public synchronized void dataWrapStruct(Object obj) { 1378 this.dataStruct = obj; 1379 } 1380 1381 1384 public synchronized Object dataGetStruct() { 1385 return dataStruct; 1386 } 1387 1388 1391 public IRubyObject equal(IRubyObject other) { 1392 if(this == other || callMethod(getRuntime().getCurrentContext(), "==",other).isTrue()){ 1393 return getRuntime().getTrue(); 1394 } 1395 1396 return getRuntime().getFalse(); 1397 } 1398 1399 public final IRubyObject equalInternal(final ThreadContext context, final IRubyObject other){ 1400 if (this == other) return getRuntime().getTrue(); 1401 return callMethod(context, "==", other); 1402 } 1403} 1404 | Popular Tags |