package org.jruby; public enum CompatVersion { RUBY1_8, RUBY1_9, BOTH; public static CompatVersion getVersionFromString(String compatString) { if (compatString.equalsIgnoreCase("RUBY1_8")) { return CompatVersion.RUBY1_8; } else if (compatString.equalsIgnoreCase("RUBY1_9")) { return CompatVersion.RUBY1_9; } else { return null; } } } /***** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2007 Damian Steer * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; /** * An almost entirely useless interface for those objects that we _really_ want * to finalise. * * @author pldms * */ public interface Finalizable { public void finalize(); } /***** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2002 Benoit Cerrina * Copyright (C) 2002 Jan Arne Petersen * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; /** * Error numbers. * @fixme * this interface is a big hack defining a bunch of arbitrary valor as system call error numbers * this is actually because I need them but will probably need to be changed to something smarter * sooner or later. * The purpose of this class it to help implement the Errno module which in turn in needed by rubicon. * @author Benoit Cerrina **/ public interface IErrno { int EPERM = 1; int ENOENT = 2; int ESRCH = 3; int EINTR = 4; int EIO = 5; int ENXIO = 6; int E2BIG = 7; int ENOEXEC = 8; int EBADF = 9; int ECHILD = 10; int EDEADLK = 11; int ENOMEM = 12; int EACCES = 13; int EFAULT = 14; int ENOTBLK = 15; int EBUSY = 16; int EEXIST = 17; int EXDEV = 18; int ENODEV = 19; int ENOTDIR = 20; int EISDIR = 21; int EINVAL = 22; int ENFILE = 23; int EMFILE = 24; int ENOTTY = 25; int ETXTBSY = 26; int EFBIG = 27; int ENOSPC = 28; int ESPIPE = 29; int EROFS = 30; int EMLINK = 31; int EPIPE = 32; int EDOM = 33; int ERANGE = 34; int EWOULDBLOCK = 35; int EAGAIN = 35; int EINPROGRESS = 36; int EALREADY = 37; int ENOTSOCK = 38; int EDESTADDRREQ = 39; int EMSGSIZE = 40; int EPROTOTYPE = 41; int ENOPROTOOPT = 42; int EPROTONOSUPPORT = 43; int ESOCKTNOSUPPORT = 44; int EOPNOTSUPP = 45; int EPFNOSUPPORT = 46; int EAFNOSUPPORT = 47; int EADDRINUSE = 48; int EADDRNOTAVAIL = 49; int ENETDOWN = 50; int ENETUNREACH = 51; int ENETRESET = 52; int ECONNABORTED = 53; int ECONNRESET = 54; int ENOBUFS = 55; int EISCONN = 56; int ENOTCONN = 57; int ESHUTDOWN = 58; int ETOOMANYREFS = 59; int ETIMEDOUT = 60; int ECONNREFUSED = 61; int ELOOP = 62; int ENAMETOOLONG = 63; int EHOSTDOWN = 64; int EHOSTUNREACH = 65; int ENOTEMPTY = 66; int EUSERS = 68; int EDQUOT = 69; int ESTALE = 70; int EREMOTE = 71; int ENOLCK = 77; int ENOSYS = 78; int EOVERFLOW = 84; int EIDRM = 90; int ENOMSG = 91; int EILSEQ = 92; int EBADMSG = 94; int EMULTIHOP = 95; int ENODATA = 96; int ENOLINK = 97; int ENOSR = 98; int ENOSTR = 99; int EPROTO = 100; int ETIME = 101; int EOPNOTSUPP_DARWIN = 102; } /* ***** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2002-2004 Jan Arne Petersen * Copyright (C) 2004-2006 Thomas E Enebo * Copyright (C) 2005 Charles O Nutter * Copyright (C) 2006 Miguel Covarrubias * Copyright (C) 2007 William N Dortch * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; import java.util.List; import java.util.Map; import org.jruby.internal.runtime.methods.DynamicMethod; import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.builtin.Variable; /** * This class is used to provide an intermediate superclass for modules and classes that include * other modules. It inserts itself as the immediate superClass of the includer, but defers all * module methods to the actual superclass. Multiple of these intermediate superclasses can be * added for multiple included modules. * * This allows the normal superclass-based searches (searchMethod, getConstant, etc) to traverse * the superclass ancestors as normal while the included modules do not actually show up in * direct inheritance traversal. * * @see org.jruby.RubyModule */ public final class IncludedModuleWrapper extends RubyClass { private final RubyModule delegate; public IncludedModuleWrapper(Ruby runtime, RubyClass superClass, RubyModule delegate) { super(runtime, superClass, false); this.delegate = delegate; this.metaClass = delegate.metaClass; } /** * Overridden newIncludeClass implementation to allow attaching future includes to the correct module * (i.e. the one to which this is attached) * * @see org.jruby.RubyModule#newIncludeClass(RubyClass) */ @Override public IncludedModuleWrapper newIncludeClass(RubyClass superClass) { IncludedModuleWrapper includedModule = new IncludedModuleWrapper(getRuntime(), superClass, getNonIncludedClass()); // include its parent (and in turn that module's parents) if (getSuperClass() != null) { includedModule.includeModule(getSuperClass()); } return includedModule; } @Override public boolean isModule() { return false; } @Override public boolean isClass() { return false; } @Override public boolean isIncluded() { return true; } @Override public boolean isImmediate() { return true; } @Override public void setMetaClass(RubyClass newRubyClass) { throw new UnsupportedOperationException("An included class is only a wrapper for a module"); } @Override public Map getMethods() { return delegate.getMethods(); } @Override public void addMethod(String name, DynamicMethod method) { throw new UnsupportedOperationException("An included class is only a wrapper for a module"); } public void setMethods(Map newMethods) { throw new UnsupportedOperationException("An included class is only a wrapper for a module"); } @Override public String getName() { return delegate.getName(); } @Override public RubyModule getNonIncludedClass() { return delegate; } @Override public RubyClass getRealClass() { return getSuperClass().getRealClass(); } @Override protected boolean isSame(RubyModule module) { return delegate.isSame(module); } /** * We don't want to reveal ourselves to Ruby code, so delegate this * operation. */ @Override public IRubyObject id() { return delegate.id(); } // // VARIABLE TABLE METHODS - pass to delegate // @Override protected boolean variableTableContains(String name) { return delegate.variableTableContains(name); } @Override protected boolean variableTableFastContains(String internedName) { return delegate.variableTableFastContains(internedName); } @Override protected IRubyObject variableTableFetch(String name) { return delegate.variableTableFetch(name); } @Override protected IRubyObject variableTableFastFetch(String internedName) { return delegate.variableTableFastFetch(internedName); } @Override protected IRubyObject variableTableStore(String name, IRubyObject value) { return delegate.variableTableStore(name, value); } @Override protected IRubyObject variableTableFastStore(String internedName, IRubyObject value) { return delegate.variableTableFastStore(internedName, value); } @Override protected IRubyObject variableTableRemove(String name) { return delegate.variableTableRemove(name); } @Override protected VariableTableEntry[] variableTableGetTable() { return delegate.variableTableGetTable(); } @Override protected int variableTableGetSize() { return delegate.variableTableGetSize(); } @Override protected void variableTableSync(List> vars) { delegate.variableTableSync(vars); } @Override protected IRubyObject variableTableReadLocked(VariableTableEntry entry) { return delegate.variableTableReadLocked(entry); } /** * Method to help ease transition to new variables implementation. * Will likely be deprecated in the near future. */ @SuppressWarnings("unchecked") @Override @Deprecated // born deprecated protected Map variableTableGetMap() { return delegate.variableTableGetMap(); } /** * Method to help ease transition to new variables implementation. * Will likely be deprecated in the near future. */ @SuppressWarnings("unchecked") @Override @Deprecated // born deprecated protected Map variableTableGetMap(Map map) { return delegate.variableTableGetMap(map); } // // CONSTANT TABLE METHODS - pass to delegate // @Override protected boolean constantTableContains(String name) { return delegate.constantTableContains(name); } @Override protected boolean constantTableFastContains(String internedName) { return delegate.constantTableFastContains(internedName); } @Override protected IRubyObject constantTableFetch(String name) { return delegate.constantTableFetch(name); } @Override protected IRubyObject constantTableFastFetch(String internedName) { return delegate.constantTableFastFetch(internedName); } @Override protected IRubyObject constantTableStore(String name, IRubyObject value) { // FIXME: legal here? may want UnsupportedOperationException return delegate.constantTableStore(name, value); } @Override protected IRubyObject constantTableFastStore(String internedName, IRubyObject value) { // FIXME: legal here? may want UnsupportedOperationException return delegate.constantTableFastStore(internedName, value); } @Override protected IRubyObject constantTableRemove(String name) { // this _is_ legal (when removing an undef) return delegate.constantTableRemove(name); } @Override protected ConstantTableEntry[] constantTableGetTable() { return delegate.constantTableGetTable(); } @Override protected int constantTableGetSize() { return delegate.constantTableGetSize(); } @Override protected void constantTableSync(List> vars) { // FIXME: legal here? may want UnsupportedOperationException delegate.constantTableSync(vars); } /** * Method to help ease transition to new variables implementation. * Will likely be deprecated in the near future. */ @SuppressWarnings("unchecked") @Override @Deprecated // born deprecated protected Map constantTableGetMap() { return delegate.constantTableGetMap(); } /** * Method to help ease transition to new variables implementation. * Will likely be deprecated in the near future. */ @SuppressWarnings("unchecked") @Override @Deprecated // born deprecated protected Map constantTableGetMap(Map map) { return delegate.constantTableGetMap(map); } } /***** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2007 Charles Nutter * Copyright (C) 2008 MenTaLguY * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.EventQueue; import java.awt.Font; import java.awt.Insets; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.image.VolatileImage; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.net.URL; import java.util.Arrays; import java.lang.reflect.InvocationTargetException; import org.jruby.anno.JRubyMethod; import org.jruby.demo.TextAreaReadline; import org.jruby.javasupport.JavaUtil; import org.jruby.runtime.Block; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; import javax.swing.JScrollPane; import javax.swing.JTextPane; /** * @author MenTaLguY * * The JRubyApplet class provides a simple way to write Java applets using * JRuby without needing to create a custom Java applet class. At applet * initialization time, JRubyApplet starts up a JRuby runtime, then evaluates * the scriptlet given as the "eval" applet parameter. * * The Java applet instance is available to the Ruby script as * JRUBY_APPLET; the script can define callbacks for applet start, stop, * and destroy by passing blocks to JRUBY_APPLET.on_start, * JRUBY_APPLET.on_stop, and JRUBY_APPLET.on_destroy, respectively. * * Ruby code can install a custom paint callback using JRUBY_APPLET.on_paint * (the Graphics2D object is passed as an argument to the callback). By * default, JRubyApplet painting is double-buffered, but you can select * single-buffered painting via JRUBY_APPLET.double_buffered = false. * * The applet's background color can be set via JRUBY_APPLET.background_color=. * You may want to set it to nil if you're not using double-buffering, so that * no background color will be drawn (your own paint code is then responsible * for filling the area). * * Beyond these things, you should be able to use JRuby's Java integration * to do whatever you would do in Java with the applet instance. * */ public class JRubyApplet extends Applet { private Ruby runtime; private boolean doubleBuffered = true; private Color backgroundColor = Color.WHITE; private RubyProc startProc; private RubyProc stopProc; private RubyProc destroyProc; private RubyProc paintProc; private Graphics priorGraphics; private IRubyObject wrappedGraphics; private VolatileImage backBuffer; private Graphics backBufferGraphics; private Facade facade; private interface Facade { public InputStream getInputStream(); public PrintStream getOutputStream(); public PrintStream getErrorStream(); public void attach(Ruby runtime, Applet applet); public void destroy(); } private static RubyProc blockToProc(Ruby runtime, Block block) { if (block.isGiven()) { RubyProc proc = block.getProcObject(); if (proc == null) { proc = RubyProc.newProc(runtime, block, block.type); } return proc; } else { return null; } } private boolean getBooleanParameter(String name, boolean defaultValue) { String value = getParameter(name); if ( value != null ) { return value.equals("true"); } else { return defaultValue; } } private InputStream getCodeResourceAsStream(String name) { if (name == null) { return null; } try { final URL directURL = new URL(getCodeBase(), name); return directURL.openStream(); } catch (IOException e) { } return JRubyApplet.class.getClassLoader().getResourceAsStream(name); } private static void safeInvokeAndWait(Runnable runnable) throws InvocationTargetException, InterruptedException { if (EventQueue.isDispatchThread()) { try { runnable.run(); } catch (Exception e) { throw new InvocationTargetException(e); } } else { EventQueue.invokeAndWait(runnable); } } public static class RubyMethods { @JRubyMethod public static IRubyObject on_start(IRubyObject recv, Block block) { JRubyApplet applet = (JRubyApplet)recv.dataGetStruct(); synchronized (applet) { applet.startProc = blockToProc(applet.runtime, block); } return recv; } @JRubyMethod public static IRubyObject on_stop(IRubyObject recv, Block block) { JRubyApplet applet = (JRubyApplet)recv.dataGetStruct(); synchronized (applet) { applet.stopProc = blockToProc(applet.runtime, block); } return recv; } @JRubyMethod public static IRubyObject on_destroy(IRubyObject recv, Block block) { JRubyApplet applet = (JRubyApplet)recv.dataGetStruct(); synchronized (applet) { applet.destroyProc = blockToProc(applet.runtime, block); } return recv; } @JRubyMethod public static IRubyObject on_paint(IRubyObject recv, Block block) { JRubyApplet applet = (JRubyApplet)recv.dataGetStruct(); synchronized (applet) { applet.paintProc = blockToProc(applet.runtime, block); applet.repaint(); } return recv; } } @Override public void init() { super.init(); if (getBooleanParameter("jruby.console", false)) { facade = new ConsoleFacade(getParameter("jruby.banner")); } else { facade = new TrivialFacade(); } synchronized (this) { if (runtime != null) { return; } final RubyInstanceConfig config = new RubyInstanceConfig() {{ setInput(facade.getInputStream()); setOutput(facade.getOutputStream()); setError(facade.getErrorStream()); setObjectSpaceEnabled(getBooleanParameter("jruby.objectspace", false)); }}; Ruby.setSecurityRestricted(true); runtime = Ruby.newInstance(config); } final String scriptName = getParameter("jruby.script"); final InputStream scriptStream = getCodeResourceAsStream(scriptName); final String evalString = getParameter("jruby.eval"); try { final JRubyApplet applet = this; safeInvokeAndWait(new Runnable() { public void run() { applet.setLayout(new BorderLayout()); applet.facade.attach(applet.runtime, applet); if (scriptStream != null) { applet.runtime.runFromMain(scriptStream, scriptName); } if (evalString != null) { applet.runtime.evalScriptlet(evalString); } } }); } catch (InterruptedException e) { } catch (InvocationTargetException e) { throw new RuntimeException("Error running script", e.getCause()); } } private void invokeCallback(final RubyProc proc, final IRubyObject[] args) { if (proc == null) { return; } final Ruby runtime = this.runtime; try { safeInvokeAndWait(new Runnable() { public void run() { ThreadContext context = runtime.getCurrentContext(); proc.call(context, args); } }); } catch (InterruptedException e) { } catch (InvocationTargetException e) { throw new RuntimeException("Ruby callback failed", e.getCause()); } } public synchronized void setBackgroundColor(Color color) { backgroundColor = color; repaint(); } public synchronized Color getBackgroundColor() { return backgroundColor; } public synchronized boolean isDoubleBuffered() { return doubleBuffered; } public synchronized void setDoubleBuffered(boolean shouldBuffer) { doubleBuffered = shouldBuffer; repaint(); } @Override public synchronized void start() { super.start(); invokeCallback(startProc, new IRubyObject[] {}); } @Override public synchronized void stop() { invokeCallback(stopProc, new IRubyObject[] {}); super.stop(); } @Override public synchronized void destroy() { try { invokeCallback(destroyProc, new IRubyObject[] {}); } finally { facade.destroy(); final Ruby runtime = this.runtime; this.runtime = null; startProc = null; stopProc = null; destroyProc = null; paintProc = null; priorGraphics = null; wrappedGraphics = null; runtime.tearDown(); super.destroy(); } } @Override public void update(Graphics g) { paint(g); } @Override public synchronized void paint(Graphics g) { if (doubleBuffered) { paintBuffered(g); } else { paintUnbuffered(g); } } private synchronized void paintBuffered(Graphics g) { do { GraphicsConfiguration config = getGraphicsConfiguration(); int width = getWidth(); int height = getHeight(); if (backBuffer == null || width != backBuffer.getWidth() || height != backBuffer.getHeight() || backBuffer.validate(config) == VolatileImage.IMAGE_INCOMPATIBLE) { if (backBuffer != null) { backBufferGraphics.dispose(); backBufferGraphics = null; backBuffer.flush(); backBuffer = null; } backBuffer = config.createCompatibleVolatileImage(width, height); backBufferGraphics = backBuffer.createGraphics(); } backBufferGraphics.setClip(g.getClip()); paintUnbuffered(backBufferGraphics); g.drawImage(backBuffer, 0, 0, this); } while (backBuffer.contentsLost()); } private synchronized void paintUnbuffered(Graphics g) { if (backgroundColor != null) { g.setColor(backgroundColor); g.fillRect(0, 0, getWidth(), getHeight()); } if (paintProc != null) { if (priorGraphics != g) { wrappedGraphics = JavaUtil.convertJavaToUsableRubyObject(runtime, g); priorGraphics = g; } ThreadContext context = runtime.getCurrentContext(); paintProc.call(context, new IRubyObject[] {wrappedGraphics}); } super.paint(g); } private static class TrivialFacade implements Facade { public TrivialFacade() {} public InputStream getInputStream() { return System.in; } public PrintStream getOutputStream() { return System.out; } public PrintStream getErrorStream() { return System.err; } public void attach(Ruby runtime, Applet applet) { final IRubyObject wrappedApplet = JavaUtil.convertJavaToUsableRubyObject(runtime, applet); wrappedApplet.dataWrapStruct(applet); runtime.defineGlobalConstant("JRUBY_APPLET", wrappedApplet); wrappedApplet.getMetaClass().defineAnnotatedMethods(RubyMethods.class); } public void destroy() {} } private static class ConsoleFacade implements Facade { private JTextPane textPane; private JScrollPane scrollPane; private TextAreaReadline adaptor; private InputStream inputStream; private PrintStream outputStream; private PrintStream errorStream; public ConsoleFacade(String bannerText) { textPane = new JTextPane(); textPane.setMargin(new Insets(4, 4, 0, 4)); textPane.setCaretColor(new Color(0xa4, 0x00, 0x00)); textPane.setBackground(new Color(0xf2, 0xf2, 0xf2)); textPane.setForeground(new Color(0xa4, 0x00, 0x00)); Font font = findFont("Monospaced", Font.PLAIN, 14, new String[] {"Monaco", "Andale Mono"}); textPane.setFont(font); scrollPane = new JScrollPane(textPane); scrollPane.setDoubleBuffered(true); if ( bannerText != null ) { bannerText = " " + bannerText + " \n\n"; } adaptor = new TextAreaReadline(textPane, bannerText); inputStream = adaptor.getInputStream(); outputStream = new PrintStream(adaptor.getOutputStream()); errorStream = new PrintStream(adaptor.getOutputStream()); } public InputStream getInputStream() { return inputStream; } public PrintStream getOutputStream() { return outputStream; } public PrintStream getErrorStream() { return errorStream; } public void attach(Ruby runtime, Applet applet) { adaptor.hookIntoRuntime(runtime); applet.add(scrollPane); applet.validate(); } public void destroy() { Container parent = scrollPane.getParent(); adaptor.shutdown(); if (parent != null) { parent.remove(scrollPane); } } private Font findFont(String otherwise, int style, int size, String[] families) { String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); Arrays.sort(fonts); for (int i = 0; i < families.length; i++) { if (Arrays.binarySearch(fonts, families[i]) >= 0) { return new Font(families[i], style, size); } } return new Font(otherwise, style, size); } } } /***** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2007 Ola Bini * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; import java.io.BufferedWriter; import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.Socket; /** * @author Ola Bini */ public class JRubyClient extends JRubyService { public JRubyClient(String[] args) throws Exception { Configuration conf = new Configuration(args[0]); if(conf.isDebug()) { System.err.println("Starting client with port " + conf.getPort() + ", key " + conf.getKey() + " and command " + conf.getCommand()); } Socket socket = new Socket(InetAddress.getLocalHost(), conf.getPort()); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); if(conf.terminate()) { writer.write(CMD_TERM + " " + conf.getKey() + "\n"); } else if(conf.noMore()) { writer.write(CMD_NO_MORE + " " + conf.getKey() + "\n"); } else { writer.write(CMD_START + " " + conf.getKey() + " " + conf.getCommand() + "\n"); } writer.flush(); writer.close(); socket.close(); } public static void main(String[] args) throws Exception { new JRubyClient(args); } }// JRubyClient /* ***** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2007 Ola Bini * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.List; import java.util.ArrayList; /** * @author Ola Bini */ public class JRubyServer extends JRubyService { private Configuration conf; private boolean stillStarting = true; private JRubyServer(String[] args) throws Exception { conf = new Configuration(args[0]); if(conf.isDebug()) { System.err.println("Starting server with port " + conf.getPort() + " and key " + conf.getKey()); } ServerSocket server = new ServerSocket(); server.bind(new InetSocketAddress(InetAddress.getLocalHost(),conf.getPort())); while(true) { Thread t1 = new Thread(new Handler(server.accept())); t1.setDaemon(true); t1.start(); } } private class Handler implements Runnable { private Socket socket; public Handler(Socket socket) { this.socket = socket; } public void run() { try { BufferedReader rr = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); String command = rr.readLine(); rr.close(); this.socket.close(); this.socket = null; if(conf.isDebug()) { System.err.println("Got command: " + command); } String[] cmds = command.split(" ", 3); if(cmds[1].equals(conf.getKey())) { if(cmds[0].equals(CMD_TERM)) { if(conf.isDebug()) { System.err.println("Terminating hard"); } System.exit(0); } else if(cmds[0].equals(CMD_NO_MORE)) { if(conf.isDebug()) { System.err.println("Accepting no more START"); } stillStarting = false; } else if(cmds[0].equals(CMD_START)) { if(stillStarting) { if(conf.isDebug()) { System.err.println("Doing START on command " + cmds[2]); } new Main().run(intoCommandArguments(cmds[2].trim())); } else { if(conf.isDebug()) { System.err.println("Not doing START anymore, invalid command"); } } } else { if(conf.isDebug()) { System.err.println("Unrecognized command"); } } } else { if(conf.isDebug()) { System.err.println("Invalid key"); } } } catch(Exception e) {} } } protected static String[] intoCommandArguments(String str) { List args = new ArrayList(); boolean inSingle = false; int contentStart = -1; for(int i=0,j=str.length();i * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; /** * @author Ola Bini */ public abstract class JRubyService { protected static class Configuration { private final static int DEFAULT_PORT = 19222; private String key; private int port = DEFAULT_PORT; private boolean terminate; private boolean noMore; private boolean debug; private String command; public Configuration(String args) { int i=0; int stop; loop: for(int j=args.length();i * Copyright (C) 2001-2002 Benoit Cerrina * Copyright (C) 2001-2004 Jan Arne Petersen * Copyright (C) 2002-2004 Anders Bengtsson * Copyright (C) 2004 Thomas E Enebo * Copyright (C) 2004-2006 Charles O Nutter * Copyright (C) 2004 Stefan Matthias Aust * Copyright (C) 2005 Kiel Hodges * Copyright (C) 2005 Jason Voegele * Copyright (C) 2005 Tim Azzopardi * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; import java.io.InputStream; import java.io.PrintStream; import org.jruby.exceptions.MainExitException; import org.jruby.exceptions.RaiseException; import org.jruby.exceptions.ThreadKill; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; import org.jruby.util.SafePropertyAccessor; import org.jruby.util.SimpleSampler; /** * Class used to launch the interpreter. * This is the main class as defined in the jruby.mf manifest. * It is very basic and does not support yet the same array of switches * as the C interpreter. * Usage: java -jar jruby.jar [switches] [rubyfile.rb] [arguments] * -e 'command' one line of script. Several -e's allowed. Omit [programfile] * @author jpetersen */ public class Main { private boolean hasPrintedUsage = false; private final RubyInstanceConfig config; public Main(RubyInstanceConfig config) { this.config = config; } public Main(final InputStream in, final PrintStream out, final PrintStream err) { this(new RubyInstanceConfig(){{ setInput(in); setOutput(out); setError(err); }}); } public Main() { this(new RubyInstanceConfig()); } public static void main(String[] args) { Main main = new Main(); try { int status = main.run(args); if (status != 0) { System.exit(status); } } catch (RaiseException re) { throw re; } catch (Throwable t) { // print out as a nice Ruby backtrace System.err.println(ThreadContext.createRawBacktraceStringFromThrowable(t)); System.exit(1); } } public int run(String[] args) { try { config.processArguments(args); return run(); } catch (MainExitException mee) { if (!mee.isAborted()) { config.getOutput().println(mee.getMessage()); if (mee.isUsageError()) { printUsage(); } } return mee.getStatus(); } catch (OutOfMemoryError oome) { // produce a nicer error since Rubyists aren't used to seeing this System.gc(); String memoryMax = SafePropertyAccessor.getProperty("jruby.memory.max"); String message = ""; if (memoryMax != null) { message = " of " + memoryMax; } System.err.println("Error: Your application used more memory than the safety cap" + message + "."); System.err.println("Specify -J-Xmx####m to increase it (#### = cap size in MB)."); if (config.getVerbose()) { System.err.println("Exception trace follows:"); oome.printStackTrace(); } else { System.err.println("Specify -w for full OutOfMemoryError stack trace"); } return 1; } catch (StackOverflowError soe) { // produce a nicer error since Rubyists aren't used to seeing this System.gc(); String stackMax = SafePropertyAccessor.getProperty("jruby.stack.max"); String message = ""; if (stackMax != null) { message = " of " + stackMax; } System.err.println("Error: Your application used more stack memory than the safety cap" + message + "."); System.err.println("Specify -J-Xss####k to increase it (#### = cap size in KB)."); if (config.getVerbose()) { System.err.println("Exception trace follows:"); soe.printStackTrace(); } else { System.err.println("Specify -w for full StackOverflowError stack trace"); } return 1; } catch (UnsupportedClassVersionError ucve) { System.err.println("Error: Some library (perhaps JRuby) was built with a later JVM version."); System.err.println("Please use libraries built with the version you intend to use or an earlier one."); if (config.getVerbose()) { System.err.println("Exception trace follows:"); ucve.printStackTrace(); } else { System.err.println("Specify -w for full UnsupportedClassVersionError stack trace"); } return 1; } catch (ThreadKill kill) { return 0; } } public int run() { if (config.isShowVersion()) { showVersion(); } if (config.isShowCopyright()) { showCopyright(); } if (!config.shouldRunInterpreter() ) { if (config.shouldPrintUsage()) { printUsage(); } if (config.shouldPrintProperties()) { printProperties(); } return 0; } InputStream in = config.getScriptSource(); String filename = config.displayedFileName(); Ruby runtime = Ruby.newInstance(config); // set thread context JRuby classloader here, for the main thread try { Thread.currentThread().setContextClassLoader(runtime.getJRubyClassLoader()); } catch (SecurityException se) { // can't set TC classloader if (runtime.getInstanceConfig().isVerbose()) { System.err.println("WARNING: Security restrictions disallowed setting context classloader for main thread."); } } if (in == null) { // no script to run, return success below } else if (config.isShouldCheckSyntax()) { runtime.parseFromMain(in, filename); config.getOutput().println("Syntax OK"); } else { long now = -1; try { if (config.isBenchmarking()) { now = System.currentTimeMillis(); } if (config.isSamplingEnabled()) { SimpleSampler.startSampleThread(); } try { runtime.runFromMain(in, filename); } finally { runtime.tearDown(); if (config.isBenchmarking()) { config.getOutput().println("Runtime: " + (System.currentTimeMillis() - now) + " ms"); } if (config.isSamplingEnabled()) { org.jruby.util.SimpleSampler.report(); } } } catch (RaiseException rj) { RubyException raisedException = rj.getException(); if (runtime.getSystemExit().isInstance(raisedException)) { IRubyObject status = raisedException.callMethod(runtime.getCurrentContext(), "status"); if (status != null && !status.isNil()) { return RubyNumeric.fix2int(status); } } else { runtime.printError(raisedException); return 1; } } } return 0; } private void showVersion() { config.getOutput().print(config.getVersionString()); } private void showCopyright() { config.getOutput().print(config.getCopyrightString()); } public void printUsage() { if (!hasPrintedUsage) { config.getOutput().print(config.getBasicUsageHelp()); hasPrintedUsage = true; } } public void printProperties() { config.getOutput().print(config.getPropertyHelp()); } } /***** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2002-2004 Jan Arne Petersen * Copyright (C) 2004-2006 Thomas E Enebo * Copyright (C) 2004 Stefan Matthias Aust * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; import java.lang.ref.SoftReference; import org.jruby.runtime.builtin.IRubyObject; public final class MetaClass extends RubyClass { private SoftReference attached = new SoftReference(null); /** NEWOBJ (in RubyObject#getSingletonClassClone()) * */ public MetaClass(Ruby runtime) { super(runtime, null, false); } /** rb_class_boot (for MetaClasses) (in makeMetaClass(RubyClass)) * */ public MetaClass(Ruby runtime, RubyClass superClass) { super(runtime, superClass, false); index = superClass.index; // use same ClassIndex as metaclass, since we're technically still of that type } public boolean isSingleton() { return true; } /** * If an object uses an anonymous class 'class << obj', then this grabs the original * metaclass and not the one that get injected as a result of 'class << obj'. */ public RubyClass getRealClass() { return superClass.getRealClass(); } public final IRubyObject allocate(){ throw getRuntime().newTypeError("can't create instance of virtual class"); } public IRubyObject getAttached() { return attached.get(); } public void setAttached(IRubyObject attached) { this.attached = new SoftReference(attached); } } /***** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2005 David Corbin * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; import java.io.PrintStream; import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod; import org.jruby.javasupport.Java; import org.jruby.javasupport.JavaObject; import org.jruby.runtime.Block; import org.jruby.runtime.ObjectAllocator; import org.jruby.runtime.builtin.IRubyObject; @JRubyClass(name = "NativeException", parent = "RuntimeError") public class NativeException extends RubyException { private final Throwable cause; public static final String CLASS_NAME = "NativeException"; private final Ruby runtime; public NativeException(Ruby runtime, RubyClass rubyClass, Throwable cause) { super(runtime, rubyClass, cause.getClass().getName() + ": " + cause.getMessage()); this.runtime = runtime; this.cause = cause; } public static RubyClass createClass(Ruby runtime, RubyClass baseClass) { // FIXME: If NativeException is expected to be used from Ruby code, it should provide // a real allocator to be used. Otherwise Class.new will fail, as will marshalling. JRUBY-415 RubyClass exceptionClass = runtime.defineClass(CLASS_NAME, baseClass, ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); exceptionClass.defineAnnotatedMethods(NativeException.class); return exceptionClass; } @JRubyMethod(frame = true) public IRubyObject cause(Block unusedBlock) { return Java.wrap(getRuntime(), JavaObject.wrap(getRuntime(), cause)); } public IRubyObject backtrace() { IRubyObject rubyTrace = super.backtrace(); if (rubyTrace.isNil()) { return rubyTrace; } RubyArray array = (RubyArray) rubyTrace.dup(); StackTraceElement[] stackTrace = cause.getStackTrace(); for (int i = stackTrace.length - 1; i >= 0; i--) { StackTraceElement element = stackTrace[i]; String className = element.getClassName(); String line = null; if (element.getFileName() == null) { line = className + ":" + element.getLineNumber() + ":in `" + element.getMethodName() + "'"; } else { int index = className.lastIndexOf("."); String packageName = null; if (index == -1) { packageName = ""; } else { packageName = className.substring(0, index) + "/"; } line = packageName.replace(".", "/") + element.getFileName() + ":" + element.getLineNumber() + ":in `" + element.getMethodName() + "'"; } RubyString string = runtime.newString(line); array.unshift(string); } return array; } public void printBacktrace(PrintStream errorStream) { super.printBacktrace(errorStream); errorStream.println("Complete Java stackTrace"); cause.printStackTrace(errorStream); } public Throwable getCause() { return cause; } } /***** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2006 Ola Bini * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; /** * @author Ola Bini */ public interface Profile { Profile ALL = new Profile() { public boolean allowBuiltin(String name) { return true; } public boolean allowClass(String name) { return true; } public boolean allowModule(String name) { return true; } public boolean allowLoad(String name) { return true; } public boolean allowRequire(String name) { return true; } }; Profile DEBUG_ALLOW = new Profile() { public boolean allowBuiltin(String name) { System.err.println("allowBuiltin("+name+")"); return true; } public boolean allowClass(String name) { System.err.println("allowClass("+name+")"); return true; } public boolean allowModule(String name) { System.err.println("allowModule("+name+")"); return true; } public boolean allowLoad(String name) { System.err.println("allowLoad("+name+")"); return true; } public boolean allowRequire(String name) { System.err.println("allowRequire("+name+")"); return true; } }; Profile NO_FILE_CLASS = new Profile() { public boolean allowBuiltin(String name) { return true; } public boolean allowClass(String name) { return !name.equals("File"); } public boolean allowModule(String name) { return true; } public boolean allowLoad(String name) { return true; } public boolean allowRequire(String name) { return true; } }; Profile ANY = ALL; Profile DEFAULT = ALL; boolean allowBuiltin(String name); boolean allowClass(String name); boolean allowModule(String name); boolean allowLoad(String name); boolean allowRequire(String name); }// Profile /* **** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2001 Chad Fowler * Copyright (C) 2001 Alan Moore * Copyright (C) 2001-2002 Benoit Cerrina * Copyright (C) 2001-2004 Jan Arne Petersen * Copyright (C) 2002-2004 Anders Bengtsson * Copyright (C) 2004 Thomas E Enebo * Copyright (C) 2004-2005 Charles O Nutter * Copyright (C) 2004 Stefan Matthias Aust * Copyright (C) 2006 Miguel Covarrubias * Copyright (C) 2006 Michael Studman * Copyright (C) 2006 Ola Bini * Copyright (C) 2007 Nick Sieger * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.jruby; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import java.util.Stack; import java.util.Vector; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.joda.time.DateTimeZone; import org.jruby.ast.Node; import org.jruby.ast.executable.RubiniusRunner; import org.jruby.ast.executable.Script; import org.jruby.ast.executable.YARVCompiledRunner; import org.jruby.common.RubyWarnings; import org.jruby.common.IRubyWarnings.ID; import org.jruby.compiler.ASTCompiler; import org.jruby.compiler.ASTInspector; import org.jruby.compiler.JITCompiler; import org.jruby.compiler.NotCompilableException; import org.jruby.compiler.impl.StandardASMCompiler; import org.jruby.compiler.yarv.StandardYARVCompiler; import org.jruby.exceptions.JumpException; import org.jruby.exceptions.RaiseException; import org.jruby.ext.JRubyPOSIXHandler; import org.jruby.ext.LateLoadingLibrary; import org.jruby.ext.posix.POSIX; import org.jruby.ext.posix.POSIXFactory; import org.jruby.internal.runtime.GlobalVariables; import org.jruby.internal.runtime.ThreadService; import org.jruby.internal.runtime.ValueAccessor; import org.jruby.javasupport.JavaSupport; import org.jruby.management.BeanManager; import org.jruby.management.ClassCache; import org.jruby.management.Config; import org.jruby.parser.Parser; import org.jruby.parser.ParserConfiguration; import org.jruby.runtime.Binding; import org.jruby.runtime.Block; import org.jruby.runtime.CacheMap; import org.jruby.runtime.CallSite; import org.jruby.runtime.CallbackFactory; import org.jruby.runtime.DynamicScope; import org.jruby.runtime.EventHook; import org.jruby.runtime.GlobalVariable; import org.jruby.runtime.IAccessor; import org.jruby.runtime.ObjectAllocator; import org.jruby.runtime.ObjectSpace; import org.jruby.runtime.RubyEvent; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.load.Library; import org.jruby.runtime.load.LoadService; import org.jruby.util.BuiltinScript; import org.jruby.util.ByteList; import org.jruby.util.IOInputStream; import org.jruby.util.IOOutputStream; import org.jruby.util.JRubyClassLoader; import org.jruby.util.JavaNameMangler; import org.jruby.util.KCode; import org.jruby.util.SafePropertyAccessor; import org.jruby.util.collections.WeakHashSet; import org.jruby.util.io.ChannelDescriptor; /** * The Ruby object represents the top-level of a JRuby "instance" in a given VM. * JRuby supports spawning multiple instances in the same JVM. Generally, objects * created under these instances are tied to a given runtime, for such details * as identity and type, because multiple Ruby instances means there are * multiple instances of each class. This means that in multi-runtime mode * (or really, multi-VM mode, where each JRuby instance is a ruby "VM"), objects * generally can't be transported across runtimes without marshaling. * * This class roots everything that makes the JRuby runtime function, and * provides a number of utility methods for constructing global types and * accessing global runtime structures. */ public final class Ruby { /** * Returns a new instance of the JRuby runtime configured with defaults. * * @return the JRuby runtime * @see org.jruby.RubyInstanceConfig */ public static Ruby newInstance() { return newInstance(new RubyInstanceConfig()); } /** * Returns a new instance of the JRuby runtime configured as specified. * * @param config The instance configuration * @return The JRuby runtime * @see org.jruby.RubyInstanceConfig */ public static Ruby newInstance(RubyInstanceConfig config) { Ruby ruby = new Ruby(config); ruby.init(); return ruby; } /** * Returns a new instance of the JRuby runtime configured with the given * input, output and error streams and otherwise default configuration * (except where specified system properties alter defaults). * * @param in the custom input stream * @param out the custom output stream * @param err the custom error stream * @return the JRuby runtime * @see org.jruby.RubyInstanceConfig */ public static Ruby newInstance(InputStream in, PrintStream out, PrintStream err) { RubyInstanceConfig config = new RubyInstanceConfig(); config.setInput(in); config.setOutput(out); config.setError(err); return newInstance(config); } /** * Create and initialize a new JRuby runtime. The properties of the * specified RubyInstanceConfig will be used to determine various JRuby * runtime characteristics. * * @param config The configuration to use for the new instance * @see org.jruby.RubyInstanceConfig */ private Ruby(RubyInstanceConfig config) { this.config = config; this.threadService = new ThreadService(this); if(config.isSamplingEnabled()) { org.jruby.util.SimpleSampler.registerThreadContext(threadService.getCurrentContext()); } this.in = config.getInput(); this.out = config.getOutput(); this.err = config.getError(); this.objectSpaceEnabled = config.isObjectSpaceEnabled(); this.profile = config.getProfile(); this.currentDirectory = config.getCurrentDirectory(); this.kcode = config.getKCode(); this.beanManager = new BeanManager(this, config.isManagementEnabled()); this.jitCompiler = new JITCompiler(this); this.beanManager.register(new Config(this)); this.beanManager.register(new ClassCache(this)); this.cacheMap = new CacheMap(this); } /** * Evaluates a script under the current scope (perhaps the top-level * scope) and returns the result (generally the last value calculated). * This version goes straight into the interpreter, bypassing compilation * and runtime preparation typical to normal script runs. * * @param script The scriptlet to run * @returns The result of the eval */ public IRubyObject evalScriptlet(String script) { ThreadContext context = getCurrentContext(); Node node = parseEval(script, "