0001: /***** BEGIN LICENSE BLOCK *****
0002: * Version: CPL 1.0/GPL 2.0/LGPL 2.1
0003: *
0004: * The contents of this file are subject to the Common Public
0005: * License Version 1.0 (the "License"); you may not use this file
0006: * except in compliance with the License. You may obtain a copy of
0007: * the License at http://www.eclipse.org/legal/cpl-v10.html
0008: *
0009: * Software distributed under the License is distributed on an "AS
0010: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
0011: * implied. See the License for the specific language governing
0012: * rights and limitations under the License.
0013: *
0014: * Copyright (C) 2001 Chad Fowler <chadfowler@chadfowler.com>
0015: * Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
0016: * Copyright (C) 2001-2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
0017: * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
0018: * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
0019: * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
0020: * Copyright (C) 2004-2005 Charles O Nutter <headius@headius.com>
0021: * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
0022: * Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
0023: * Copyright (C) 2006 Michael Studman <codehaus@michaelstudman.com>
0024: * Copyright (C) 2006 Ola Bini <ola@ologix.com>
0025: * Copyright (C) 2007 Nick Sieger <nicksieger@gmail.com>
0026: *
0027: * Alternatively, the contents of this file may be used under the terms of
0028: * either of the GNU General Public License Version 2 or later (the "GPL"),
0029: * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
0030: * in which case the provisions of the GPL or the LGPL are applicable instead
0031: * of those above. If you wish to allow use of your version of this file only
0032: * under the terms of either the GPL or the LGPL, and not to allow others to
0033: * use your version of this file under the terms of the CPL, indicate your
0034: * decision by deleting the provisions above and replace them with the notice
0035: * and other provisions required by the GPL or the LGPL. If you do not delete
0036: * the provisions above, a recipient may use your version of this file under
0037: * the terms of any one of the CPL, the GPL or the LGPL.
0038: ***** END LICENSE BLOCK *****/package org.jruby;
0039:
0040: import java.io.BufferedReader;
0041: import java.io.File;
0042: import java.io.FileReader;
0043: import java.io.IOException;
0044: import java.io.InputStream;
0045: import java.io.PrintStream;
0046: import java.io.Reader;
0047: import java.io.StringReader;
0048: import java.util.ArrayList;
0049: import java.util.Hashtable;
0050: import java.util.Iterator;
0051: import java.util.LinkedList;
0052: import java.util.List;
0053: import java.util.Map;
0054: import java.util.Random;
0055: import java.util.Stack;
0056: import java.util.WeakHashMap;
0057: import org.jruby.ast.Node;
0058: import org.jruby.ast.executable.Script;
0059: import org.jruby.ast.executable.YARVCompiledRunner;
0060: import org.jruby.common.RubyWarnings;
0061: import org.jruby.compiler.NodeCompilerFactory;
0062: import org.jruby.compiler.NotCompilableException;
0063: import org.jruby.compiler.impl.StandardASMCompiler;
0064: import org.jruby.compiler.yarv.StandardYARVCompiler;
0065: import org.jruby.evaluator.EvaluationState;
0066: import org.jruby.exceptions.JumpException;
0067: import org.jruby.exceptions.RaiseException;
0068: import org.jruby.internal.runtime.GlobalVariables;
0069: import org.jruby.internal.runtime.ThreadService;
0070: import org.jruby.internal.runtime.ValueAccessor;
0071: import org.jruby.javasupport.Java;
0072: import org.jruby.javasupport.JavaSupport;
0073: import org.jruby.libraries.IConvLibrary;
0074: import org.jruby.libraries.JRubyLibrary;
0075: import org.jruby.libraries.NKFLibrary;
0076: import org.jruby.libraries.RbConfigLibrary;
0077: import org.jruby.libraries.StringIOLibrary;
0078: import org.jruby.libraries.StringScannerLibrary;
0079: import org.jruby.libraries.ZlibLibrary;
0080: import org.jruby.libraries.YamlLibrary;
0081: import org.jruby.libraries.EnumeratorLibrary;
0082: import org.jruby.libraries.BigDecimalLibrary;
0083: import org.jruby.libraries.DigestLibrary;
0084: import org.jruby.libraries.ThreadLibrary;
0085: import org.jruby.libraries.IOWaitLibrary;
0086: import org.jruby.ext.socket.RubySocket;
0087: import org.jruby.ext.Generator;
0088: import org.jruby.ext.Readline;
0089: import org.jruby.parser.Parser;
0090: import org.jruby.runtime.Block;
0091: import org.jruby.runtime.CacheMap;
0092: import org.jruby.runtime.CallbackFactory;
0093: import org.jruby.runtime.DynamicScope;
0094: import org.jruby.runtime.EventHook;
0095: import org.jruby.runtime.GlobalVariable;
0096: import org.jruby.runtime.IAccessor;
0097: import org.jruby.runtime.MethodSelectorTable;
0098: import org.jruby.runtime.ObjectAllocator;
0099: import org.jruby.runtime.ObjectSpace;
0100: import org.jruby.runtime.ThreadContext;
0101: import org.jruby.runtime.builtin.IRubyObject;
0102: import org.jruby.runtime.load.Library;
0103: import org.jruby.runtime.load.LoadService;
0104: import org.jruby.util.BuiltinScript;
0105: import org.jruby.util.ByteList;
0106: import org.jruby.util.IOInputStream;
0107: import org.jruby.util.IOOutputStream;
0108: import org.jruby.util.JRubyClassLoader;
0109: import org.jruby.util.KCode;
0110: import org.jruby.util.MethodCache;
0111: import org.jruby.util.NormalizedFile;
0112: import org.jruby.util.collections.SinglyLinkedList;
0113:
0114: /**
0115: * The jruby runtime.
0116: */
0117: public final class Ruby {
0118: private static String[] BUILTIN_LIBRARIES = { "fcntl", "yaml",
0119: "yaml/syck", "jsignal" };
0120:
0121: private CacheMap cacheMap = new CacheMap(this );
0122: private MethodCache methodCache = new MethodCache();
0123: private ThreadService threadService = new ThreadService(this );
0124: private Hashtable runtimeInformation;
0125: private final MethodSelectorTable selectorTable = new MethodSelectorTable();
0126:
0127: private int stackTraces = 0;
0128:
0129: private ObjectSpace objectSpace = new ObjectSpace();
0130:
0131: private final RubyFixnum[] fixnumCache = new RubyFixnum[256];
0132: private final RubySymbol.SymbolTable symbolTable = new RubySymbol.SymbolTable();
0133: private Hashtable ioHandlers = new Hashtable();
0134: private long randomSeed = 0;
0135: private long randomSeedSequence = 0;
0136: private Random random = new Random();
0137:
0138: private List eventHooks = new LinkedList();
0139: private boolean globalAbortOnExceptionEnabled = false;
0140: private boolean doNotReverseLookupEnabled = false;
0141: private final boolean objectSpaceEnabled;
0142:
0143: private long globalState = 1;
0144:
0145: /** safe-level:
0146: 0 - strings from streams/environment/ARGV are tainted (default)
0147: 1 - no dangerous operation by tainted value
0148: 2 - process/file operations prohibited
0149: 3 - all genetated objects are tainted
0150: 4 - no global (non-tainted) variable modification/no direct output
0151: */
0152: private int safeLevel = 0;
0153:
0154: // Default classes/objects
0155: private IRubyObject nilObject;
0156: private RubyBoolean trueObject;
0157: private RubyBoolean falseObject;
0158: private RubyClass objectClass;
0159: private RubyClass stringClass;
0160: private RubyModule enumerableModule;
0161: private RubyClass systemCallError = null;
0162: private RubyModule errnoModule = null;
0163: private IRubyObject topSelf;
0164:
0165: // former java.lang.System concepts now internalized for MVM
0166: private String currentDirectory;
0167:
0168: private long startTime = System.currentTimeMillis();
0169:
0170: private RubyInstanceConfig config;
0171:
0172: private InputStream in;
0173: private PrintStream out;
0174: private PrintStream err;
0175:
0176: private IRubyObject verbose;
0177: private IRubyObject debug;
0178:
0179: // Java support
0180: private JavaSupport javaSupport;
0181: private static JRubyClassLoader jrubyClassLoader;
0182:
0183: private static boolean securityRestricted = false;
0184:
0185: private Parser parser = new Parser(this );
0186:
0187: private LoadService loadService;
0188: private GlobalVariables globalVariables = new GlobalVariables(this );
0189: private RubyWarnings warnings = new RubyWarnings(this );
0190:
0191: // Contains a list of all blocks (as Procs) that should be called when
0192: // the runtime environment exits.
0193: private Stack atExitBlocks = new Stack();
0194:
0195: private RubyModule kernelModule;
0196:
0197: private RubyClass nilClass;
0198:
0199: private RubyClass fixnumClass;
0200:
0201: private RubyClass arrayClass;
0202:
0203: private RubyClass hashClass;
0204:
0205: private IRubyObject tmsStruct;
0206:
0207: private IRubyObject undef;
0208:
0209: private Profile profile;
0210:
0211: private String jrubyHome;
0212:
0213: private KCode kcode = KCode.NONE;
0214:
0215: public int symbolLastId = 0;
0216: public int moduleLastId = 0;
0217:
0218: private Object respondToMethod;
0219:
0220: /**
0221: * A list of finalizers, weakly referenced, to be executed on tearDown
0222: */
0223: private Map finalizers;
0224:
0225: /**
0226: * Create and initialize a new jruby Runtime.
0227: */
0228: private Ruby(RubyInstanceConfig config) {
0229: this .config = config;
0230: this .in = config.getInput();
0231: this .out = config.getOutput();
0232: this .err = config.getError();
0233: this .objectSpaceEnabled = config.isObjectSpaceEnabled();
0234: this .profile = config.getProfile();
0235: this .currentDirectory = config.getCurrentDirectory();
0236: ;
0237: }
0238:
0239: /**
0240: * Returns a default instance of the JRuby runtime.
0241: *
0242: * @return the JRuby runtime
0243: */
0244: public static Ruby getDefaultInstance() {
0245: return newInstance(new RubyInstanceConfig());
0246: }
0247:
0248: /**
0249: * Returns a default instance of the JRuby runtime configured as provided.
0250: *
0251: * @param config the instance configuration
0252: * @return the JRuby runtime
0253: */
0254: public static Ruby newInstance(RubyInstanceConfig config) {
0255: Ruby ruby = new Ruby(config);
0256: ruby.init();
0257: return ruby;
0258: }
0259:
0260: /**
0261: * Returns a default instance of the JRuby runtime configured with the given input, output and error streams.
0262: *
0263: * @param in the custom input stream
0264: * @param out the custom output stream
0265: * @param err the custom error stream
0266: * @return the JRuby runtime
0267: */
0268: public static Ruby newInstance(InputStream in, PrintStream out,
0269: PrintStream err) {
0270: RubyInstanceConfig config = new RubyInstanceConfig();
0271: config.setInput(in);
0272: config.setOutput(out);
0273: config.setError(err);
0274: return newInstance(config);
0275: }
0276:
0277: public IRubyObject evalScript(Reader reader, String name) {
0278: return eval(parse(reader, name, getCurrentContext()
0279: .getCurrentScope(), 0));
0280: }
0281:
0282: /**
0283: * Evaluates a script and returns a RubyObject.
0284: */
0285: public IRubyObject evalScript(String script) {
0286: return eval(parse(script, "<script>", getCurrentContext()
0287: .getCurrentScope(), 0));
0288: }
0289:
0290: public IRubyObject eval(Node node) {
0291: try {
0292: ThreadContext tc = getCurrentContext();
0293:
0294: return EvaluationState.eval(this , tc, node, tc
0295: .getFrameSelf(), Block.NULL_BLOCK);
0296: } catch (JumpException je) {
0297: if (je.getJumpType() == JumpException.JumpType.ReturnJump) {
0298: throw newLocalJumpError("return", (IRubyObject) je
0299: .getValue(), "unexpected return");
0300: // return (IRubyObject)je.getSecondaryData();
0301: } else if (je.getJumpType() == JumpException.JumpType.BreakJump) {
0302: throw newLocalJumpError("break", (IRubyObject) je
0303: .getValue(), "unexpected break");
0304: }
0305:
0306: throw je;
0307: }
0308: }
0309:
0310: public IRubyObject compileOrFallbackAndRun(Node node) {
0311: try {
0312: ThreadContext tc = getCurrentContext();
0313:
0314: // do the compile if JIT is enabled
0315: if (config.isJitEnabled() && !hasEventHooks()) {
0316: Script script = null;
0317: try {
0318: StandardASMCompiler compiler = new StandardASMCompiler(
0319: node);
0320: NodeCompilerFactory.getCompiler(node).compile(node,
0321: compiler);
0322:
0323: Class scriptClass = compiler.loadClass(this
0324: .getJRubyClassLoader());
0325:
0326: script = (Script) scriptClass.newInstance();
0327: } catch (Throwable t) {
0328: return eval(node);
0329: }
0330:
0331: // FIXME: Pass something better for args and block here?
0332: return script.run(getCurrentContext(), tc
0333: .getFrameSelf(), IRubyObject.NULL_ARRAY,
0334: Block.NULL_BLOCK);
0335: } else {
0336: return eval(node);
0337: }
0338: } catch (JumpException je) {
0339: if (je.getJumpType() == JumpException.JumpType.ReturnJump) {
0340: return (IRubyObject) je.getValue();
0341: } else {
0342: throw je;
0343: }
0344: }
0345:
0346: }
0347:
0348: public IRubyObject compileAndRun(Node node) {
0349: try {
0350: ThreadContext tc = getCurrentContext();
0351:
0352: // do the compile
0353: StandardASMCompiler compiler = new StandardASMCompiler(node);
0354: NodeCompilerFactory.getCompiler(node).compile(node,
0355: compiler);
0356:
0357: Class scriptClass = compiler.loadClass(this
0358: .getJRubyClassLoader());
0359:
0360: Script script = (Script) scriptClass.newInstance();
0361: // FIXME: Pass something better for args and block here?
0362: return script.run(getCurrentContext(), tc.getFrameSelf(),
0363: IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
0364: } catch (NotCompilableException nce) {
0365: System.err.println("Error -- Not compileable: "
0366: + nce.getMessage());
0367: return null;
0368: } catch (JumpException je) {
0369: if (je.getJumpType() == JumpException.JumpType.ReturnJump) {
0370: return (IRubyObject) je.getValue();
0371: } else {
0372: throw je;
0373: }
0374: } catch (ClassNotFoundException e) {
0375: System.err.println("Error -- Not compileable: "
0376: + e.getMessage());
0377: return null;
0378: } catch (InstantiationException e) {
0379: System.err.println("Error -- Not compileable: "
0380: + e.getMessage());
0381: return null;
0382: } catch (IllegalAccessException e) {
0383: System.err.println("Error -- Not compileable: "
0384: + e.getMessage());
0385: return null;
0386: }
0387: }
0388:
0389: public IRubyObject ycompileAndRun(Node node) {
0390: try {
0391: StandardYARVCompiler compiler = new StandardYARVCompiler(
0392: this );
0393: NodeCompilerFactory.getYARVCompiler().compile(node,
0394: compiler);
0395: org.jruby.lexer.yacc.ISourcePosition p = node.getPosition();
0396: if (p == null && node instanceof org.jruby.ast.RootNode) {
0397: p = ((org.jruby.ast.RootNode) node).getBodyNode()
0398: .getPosition();
0399: }
0400: return new YARVCompiledRunner(this , compiler
0401: .getInstructionSequence("<main>", p.getFile(),
0402: "toplevel")).run();
0403: } catch (NotCompilableException nce) {
0404: System.err.println("Error -- Not compileable: "
0405: + nce.getMessage());
0406: return null;
0407: } catch (JumpException je) {
0408: if (je.getJumpType() == JumpException.JumpType.ReturnJump) {
0409: return (IRubyObject) je.getValue();
0410: }
0411:
0412: throw je;
0413: }
0414: }
0415:
0416: Object getRespondToMethod() {
0417: return respondToMethod;
0418: }
0419:
0420: void setRespondToMethod(Object rtm) {
0421: this .respondToMethod = rtm;
0422: }
0423:
0424: public RubyClass getObject() {
0425: return objectClass;
0426: }
0427:
0428: public IRubyObject getUndef() {
0429: return undef;
0430: }
0431:
0432: public RubyModule getKernel() {
0433: return kernelModule;
0434: }
0435:
0436: public RubyModule getEnumerable() {
0437: return enumerableModule;
0438: }
0439:
0440: public RubyClass getString() {
0441: return stringClass;
0442: }
0443:
0444: public RubyClass getFixnum() {
0445: return fixnumClass;
0446: }
0447:
0448: public RubyClass getHash() {
0449: return hashClass;
0450: }
0451:
0452: public RubyClass getArray() {
0453: return arrayClass;
0454: }
0455:
0456: public IRubyObject getTmsStruct() {
0457: return tmsStruct;
0458: }
0459:
0460: /** Returns the "true" instance from the instance pool.
0461: * @return The "true" instance.
0462: */
0463: public RubyBoolean getTrue() {
0464: return trueObject;
0465: }
0466:
0467: /** Returns the "false" instance from the instance pool.
0468: * @return The "false" instance.
0469: */
0470: public RubyBoolean getFalse() {
0471: return falseObject;
0472: }
0473:
0474: /** Returns the "nil" singleton instance.
0475: * @return "nil"
0476: */
0477: public IRubyObject getNil() {
0478: return nilObject;
0479: }
0480:
0481: public RubyClass getNilClass() {
0482: return nilClass;
0483: }
0484:
0485: public RubyModule getModule(String name) {
0486: return (RubyModule) objectClass.getConstantAt(name);
0487: }
0488:
0489: /** Returns a class from the instance pool.
0490: *
0491: * @param name The name of the class.
0492: * @return The class.
0493: */
0494: public RubyClass getClass(String name) {
0495: try {
0496: return objectClass.getClass(name);
0497: } catch (ClassCastException e) {
0498: throw newTypeError(name + " is not a Class");
0499: }
0500: }
0501:
0502: /** Define a new class with name 'name' and super class 'superClass'.
0503: *
0504: * MRI: rb_define_class / rb_define_class_id
0505: *
0506: */
0507: public RubyClass defineClass(String name, RubyClass super Class,
0508: ObjectAllocator allocator) {
0509: return defineClassUnder(name, super Class, allocator,
0510: objectClass.getCRef());
0511: }
0512:
0513: public RubyClass defineClassUnder(String name,
0514: RubyClass super Class, ObjectAllocator allocator,
0515: SinglyLinkedList parentCRef) {
0516: if (super Class == null)
0517: super Class = objectClass;
0518:
0519: return super Class
0520: .newSubClass(name, allocator, parentCRef, true);
0521: }
0522:
0523: /** rb_define_module / rb_define_module_id
0524: *
0525: */
0526: public RubyModule defineModule(String name) {
0527: return defineModuleUnder(name, objectClass.getCRef());
0528: }
0529:
0530: public RubyModule defineModuleUnder(String name,
0531: SinglyLinkedList parentCRef) {
0532: RubyModule newModule = RubyModule.newModule(this , name,
0533: parentCRef);
0534:
0535: ((RubyModule) parentCRef.getValue()).setConstant(name,
0536: newModule);
0537:
0538: return newModule;
0539: }
0540:
0541: /**
0542: * In the current context, get the named module. If it doesn't exist a
0543: * new module is created.
0544: */
0545: public RubyModule getOrCreateModule(String name) {
0546: IRubyObject module = objectClass.getConstantAt(name);
0547:
0548: if (module == null) {
0549: module = defineModule(name);
0550: } else if (getSafeLevel() >= 4) {
0551: throw newSecurityError("Extending module prohibited.");
0552: } else if (!(module instanceof RubyModule)) {
0553: throw newTypeError(name + " is not a Module");
0554: }
0555:
0556: return (RubyModule) module;
0557: }
0558:
0559: /** Getter for property securityLevel.
0560: * @return Value of property securityLevel.
0561: */
0562: public int getSafeLevel() {
0563: return this .safeLevel;
0564: }
0565:
0566: /** Setter for property securityLevel.
0567: * @param safeLevel New value of property securityLevel.
0568: */
0569: public void setSafeLevel(int safeLevel) {
0570: this .safeLevel = safeLevel;
0571: }
0572:
0573: public KCode getKCode() {
0574: return kcode;
0575: }
0576:
0577: public void setKCode(KCode kcode) {
0578: this .kcode = kcode;
0579: }
0580:
0581: public void secure(int level) {
0582: if (level <= safeLevel) {
0583: throw newSecurityError("Insecure operation '"
0584: + getCurrentContext().getFrameName()
0585: + "' at level " + safeLevel);
0586: }
0587: }
0588:
0589: // FIXME moved this hear to get what's obviously a utility method out of IRubyObject.
0590: // perhaps security methods should find their own centralized home at some point.
0591: public void checkSafeString(IRubyObject object) {
0592: if (getSafeLevel() > 0 && object.isTaint()) {
0593: ThreadContext tc = getCurrentContext();
0594: if (tc.getFrameName() != null) {
0595: throw newSecurityError("Insecure operation - "
0596: + tc.getFrameName());
0597: }
0598: throw newSecurityError("Insecure operation: -r");
0599: }
0600: secure(4);
0601: if (!(object instanceof RubyString)) {
0602: throw newTypeError("wrong argument type "
0603: + object.getMetaClass().getName()
0604: + " (expected String)");
0605: }
0606: }
0607:
0608: /**
0609: * Retrieve mappings of cached methods to where they have been cached. When a cached
0610: * method needs to be invalidated this map can be used to remove all places it has been
0611: * cached.
0612: *
0613: * @return the mappings of where cached methods have been stored
0614: */
0615: public CacheMap getCacheMap() {
0616: return cacheMap;
0617: }
0618:
0619: /**
0620: * Retrieve method cache.
0621: *
0622: * @return method cache where cached methods have been stored
0623: */
0624: public MethodCache getMethodCache() {
0625: return methodCache;
0626: }
0627:
0628: /**
0629: * @see org.jruby.Ruby#getRuntimeInformation
0630: */
0631: public Map getRuntimeInformation() {
0632: return runtimeInformation == null ? runtimeInformation = new Hashtable()
0633: : runtimeInformation;
0634: }
0635:
0636: public MethodSelectorTable getSelectorTable() {
0637: return selectorTable;
0638: }
0639:
0640: /** rb_define_global_const
0641: *
0642: */
0643: public void defineGlobalConstant(String name, IRubyObject value) {
0644: objectClass.defineConstant(name, value);
0645: }
0646:
0647: public boolean isClassDefined(String name) {
0648: return getModule(name) != null;
0649: }
0650:
0651: /** Getter for property rubyTopSelf.
0652: * @return Value of property rubyTopSelf.
0653: */
0654: public IRubyObject getTopSelf() {
0655: return topSelf;
0656: }
0657:
0658: public void setCurrentDirectory(String dir) {
0659: currentDirectory = dir;
0660: }
0661:
0662: public String getCurrentDirectory() {
0663: return currentDirectory;
0664: }
0665:
0666: /** ruby_init
0667: *
0668: */
0669: // TODO: Figure out real dependencies between vars and reorder/refactor into better methods
0670: private void init() {
0671: ThreadContext tc = getCurrentContext();
0672:
0673: javaSupport = new JavaSupport(this );
0674:
0675: tc.preInitCoreClasses();
0676:
0677: initCoreClasses();
0678:
0679: verbose = falseObject;
0680: debug = falseObject;
0681:
0682: // init selector table, now that classes are done adding methods
0683: selectorTable.init();
0684:
0685: initLibraries();
0686:
0687: topSelf = TopSelfFactory.createTopSelf(this );
0688:
0689: tc.preInitBuiltinClasses(objectClass, topSelf);
0690:
0691: RubyGlobal.createGlobals(this );
0692:
0693: defineGlobalConstant("TRUE", trueObject);
0694: defineGlobalConstant("FALSE", falseObject);
0695: defineGlobalConstant("NIL", nilObject);
0696:
0697: getObject().defineConstant("TOPLEVEL_BINDING", newBinding());
0698:
0699: RubyKernel.autoload(topSelf, newSymbol("Java"),
0700: newString("java"));
0701:
0702: methodCache.initialized();
0703: }
0704:
0705: private void initLibraries() {
0706: loadService = config.createLoadService(this );
0707: registerBuiltin("java.rb", new Library() {
0708: public void load(Ruby runtime) throws IOException {
0709: Java.createJavaModule(runtime);
0710: new BuiltinScript("javasupport").load(runtime);
0711: RubyClassPathVariable.createClassPathVariable(runtime);
0712: }
0713: });
0714:
0715: registerBuiltin("socket.rb", new RubySocket.Service());
0716: registerBuiltin("rbconfig.rb", new RbConfigLibrary());
0717:
0718: for (int i = 0; i < BUILTIN_LIBRARIES.length; i++) {
0719: if (profile.allowBuiltin(BUILTIN_LIBRARIES[i])) {
0720: loadService.registerRubyBuiltin(BUILTIN_LIBRARIES[i]);
0721: }
0722: }
0723:
0724: final Library NO_OP_LIBRARY = new Library() {
0725: public void load(Ruby runtime) throws IOException {
0726: }
0727: };
0728:
0729: registerBuiltin("jruby.rb", new JRubyLibrary());
0730: registerBuiltin("iconv.rb", new IConvLibrary());
0731: registerBuiltin("nkf.rb", new NKFLibrary());
0732: registerBuiltin("stringio.rb", new StringIOLibrary());
0733: registerBuiltin("strscan.rb", new StringScannerLibrary());
0734: registerBuiltin("zlib.rb", new ZlibLibrary());
0735: registerBuiltin("yaml_internal.rb", new YamlLibrary());
0736: registerBuiltin("enumerator.rb", new EnumeratorLibrary());
0737: registerBuiltin("generator_internal.rb",
0738: new Generator.Service());
0739: registerBuiltin("readline.rb", new Readline.Service());
0740: registerBuiltin("thread.so", new ThreadLibrary());
0741: registerBuiltin("openssl.so", new Library() {
0742: public void load(Ruby runtime) throws IOException {
0743: runtime.getModule("Kernel").callMethod(
0744: runtime.getCurrentContext(), "require",
0745: runtime.newString("rubygems"));
0746: runtime.getTopSelf().callMethod(
0747: runtime.getCurrentContext(), "gem",
0748: runtime.newString("jruby-openssl"));
0749: runtime.getModule("Kernel").callMethod(
0750: runtime.getCurrentContext(), "require",
0751: runtime.newString("openssl.rb"));
0752: }
0753: });
0754: registerBuiltin("digest.so", new DigestLibrary());
0755: registerBuiltin("digest.rb", new DigestLibrary());
0756: registerBuiltin("digest/md5.rb", new DigestLibrary.MD5());
0757: registerBuiltin("digest/rmd160.rb", new DigestLibrary.RMD160());
0758: registerBuiltin("digest/sha1.rb", new DigestLibrary.SHA1());
0759: registerBuiltin("digest/sha2.rb", new DigestLibrary.SHA2());
0760: registerBuiltin("bigdecimal.rb", new BigDecimalLibrary());
0761: registerBuiltin("io/wait.so", new IOWaitLibrary());
0762: registerBuiltin("etc.so", NO_OP_LIBRARY);
0763: }
0764:
0765: private void registerBuiltin(String nm, Library lib) {
0766: if (profile.allowBuiltin(nm)) {
0767: loadService.registerBuiltin(nm, lib);
0768: }
0769: }
0770:
0771: private void initCoreClasses() {
0772: undef = new RubyUndef();
0773:
0774: RubyClass objectMetaClass = RubyClass
0775: .createBootstrapMetaClass(this , "Object", null,
0776: RubyObject.OBJECT_ALLOCATOR, null);
0777: RubyObject.createObjectClass(this , objectMetaClass);
0778:
0779: objectClass = objectMetaClass;
0780: objectClass.setConstant("Object", objectClass);
0781: RubyClass moduleClass = RubyClass.createBootstrapMetaClass(
0782: this , "Module", objectClass,
0783: RubyModule.MODULE_ALLOCATOR, objectClass.getCRef());
0784: objectClass.setConstant("Module", moduleClass);
0785: RubyClass classClass = RubyClass.newClassClass(this ,
0786: moduleClass);
0787: objectClass.setConstant("Class", classClass);
0788:
0789: classClass.setMetaClass(classClass);
0790: moduleClass.setMetaClass(classClass);
0791: objectClass.setMetaClass(classClass);
0792:
0793: // I don't think the containment is correct here (parent cref)
0794: RubyClass metaClass = objectClass.makeMetaClass(classClass,
0795: objectMetaClass.getCRef());
0796: metaClass = moduleClass.makeMetaClass(metaClass,
0797: objectMetaClass.getCRef());
0798: metaClass = classClass.makeMetaClass(metaClass, objectMetaClass
0799: .getCRef());
0800:
0801: RubyModule.createModuleClass(this , moduleClass);
0802:
0803: kernelModule = RubyKernel.createKernelModule(this );
0804: objectClass.includeModule(kernelModule);
0805:
0806: RubyClass.createClassClass(classClass);
0807:
0808: nilClass = RubyNil.createNilClass(this );
0809:
0810: // Pre-create the core classes we know we will get referenced by starting up the runtime.
0811: RubyBoolean.createFalseClass(this );
0812: RubyBoolean.createTrueClass(this );
0813:
0814: nilObject = new RubyNil(this );
0815: trueObject = new RubyBoolean(this , true);
0816: falseObject = new RubyBoolean(this , false);
0817:
0818: RubyComparable.createComparable(this );
0819: enumerableModule = RubyEnumerable.createEnumerableModule(this );
0820: stringClass = RubyString.createStringClass(this );
0821: RubySymbol.createSymbolClass(this );
0822:
0823: if (profile.allowClass("ThreadGroup"))
0824: RubyThreadGroup.createThreadGroupClass(this );
0825: if (profile.allowClass("Thread"))
0826: RubyThread.createThreadClass(this );
0827: if (profile.allowClass("Exception"))
0828: RubyException.createExceptionClass(this );
0829: if (profile.allowModule("Precision"))
0830: RubyPrecision.createPrecisionModule(this );
0831: if (profile.allowClass("Numeric"))
0832: RubyNumeric.createNumericClass(this );
0833: if (profile.allowClass("Integer"))
0834: RubyInteger.createIntegerClass(this );
0835: if (profile.allowClass("Fixnum"))
0836: fixnumClass = RubyFixnum.createFixnumClass(this );
0837: if (profile.allowClass("Hash"))
0838: hashClass = RubyHash.createHashClass(this );
0839:
0840: RubyIO.createIOClass(this );
0841:
0842: if (profile.allowClass("Array"))
0843: arrayClass = RubyArray.createArrayClass(this );
0844:
0845: RubyClass structClass = null;
0846: if (profile.allowClass("Struct"))
0847: structClass = RubyStruct.createStructClass(this );
0848:
0849: if (profile.allowClass("Tms")) {
0850: tmsStruct = RubyStruct.newInstance(structClass,
0851: new IRubyObject[] { newString("Tms"),
0852: newSymbol("utime"), newSymbol("stime"),
0853: newSymbol("cutime"), newSymbol("cstime") },
0854: Block.NULL_BLOCK);
0855: }
0856:
0857: if (profile.allowClass("Float"))
0858: RubyFloat.createFloatClass(this );
0859: if (profile.allowClass("Bignum"))
0860: RubyBignum.createBignumClass(this );
0861: if (profile.allowClass("Binding"))
0862: RubyBinding.createBindingClass(this );
0863: // Math depends on all numeric types
0864: if (profile.allowModule("Math"))
0865: RubyMath.createMathModule(this );
0866: if (profile.allowClass("Regexp"))
0867: RubyRegexp.createRegexpClass(this );
0868: if (profile.allowClass("Range"))
0869: RubyRange.createRangeClass(this );
0870: if (profile.allowModule("ObjectSpace"))
0871: RubyObjectSpace.createObjectSpaceModule(this );
0872: if (profile.allowModule("GC"))
0873: RubyGC.createGCModule(this );
0874: if (profile.allowClass("Proc"))
0875: RubyProc.createProcClass(this );
0876: if (profile.allowClass("Method"))
0877: RubyMethod.createMethodClass(this );
0878: if (profile.allowClass("MatchData"))
0879: RubyMatchData.createMatchDataClass(this );
0880: if (profile.allowModule("Marshal"))
0881: RubyMarshal.createMarshalModule(this );
0882: if (profile.allowClass("Dir"))
0883: RubyDir.createDirClass(this );
0884: if (profile.allowModule("FileTest"))
0885: RubyFileTest.createFileTestModule(this );
0886: // depends on IO, FileTest
0887: if (profile.allowClass("File"))
0888: RubyFile.createFileClass(this );
0889: if (profile.allowModule("Process"))
0890: RubyProcess.createProcessModule(this );
0891: if (profile.allowClass("Time"))
0892: RubyTime.createTimeClass(this );
0893: if (profile.allowClass("UnboundMethod"))
0894: RubyUnboundMethod.defineUnboundMethodClass(this );
0895:
0896: RubyClass exceptionClass = getClass("Exception");
0897: RubyClass standardError = null;
0898: RubyClass runtimeError = null;
0899: RubyClass ioError = null;
0900: RubyClass scriptError = null;
0901: RubyClass nameError = null;
0902: RubyClass signalException = null;
0903:
0904: RubyClass rangeError = null;
0905: if (profile.allowClass("StandardError")) {
0906: standardError = defineClass("StandardError",
0907: exceptionClass, exceptionClass.getAllocator());
0908: }
0909: if (profile.allowClass("RuntimeError")) {
0910: runtimeError = defineClass("RuntimeError", standardError,
0911: standardError.getAllocator());
0912: }
0913: if (profile.allowClass("IOError")) {
0914: ioError = defineClass("IOError", standardError,
0915: standardError.getAllocator());
0916: }
0917: if (profile.allowClass("ScriptError")) {
0918: scriptError = defineClass("ScriptError", exceptionClass,
0919: exceptionClass.getAllocator());
0920: }
0921: if (profile.allowClass("NameError")) {
0922: nameError = RubyNameError.createNameErrorClass(this ,
0923: standardError);
0924: }
0925: if (profile.allowClass("NoMethodError")) {
0926: RubyNoMethodError.createNoMethodErrorClass(this , nameError);
0927: }
0928: if (profile.allowClass("RangeError")) {
0929: rangeError = defineClass("RangeError", standardError,
0930: standardError.getAllocator());
0931: }
0932: if (profile.allowClass("SystemExit")) {
0933: RubySystemExit.createSystemExitClass(this , exceptionClass);
0934: }
0935: if (profile.allowClass("Fatal")) {
0936: defineClass("Fatal", exceptionClass, exceptionClass
0937: .getAllocator());
0938: }
0939: if (profile.allowClass("SignalException")) {
0940: signalException = defineClass("SignalException",
0941: exceptionClass, exceptionClass.getAllocator());
0942: }
0943: if (profile.allowClass("Interrupt")) {
0944: defineClass("Interrupt", signalException, signalException
0945: .getAllocator());
0946: }
0947: if (profile.allowClass("TypeError")) {
0948: defineClass("TypeError", standardError, standardError
0949: .getAllocator());
0950: }
0951: if (profile.allowClass("ArgumentError")) {
0952: defineClass("ArgumentError", standardError, standardError
0953: .getAllocator());
0954: }
0955: if (profile.allowClass("IndexError")) {
0956: defineClass("IndexError", standardError, standardError
0957: .getAllocator());
0958: }
0959: if (profile.allowClass("SyntaxError")) {
0960: defineClass("SyntaxError", scriptError, scriptError
0961: .getAllocator());
0962: }
0963: if (profile.allowClass("LoadError")) {
0964: defineClass("LoadError", scriptError, scriptError
0965: .getAllocator());
0966: }
0967: if (profile.allowClass("NotImplementedError")) {
0968: defineClass("NotImplementedError", scriptError, scriptError
0969: .getAllocator());
0970: }
0971: if (profile.allowClass("SecurityError")) {
0972: defineClass("SecurityError", standardError, standardError
0973: .getAllocator());
0974: }
0975: if (profile.allowClass("NoMemoryError")) {
0976: defineClass("NoMemoryError", exceptionClass, exceptionClass
0977: .getAllocator());
0978: }
0979: if (profile.allowClass("RegexpError")) {
0980: defineClass("RegexpError", standardError, standardError
0981: .getAllocator());
0982: }
0983: if (profile.allowClass("EOFError")) {
0984: defineClass("EOFError", ioError, ioError.getAllocator());
0985: }
0986: if (profile.allowClass("LocalJumpError")) {
0987: RubyLocalJumpError.createLocalJumpErrorClass(this ,
0988: standardError);
0989: }
0990: if (profile.allowClass("ThreadError")) {
0991: defineClass("ThreadError", standardError, standardError
0992: .getAllocator());
0993: }
0994: if (profile.allowClass("SystemStackError")) {
0995: defineClass("SystemStackError", exceptionClass,
0996: exceptionClass.getAllocator());
0997: }
0998: if (profile.allowClass("ZeroDivisionError")) {
0999: defineClass("ZeroDivisionError", standardError,
1000: standardError.getAllocator());
1001: }
1002: // FIXME: Actually this somewhere <- fixed
1003: if (profile.allowClass("FloatDomainError")) {
1004: defineClass("FloatDomainError", rangeError, rangeError
1005: .getAllocator());
1006: }
1007: if (profile.allowClass("NativeException"))
1008: NativeException.createClass(this , runtimeError);
1009: if (profile.allowClass("SystemCallError")) {
1010: systemCallError = defineClass("SystemCallError",
1011: standardError, standardError.getAllocator());
1012: }
1013: if (profile.allowModule("Errno"))
1014: errnoModule = defineModule("Errno");
1015:
1016: initErrnoErrors();
1017:
1018: if (profile.allowClass("Data"))
1019: defineClass("Data", objectClass, objectClass.getAllocator());
1020: if (profile.allowModule("Signal"))
1021: RubySignal.createSignal(this );
1022: if (profile.allowClass("Continuation"))
1023: RubyContinuation.createContinuation(this );
1024: }
1025:
1026: /**
1027: * Create module Errno's Variables. We have this method since Errno does not have it's
1028: * own java class.
1029: */
1030: private void initErrnoErrors() {
1031: createSysErr(IErrno.ENOTEMPTY, "ENOTEMPTY");
1032: createSysErr(IErrno.ERANGE, "ERANGE");
1033: createSysErr(IErrno.ESPIPE, "ESPIPE");
1034: createSysErr(IErrno.ENFILE, "ENFILE");
1035: createSysErr(IErrno.EXDEV, "EXDEV");
1036: createSysErr(IErrno.ENOMEM, "ENOMEM");
1037: createSysErr(IErrno.E2BIG, "E2BIG");
1038: createSysErr(IErrno.ENOENT, "ENOENT");
1039: createSysErr(IErrno.ENOSYS, "ENOSYS");
1040: createSysErr(IErrno.EDOM, "EDOM");
1041: createSysErr(IErrno.ENOSPC, "ENOSPC");
1042: createSysErr(IErrno.EINVAL, "EINVAL");
1043: createSysErr(IErrno.EEXIST, "EEXIST");
1044: createSysErr(IErrno.EAGAIN, "EAGAIN");
1045: createSysErr(IErrno.ENXIO, "ENXIO");
1046: createSysErr(IErrno.EILSEQ, "EILSEQ");
1047: createSysErr(IErrno.ENOLCK, "ENOLCK");
1048: createSysErr(IErrno.EPIPE, "EPIPE");
1049: createSysErr(IErrno.EFBIG, "EFBIG");
1050: createSysErr(IErrno.EISDIR, "EISDIR");
1051: createSysErr(IErrno.EBUSY, "EBUSY");
1052: createSysErr(IErrno.ECHILD, "ECHILD");
1053: createSysErr(IErrno.EIO, "EIO");
1054: createSysErr(IErrno.EPERM, "EPERM");
1055: createSysErr(IErrno.EDEADLOCK, "EDEADLOCK");
1056: createSysErr(IErrno.ENAMETOOLONG, "ENAMETOOLONG");
1057: createSysErr(IErrno.EMLINK, "EMLINK");
1058: createSysErr(IErrno.ENOTTY, "ENOTTY");
1059: createSysErr(IErrno.ENOTDIR, "ENOTDIR");
1060: createSysErr(IErrno.EFAULT, "EFAULT");
1061: createSysErr(IErrno.EBADF, "EBADF");
1062: createSysErr(IErrno.EINTR, "EINTR");
1063: createSysErr(IErrno.EWOULDBLOCK, "EWOULDBLOCK");
1064: createSysErr(IErrno.EDEADLK, "EDEADLK");
1065: createSysErr(IErrno.EROFS, "EROFS");
1066: createSysErr(IErrno.EMFILE, "EMFILE");
1067: createSysErr(IErrno.ENODEV, "ENODEV");
1068: createSysErr(IErrno.EACCES, "EACCES");
1069: createSysErr(IErrno.ENOEXEC, "ENOEXEC");
1070: createSysErr(IErrno.ESRCH, "ESRCH");
1071: createSysErr(IErrno.ECONNREFUSED, "ECONNREFUSED");
1072: createSysErr(IErrno.ECONNRESET, "ECONNRESET");
1073: createSysErr(IErrno.EADDRINUSE, "EADDRINUSE");
1074: }
1075:
1076: /**
1077: * Creates a system error.
1078: * @param i the error code (will probably use a java exception instead)
1079: * @param name of the error to define.
1080: **/
1081: private void createSysErr(int i, String name) {
1082: if (profile.allowClass(name)) {
1083: errnoModule.defineClassUnder(name, systemCallError,
1084: systemCallError.getAllocator()).defineConstant(
1085: "Errno", newFixnum(i));
1086: }
1087: }
1088:
1089: /** Getter for property isVerbose.
1090: * @return Value of property isVerbose.
1091: */
1092: public IRubyObject getVerbose() {
1093: return verbose;
1094: }
1095:
1096: /** Setter for property isVerbose.
1097: * @param verbose New value of property isVerbose.
1098: */
1099: public void setVerbose(IRubyObject verbose) {
1100: this .verbose = verbose;
1101: }
1102:
1103: /** Getter for property isDebug.
1104: * @return Value of property isDebug.
1105: */
1106: public IRubyObject getDebug() {
1107: return debug;
1108: }
1109:
1110: /** Setter for property isDebug.
1111: * @param debug New value of property isDebug.
1112: */
1113: public void setDebug(IRubyObject debug) {
1114: this .debug = debug;
1115: }
1116:
1117: public JavaSupport getJavaSupport() {
1118: return javaSupport;
1119: }
1120:
1121: public JRubyClassLoader getJRubyClassLoader() {
1122: if (!Ruby.isSecurityRestricted() && jrubyClassLoader == null)
1123: jrubyClassLoader = new JRubyClassLoader(Thread
1124: .currentThread().getContextClassLoader());
1125: return jrubyClassLoader;
1126: }
1127:
1128: /** Defines a global variable
1129: */
1130: public void defineVariable(final GlobalVariable variable) {
1131: globalVariables.define(variable.name(), new IAccessor() {
1132: public IRubyObject getValue() {
1133: return variable.get();
1134: }
1135:
1136: public IRubyObject setValue(IRubyObject newValue) {
1137: return variable.set(newValue);
1138: }
1139: });
1140: }
1141:
1142: /** defines a readonly global variable
1143: *
1144: */
1145: public void defineReadonlyVariable(String name, IRubyObject value) {
1146: globalVariables.defineReadonly(name, new ValueAccessor(value));
1147: }
1148:
1149: public Node parse(Reader content, String file, DynamicScope scope,
1150: int lineNumber) {
1151: return parser.parse(file, content, scope, lineNumber);
1152: }
1153:
1154: public Node parse(String content, String file, DynamicScope scope,
1155: int lineNumber) {
1156: return parser.parse(file, content, scope, lineNumber);
1157: }
1158:
1159: public Node parse(String content, String file, DynamicScope scope,
1160: int lineNumber, boolean extraPositionInformation) {
1161: return parser.parse(file, content, scope, lineNumber,
1162: extraPositionInformation);
1163: }
1164:
1165: public ThreadService getThreadService() {
1166: return threadService;
1167: }
1168:
1169: public ThreadContext getCurrentContext() {
1170: return threadService.getCurrentContext();
1171: }
1172:
1173: /**
1174: * Returns the loadService.
1175: * @return ILoadService
1176: */
1177: public LoadService getLoadService() {
1178: return loadService;
1179: }
1180:
1181: public RubyWarnings getWarnings() {
1182: return warnings;
1183: }
1184:
1185: public PrintStream getErrorStream() {
1186: // FIXME: We can't guarantee this will always be a RubyIO...so the old code here is not safe
1187: /*java.io.OutputStream os = ((RubyIO) getGlobalVariables().get("$stderr")).getOutStream();
1188: if(null != os) {
1189: return new PrintStream(os);
1190: } else {
1191: return new PrintStream(new org.jruby.util.SwallowingOutputStream());
1192: }*/
1193: return new PrintStream(new IOOutputStream(getGlobalVariables()
1194: .get("$stderr")));
1195: }
1196:
1197: public InputStream getInputStream() {
1198: return new IOInputStream(getGlobalVariables().get("$stdin"));
1199: }
1200:
1201: public PrintStream getOutputStream() {
1202: return new PrintStream(new IOOutputStream(getGlobalVariables()
1203: .get("$stdout")));
1204: }
1205:
1206: public RubyModule getClassFromPath(String path) {
1207: RubyModule c = getObject();
1208: if (path.length() == 0 || path.charAt(0) == '#') {
1209: throw newTypeError("can't retrieve anonymous class " + path);
1210: }
1211: int pbeg = 0, p = 0;
1212: for (int l = path.length(); p < l;) {
1213: while (p < l && path.charAt(p) != ':') {
1214: p++;
1215: }
1216: String str = path.substring(pbeg, p);
1217:
1218: if (p < l && path.charAt(p) == ':') {
1219: if (p + 1 < l && path.charAt(p + 1) != ':') {
1220: throw newTypeError("undefined class/module "
1221: + path.substring(pbeg, p));
1222: }
1223: p += 2;
1224: pbeg = p;
1225: }
1226:
1227: IRubyObject cc = c.getConstant(str);
1228: if (!(cc instanceof RubyModule)) {
1229: throw newTypeError("" + str
1230: + " does not refer to class/module");
1231: }
1232: c = (RubyModule) cc;
1233: }
1234: return c;
1235: }
1236:
1237: /** Prints an error with backtrace to the error stream.
1238: *
1239: * MRI: eval.c - error_print()
1240: *
1241: */
1242: public void printError(RubyException excp) {
1243: if (excp == null || excp.isNil()) {
1244: return;
1245: }
1246:
1247: ThreadContext tc = getCurrentContext();
1248: IRubyObject backtrace = excp.callMethod(tc, "backtrace");
1249:
1250: PrintStream errorStream = getErrorStream();
1251: if (backtrace.isNil() || !(backtrace instanceof RubyArray)) {
1252: if (tc.getSourceFile() != null) {
1253: errorStream.print(tc.getPosition());
1254: } else {
1255: errorStream.print(tc.getSourceLine());
1256: }
1257: } else if (((RubyArray) backtrace).getLength() == 0) {
1258: printErrorPos(errorStream);
1259: } else {
1260: IRubyObject mesg = ((RubyArray) backtrace)
1261: .first(IRubyObject.NULL_ARRAY);
1262:
1263: if (mesg.isNil()) {
1264: printErrorPos(errorStream);
1265: } else {
1266: errorStream.print(mesg);
1267: }
1268: }
1269:
1270: RubyClass type = excp.getMetaClass();
1271: String info = excp.toString();
1272:
1273: if (type == getClass("RuntimeError")
1274: && (info == null || info.length() == 0)) {
1275: errorStream.print(": unhandled exception\n");
1276: } else {
1277: String path = type.getName();
1278:
1279: if (info.length() == 0) {
1280: errorStream.print(": " + path + '\n');
1281: } else {
1282: if (path.startsWith("#")) {
1283: path = null;
1284: }
1285:
1286: String tail = null;
1287: if (info.indexOf("\n") != -1) {
1288: tail = info.substring(info.indexOf("\n") + 1);
1289: info = info.substring(0, info.indexOf("\n"));
1290: }
1291:
1292: errorStream.print(": " + info);
1293:
1294: if (path != null) {
1295: errorStream.print(" (" + path + ")\n");
1296: }
1297:
1298: if (tail != null) {
1299: errorStream.print(tail + '\n');
1300: }
1301: }
1302: }
1303:
1304: excp.printBacktrace(errorStream);
1305: }
1306:
1307: private void printErrorPos(PrintStream errorStream) {
1308: ThreadContext tc = getCurrentContext();
1309: if (tc.getSourceFile() != null) {
1310: if (tc.getFrameName() != null) {
1311: errorStream.print(tc.getPosition());
1312: errorStream.print(":in '" + tc.getFrameName() + '\'');
1313: } else if (tc.getSourceLine() != 0) {
1314: errorStream.print(tc.getPosition());
1315: } else {
1316: errorStream.print(tc.getSourceFile());
1317: }
1318: }
1319: }
1320:
1321: /** This method compiles and interprets a Ruby script.
1322: *
1323: * It can be used if you want to use JRuby as a Macro language.
1324: *
1325: */
1326: public void loadScript(RubyString scriptName, RubyString source) {
1327: loadScript(scriptName.toString(), new StringReader(source
1328: .toString()));
1329: }
1330:
1331: public void loadScript(String scriptName, Reader source) {
1332: if (!Ruby.isSecurityRestricted()) {
1333: File f = new File(scriptName);
1334: if (f.exists() && !f.isAbsolute()
1335: && !scriptName.startsWith("./")) {
1336: scriptName = "./" + scriptName;
1337: }
1338: ;
1339: }
1340:
1341: IRubyObject self = getTopSelf();
1342: ThreadContext context = getCurrentContext();
1343:
1344: try {
1345: secure(4); /* should alter global state */
1346:
1347: context.preNodeEval(objectClass, self);
1348:
1349: Node node = parse(source, scriptName, null, 0);
1350: EvaluationState.eval(this , context, node, self,
1351: Block.NULL_BLOCK);
1352: } catch (JumpException je) {
1353: if (je.getJumpType() == JumpException.JumpType.ReturnJump) {
1354: // Make sure this does not bubble out to java caller.
1355: } else {
1356: throw je;
1357: }
1358: } finally {
1359: context.postNodeEval();
1360: }
1361: }
1362:
1363: public void loadScript(Script script) {
1364: IRubyObject self = getTopSelf();
1365: ThreadContext context = getCurrentContext();
1366:
1367: try {
1368: secure(4); /* should alter global state */
1369:
1370: context.preNodeEval(objectClass, self);
1371:
1372: script.run(context, self, IRubyObject.NULL_ARRAY,
1373: Block.NULL_BLOCK);
1374: } catch (JumpException je) {
1375: if (je.getJumpType() == JumpException.JumpType.ReturnJump) {
1376: // Make sure this does not bubble out to java caller.
1377: } else {
1378: throw je;
1379: }
1380: } finally {
1381: context.postNodeEval();
1382: }
1383: }
1384:
1385: public void loadNode(String scriptName, Node node) {
1386: IRubyObject self = getTopSelf();
1387: ThreadContext context = getCurrentContext();
1388:
1389: try {
1390: secure(4); /* should alter global state */
1391:
1392: context.preNodeEval(objectClass, self);
1393:
1394: EvaluationState.eval(this , context, node, self,
1395: Block.NULL_BLOCK);
1396: } catch (JumpException je) {
1397: if (je.getJumpType() == JumpException.JumpType.ReturnJump) {
1398: // Make sure this does not bubble out to java caller.
1399: } else {
1400: throw je;
1401: }
1402: } finally {
1403: context.postNodeEval();
1404: }
1405: }
1406:
1407: /** Loads, compiles and interprets a Ruby file.
1408: * Used by Kernel#require.
1409: *
1410: * @mri rb_load
1411: */
1412: public void loadFile(File file) {
1413: assert file != null : "No such file to load";
1414: BufferedReader source = null;
1415: try {
1416: source = new BufferedReader(new FileReader(file));
1417: loadScript(file.getPath().replace(File.separatorChar, '/'),
1418: source);
1419: } catch (IOException ioExcptn) {
1420: throw newIOErrorFromException(ioExcptn);
1421: } finally {
1422: try {
1423: if (source == null) {
1424: source.close();
1425: }
1426: } catch (IOException ioe) {
1427: }
1428: }
1429: }
1430:
1431: /** Call the trace function
1432: *
1433: * MRI: eval.c - call_trace_func
1434: *
1435: */
1436: // public void callTraceFunction(ThreadContext context, String event, ISourcePosition position,
1437: // RubyBinding binding, String name, IRubyObject type) {
1438: // if (traceFunction == null) return;
1439: //
1440: // if (!context.isWithinTrace()) {
1441: // context.setWithinTrace(true);
1442: //
1443: // ISourcePosition savePosition = context.getPosition();
1444: // String file = position.getFile();
1445: //
1446: // if (file == null) file = "(ruby)";
1447: // if (type == null) type = getFalse();
1448: //
1449: // context.preTrace();
1450: // try {
1451: // traceFunction.call(new IRubyObject[] {
1452: // newString(event), // event name
1453: // newString(file), // filename
1454: // newFixnum(position.getStartLine() + 1), // line numbers should be 1-based
1455: // name != null ? RubySymbol.newSymbol(this, name) : getNil(),
1456: // binding != null ? binding : getNil(),
1457: // type
1458: // });
1459: // } finally {
1460: // context.postTrace();
1461: // context.setPosition(savePosition);
1462: // context.setWithinTrace(false);
1463: // }
1464: // }
1465: // }
1466: public class CallTraceFuncHook implements EventHook {
1467: private RubyProc traceFunc;
1468:
1469: public void setTraceFunc(RubyProc traceFunc) {
1470: this .traceFunc = traceFunc;
1471: }
1472:
1473: public void event(ThreadContext context, int event,
1474: String file, int line, String name, IRubyObject type) {
1475: if (!context.isWithinTrace()) {
1476: if (file == null)
1477: file = "(ruby)";
1478: if (type == null)
1479: type = getFalse();
1480:
1481: RubyBinding binding = RubyBinding.newBinding(Ruby.this );
1482:
1483: context.preTrace();
1484: try {
1485: traceFunc.call(new IRubyObject[] {
1486: newString(EVENT_NAMES[event]), // event name
1487: newString(file), // filename
1488: newFixnum(line + 1), // line numbers should be 1-based
1489: name != null ? RubySymbol.newSymbol(
1490: Ruby.this , name) : getNil(),
1491: binding, type });
1492: } finally {
1493: context.postTrace();
1494: }
1495: }
1496: }
1497:
1498: public boolean isInterestedInEvent(int event) {
1499: return true;
1500: }
1501: };
1502:
1503: private final CallTraceFuncHook callTraceFuncHook = new CallTraceFuncHook();
1504:
1505: public void addEventHook(EventHook hook) {
1506: eventHooks.add(hook);
1507: }
1508:
1509: public void removeEventHook(EventHook hook) {
1510: eventHooks.remove(hook);
1511: }
1512:
1513: public void setTraceFunction(RubyProc traceFunction) {
1514: removeEventHook(callTraceFuncHook);
1515:
1516: if (traceFunction == null) {
1517: return;
1518: }
1519:
1520: callTraceFuncHook.setTraceFunc(traceFunction);
1521: addEventHook(callTraceFuncHook);
1522: }
1523:
1524: public void callEventHooks(ThreadContext context, int event,
1525: String file, int line, String name, IRubyObject type) {
1526: for (int i = 0; i < eventHooks.size(); i++) {
1527: EventHook eventHook = (EventHook) eventHooks.get(i);
1528: if (eventHook.isInterestedInEvent(event)) {
1529: eventHook.event(context, event, file, line, name, type);
1530: }
1531: }
1532: }
1533:
1534: public boolean hasEventHooks() {
1535: return !eventHooks.isEmpty();
1536: }
1537:
1538: public GlobalVariables getGlobalVariables() {
1539: return globalVariables;
1540: }
1541:
1542: // For JSR 223 support: see http://scripting.java.net/
1543: public void setGlobalVariables(GlobalVariables globalVariables) {
1544: this .globalVariables = globalVariables;
1545: }
1546:
1547: public CallbackFactory callbackFactory(Class type) {
1548: return CallbackFactory.createFactory(this , type);
1549: }
1550:
1551: /**
1552: * Push block onto exit stack. When runtime environment exits
1553: * these blocks will be evaluated.
1554: *
1555: * @return the element that was pushed onto stack
1556: */
1557: public IRubyObject pushExitBlock(RubyProc proc) {
1558: atExitBlocks.push(proc);
1559: return proc;
1560: }
1561:
1562: public void addFinalizer(Finalizable finalizer) {
1563: synchronized (this ) {
1564: if (finalizers == null) {
1565: finalizers = new WeakHashMap();
1566: }
1567: }
1568:
1569: synchronized (finalizers) {
1570: finalizers.put(finalizer, null);
1571: }
1572: }
1573:
1574: public void removeFinalizer(Finalizable finalizer) {
1575: if (finalizers != null) {
1576: synchronized (finalizers) {
1577: finalizers.remove(finalizer);
1578: }
1579: }
1580: }
1581:
1582: /**
1583: * Make sure Kernel#at_exit procs get invoked on runtime shutdown.
1584: * This method needs to be explicitly called to work properly.
1585: * I thought about using finalize(), but that did not work and I
1586: * am not sure the runtime will be at a state to run procs by the
1587: * time Ruby is going away. This method can contain any other
1588: * things that need to be cleaned up at shutdown.
1589: */
1590: public void tearDown() {
1591: while (!atExitBlocks.empty()) {
1592: RubyProc proc = (RubyProc) atExitBlocks.pop();
1593:
1594: proc.call(IRubyObject.NULL_ARRAY);
1595: }
1596: if (finalizers != null) {
1597: synchronized (finalizers) {
1598: for (Iterator finalIter = new ArrayList(finalizers
1599: .keySet()).iterator(); finalIter.hasNext();) {
1600: ((Finalizable) finalIter.next()).finalize();
1601: finalIter.remove();
1602: }
1603: }
1604: }
1605: }
1606:
1607: // new factory methods ------------------------------------------------------------------------
1608:
1609: public RubyArray newArray() {
1610: return RubyArray.newArray(this );
1611: }
1612:
1613: public RubyArray newArrayLight() {
1614: return RubyArray.newArrayLight(this );
1615: }
1616:
1617: public RubyArray newArray(IRubyObject object) {
1618: return RubyArray.newArray(this , object);
1619: }
1620:
1621: public RubyArray newArray(IRubyObject car, IRubyObject cdr) {
1622: return RubyArray.newArray(this , car, cdr);
1623: }
1624:
1625: public RubyArray newArray(IRubyObject[] objects) {
1626: return RubyArray.newArray(this , objects);
1627: }
1628:
1629: public RubyArray newArrayNoCopy(IRubyObject[] objects) {
1630: return RubyArray.newArrayNoCopy(this , objects);
1631: }
1632:
1633: public RubyArray newArrayNoCopyLight(IRubyObject[] objects) {
1634: return RubyArray.newArrayNoCopyLight(this , objects);
1635: }
1636:
1637: public RubyArray newArray(List list) {
1638: return RubyArray.newArray(this , list);
1639: }
1640:
1641: public RubyArray newArray(int size) {
1642: return RubyArray.newArray(this , size);
1643: }
1644:
1645: public RubyBoolean newBoolean(boolean value) {
1646: return RubyBoolean.newBoolean(this , value);
1647: }
1648:
1649: public RubyFileStat newRubyFileStat(String file) {
1650: return (RubyFileStat) getClass("File")
1651: .getClass("Stat")
1652: .callMethod(getCurrentContext(), "new", newString(file));
1653: }
1654:
1655: public RubyFixnum newFixnum(long value) {
1656: return RubyFixnum.newFixnum(this , value);
1657: }
1658:
1659: public RubyFloat newFloat(double value) {
1660: return RubyFloat.newFloat(this , value);
1661: }
1662:
1663: public RubyNumeric newNumeric() {
1664: return RubyNumeric.newNumeric(this );
1665: }
1666:
1667: public RubyProc newProc(boolean isLambda, Block block) {
1668: if (!isLambda && block.getProcObject() != null)
1669: return block.getProcObject();
1670:
1671: RubyProc proc = RubyProc.newProc(this , isLambda);
1672:
1673: proc.callInit(IRubyObject.NULL_ARRAY, block);
1674:
1675: return proc;
1676: }
1677:
1678: public RubyBinding newBinding() {
1679: return RubyBinding.newBinding(this );
1680: }
1681:
1682: public RubyBinding newBinding(Block block) {
1683: return RubyBinding.newBinding(this , block);
1684: }
1685:
1686: public RubyString newString() {
1687: return RubyString.newString(this , "");
1688: }
1689:
1690: public RubyString newString(String string) {
1691: return RubyString.newString(this , string);
1692: }
1693:
1694: public RubyString newString(ByteList byteList) {
1695: return RubyString.newString(this , byteList);
1696: }
1697:
1698: public RubyString newStringShared(ByteList byteList) {
1699: return RubyString.newStringShared(this , byteList);
1700: }
1701:
1702: public RubySymbol newSymbol(String string) {
1703: return RubySymbol.newSymbol(this , string);
1704: }
1705:
1706: public RubyTime newTime(long milliseconds) {
1707: return RubyTime.newTime(this , milliseconds);
1708: }
1709:
1710: public RaiseException newRuntimeError(String message) {
1711: return newRaiseException(getClass("RuntimeError"), message);
1712: }
1713:
1714: public RaiseException newArgumentError(String message) {
1715: return newRaiseException(getClass("ArgumentError"), message);
1716: }
1717:
1718: public RaiseException newArgumentError(int got, int expected) {
1719: return newRaiseException(getClass("ArgumentError"),
1720: "wrong # of arguments(" + got + " for " + expected
1721: + ")");
1722: }
1723:
1724: public RaiseException newErrnoEBADFError() {
1725: return newRaiseException(getModule("Errno").getClass("EBADF"),
1726: "Bad file descriptor");
1727: }
1728:
1729: public RaiseException newErrnoECONNREFUSEDError() {
1730: return newRaiseException(getModule("Errno").getClass(
1731: "ECONNREFUSED"), "Connection refused");
1732: }
1733:
1734: public RaiseException newErrnoEADDRINUSEError() {
1735: return newRaiseException(getModule("Errno").getClass(
1736: "EADDRINUSE"), "Address in use");
1737: }
1738:
1739: public RaiseException newErrnoEINVALError() {
1740: return newRaiseException(getModule("Errno").getClass("EINVAL"),
1741: "Invalid file");
1742: }
1743:
1744: public RaiseException newErrnoENOENTError() {
1745: return newRaiseException(getModule("Errno").getClass("ENOENT"),
1746: "File not found");
1747: }
1748:
1749: public RaiseException newErrnoESPIPEError() {
1750: return newRaiseException(getModule("Errno").getClass("ESPIPE"),
1751: "Illegal seek");
1752: }
1753:
1754: public RaiseException newErrnoEBADFError(String message) {
1755: return newRaiseException(getModule("Errno").getClass("EBADF"),
1756: message);
1757: }
1758:
1759: public RaiseException newErrnoEINVALError(String message) {
1760: return newRaiseException(getModule("Errno").getClass("EINVAL"),
1761: message);
1762: }
1763:
1764: public RaiseException newErrnoENOENTError(String message) {
1765: return newRaiseException(getModule("Errno").getClass("ENOENT"),
1766: message);
1767: }
1768:
1769: public RaiseException newErrnoESPIPEError(String message) {
1770: return newRaiseException(getModule("Errno").getClass("ESPIPE"),
1771: message);
1772: }
1773:
1774: public RaiseException newErrnoEEXISTError(String message) {
1775: return newRaiseException(getModule("Errno").getClass("EEXIST"),
1776: message);
1777: }
1778:
1779: public RaiseException newErrnoEDOMError(String message) {
1780: return newRaiseException(getModule("Errno").getClass("EDOM"),
1781: "Domain error - " + message);
1782: }
1783:
1784: public RaiseException newIndexError(String message) {
1785: return newRaiseException(getClass("IndexError"), message);
1786: }
1787:
1788: public RaiseException newSecurityError(String message) {
1789: return newRaiseException(getClass("SecurityError"), message);
1790: }
1791:
1792: public RaiseException newSystemCallError(String message) {
1793: return newRaiseException(getClass("SystemCallError"), message);
1794: }
1795:
1796: public RaiseException newTypeError(String message) {
1797: return newRaiseException(getClass("TypeError"), message);
1798: }
1799:
1800: public RaiseException newThreadError(String message) {
1801: return newRaiseException(getClass("ThreadError"), message);
1802: }
1803:
1804: public RaiseException newSyntaxError(String message) {
1805: return newRaiseException(getClass("SyntaxError"), message);
1806: }
1807:
1808: public RaiseException newRegexpError(String message) {
1809: return newRaiseException(getClass("RegexpError"), message);
1810: }
1811:
1812: public RaiseException newRangeError(String message) {
1813: return newRaiseException(getClass("RangeError"), message);
1814: }
1815:
1816: public RaiseException newNotImplementedError(String message) {
1817: return newRaiseException(getClass("NotImplementedError"),
1818: message);
1819: }
1820:
1821: public RaiseException newInvalidEncoding(String message) {
1822: return newRaiseException(getClass("Iconv").getClass(
1823: "InvalidEncoding"), message);
1824: }
1825:
1826: public RaiseException newNoMethodError(String message, String name,
1827: IRubyObject args) {
1828: return new RaiseException(new RubyNoMethodError(this , this
1829: .getClass("NoMethodError"), message, name, args), true);
1830: }
1831:
1832: public RaiseException newNameError(String message, String name) {
1833: return new RaiseException(new RubyNameError(this , this
1834: .getClass("NameError"), message, name), true);
1835: }
1836:
1837: public RaiseException newLocalJumpError(String reason,
1838: IRubyObject exitValue, String message) {
1839: return new RaiseException(
1840: new RubyLocalJumpError(this ,
1841: getClass("LocalJumpError"), message, reason,
1842: exitValue), true);
1843: }
1844:
1845: public RaiseException newLoadError(String message) {
1846: return newRaiseException(getClass("LoadError"), message);
1847: }
1848:
1849: public RaiseException newFrozenError(String objectType) {
1850: // TODO: Should frozen error have its own distinct class? If not should more share?
1851: return newRaiseException(getClass("TypeError"),
1852: "can't modify frozen " + objectType);
1853: }
1854:
1855: public RaiseException newSystemStackError(String message) {
1856: return newRaiseException(getClass("SystemStackError"), message);
1857: }
1858:
1859: public RaiseException newSystemExit(int status) {
1860: RubyClass exc = getClass("SystemExit");
1861: IRubyObject[] exArgs = new IRubyObject[] { newFixnum(status),
1862: newString("exit") };
1863: return new RaiseException((RubyException) exc.newInstance(
1864: exArgs, Block.NULL_BLOCK));
1865: }
1866:
1867: public RaiseException newIOError(String message) {
1868: return newRaiseException(getClass("IOError"), message);
1869: }
1870:
1871: public RaiseException newStandardError(String message) {
1872: return newRaiseException(getClass("StandardError"), message);
1873: }
1874:
1875: public RaiseException newIOErrorFromException(IOException ioe) {
1876: return newRaiseException(getClass("IOError"), ioe.getMessage());
1877: }
1878:
1879: public RaiseException newTypeError(IRubyObject receivedObject,
1880: RubyClass expectedType) {
1881: return newRaiseException(getClass("TypeError"),
1882: "wrong argument type " + receivedObject.getMetaClass()
1883: + " (expected " + expectedType + ")");
1884: }
1885:
1886: public RaiseException newEOFError() {
1887: return newRaiseException(getClass("EOFError"),
1888: "End of file reached");
1889: }
1890:
1891: public RaiseException newZeroDivisionError() {
1892: return newRaiseException(getClass("ZeroDivisionError"),
1893: "divided by 0");
1894: }
1895:
1896: public RaiseException newFloatDomainError(String message) {
1897: return newRaiseException(getClass("FloatDomainError"), message);
1898: }
1899:
1900: /**
1901: * @param exceptionClass
1902: * @param message
1903: * @return
1904: */
1905: private RaiseException newRaiseException(RubyClass exceptionClass,
1906: String message) {
1907: RaiseException re = new RaiseException(this , exceptionClass,
1908: message, true);
1909: return re;
1910: }
1911:
1912: public RubySymbol.SymbolTable getSymbolTable() {
1913: return symbolTable;
1914: }
1915:
1916: public void setStackTraces(int stackTraces) {
1917: this .stackTraces = stackTraces;
1918: }
1919:
1920: public int getStackTraces() {
1921: return stackTraces;
1922: }
1923:
1924: public void setRandomSeed(long randomSeed) {
1925: this .randomSeed = randomSeed;
1926: }
1927:
1928: public long getRandomSeed() {
1929: return randomSeed;
1930: }
1931:
1932: public Random getRandom() {
1933: return random;
1934: }
1935:
1936: public ObjectSpace getObjectSpace() {
1937: return objectSpace;
1938: }
1939:
1940: public Hashtable getIoHandlers() {
1941: return ioHandlers;
1942: }
1943:
1944: public RubyFixnum[] getFixnumCache() {
1945: return fixnumCache;
1946: }
1947:
1948: public long incrementRandomSeedSequence() {
1949: return randomSeedSequence++;
1950: }
1951:
1952: public InputStream getIn() {
1953: return in;
1954: }
1955:
1956: public PrintStream getOut() {
1957: return out;
1958: }
1959:
1960: public PrintStream getErr() {
1961: return err;
1962: }
1963:
1964: public boolean isGlobalAbortOnExceptionEnabled() {
1965: return globalAbortOnExceptionEnabled;
1966: }
1967:
1968: public void setGlobalAbortOnExceptionEnabled(boolean enable) {
1969: globalAbortOnExceptionEnabled = enable;
1970: }
1971:
1972: public boolean isDoNotReverseLookupEnabled() {
1973: return doNotReverseLookupEnabled;
1974: }
1975:
1976: public void setDoNotReverseLookupEnabled(boolean b) {
1977: doNotReverseLookupEnabled = b;
1978: }
1979:
1980: private ThreadLocal inspect = new ThreadLocal();
1981:
1982: public boolean registerInspecting(Object obj) {
1983: java.util.Map val = (java.util.Map) inspect.get();
1984: if (null == val) {
1985: val = new java.util.IdentityHashMap();
1986: inspect.set(val);
1987: }
1988: if (val.containsKey(obj)) {
1989: return false;
1990: }
1991: val.put(obj, null);
1992: return true;
1993: }
1994:
1995: public void unregisterInspecting(Object obj) {
1996: java.util.Map val = (java.util.Map) inspect.get();
1997: val.remove(obj);
1998: }
1999:
2000: public boolean isObjectSpaceEnabled() {
2001: return objectSpaceEnabled;
2002: }
2003:
2004: public long getStartTime() {
2005: return startTime;
2006: }
2007:
2008: public Profile getProfile() {
2009: return profile;
2010: }
2011:
2012: public String getJRubyHome() {
2013: if (jrubyHome == null) {
2014: jrubyHome = verifyHome(System.getProperty("jruby.home",
2015: System.getProperty("user.home") + "/.jruby"));
2016: }
2017:
2018: try {
2019: // This comment also in rbConfigLibrary
2020: // Our shell scripts pass in non-canonicalized paths, but even if we didn't
2021: // anyone who did would become unhappy because Ruby apps expect no relative
2022: // operators in the pathname (rubygems, for example).
2023: return new NormalizedFile(jrubyHome).getCanonicalPath();
2024: } catch (IOException e) {
2025: }
2026:
2027: return new NormalizedFile(jrubyHome).getAbsolutePath();
2028: }
2029:
2030: public void setJRubyHome(String home) {
2031: jrubyHome = verifyHome(home);
2032: }
2033:
2034: // We require the home directory to be absolute
2035: private String verifyHome(String home) {
2036: if (home.equals(".")) {
2037: home = System.getProperty("user.dir");
2038: }
2039: NormalizedFile f = new NormalizedFile(home);
2040: if (!f.isAbsolute()) {
2041: home = f.getAbsolutePath();
2042: }
2043: f.mkdirs();
2044: return home;
2045: }
2046:
2047: public RubyInstanceConfig getInstanceConfig() {
2048: return config;
2049: }
2050:
2051: /** GET_VM_STATE_VERSION */
2052: public long getGlobalState() {
2053: synchronized (this ) {
2054: return globalState;
2055: }
2056: }
2057:
2058: /** INC_VM_STATE_VERSION */
2059: public void incGlobalState() {
2060: synchronized (this ) {
2061: globalState = (globalState + 1) & 0x8fffffff;
2062: }
2063: }
2064:
2065: public static boolean isSecurityRestricted() {
2066: return securityRestricted;
2067: }
2068:
2069: public static void setSecurityRestricted(boolean restricted) {
2070: securityRestricted = restricted;
2071: }
2072: }
|