Index: src/org/jruby/RubyThread.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyThread.java,v
retrieving revision 1.15
diff -u -r1.15 RubyThread.java
--- src/org/jruby/RubyThread.java	29 Dec 2005 00:33:06 -0000	1.15
+++ src/org/jruby/RubyThread.java	23 Jan 2006 18:31:36 -0000
@@ -182,6 +182,26 @@
     public static RubyThread start(IRubyObject recv, IRubyObject[] args) {
         return startThread(recv, args, false);
     }
+    
+    public static RubyThread adopt(IRubyObject recv, Thread t) {
+        return adoptThread(recv, t);
+    }
+
+    private static RubyThread adoptThread(final IRubyObject recv, Thread t) {
+        final IRuby runtime = recv.getRuntime();
+        final RubyThread rubyThread = new RubyThread(runtime, (RubyClass) recv, false);
+        
+        rubyThread.threadImpl = new NativeThread(rubyThread, t);
+        runtime.getThreadService().registerNewThread(rubyThread);
+        
+        runtime.getCurrentContext().preAdoptThread();
+        
+        rubyThread.callInit(new IRubyObject[0]);
+        
+        rubyThread.notifyStarted();
+        
+        return rubyThread;
+    }
 
     private static RubyThread startThread(final IRubyObject recv, final IRubyObject[] args, boolean callInit) {
         final IRuby runtime = recv.getRuntime();
@@ -284,6 +304,15 @@
         
     }
 
+    private RubyThread(IRuby runtime, RubyClass type, boolean narf) {
+        super(runtime, type);
+        this.threadService = runtime.getThreadService();
+        
+        // set to default thread group
+        RubyThreadGroup defaultThreadGroup = (RubyThreadGroup)runtime.getClass("ThreadGroup").getConstant("Default");
+        defaultThreadGroup.add(this);
+    }
+
     /**
      * Returns the status of the global ``abort on exception'' condition. The
      * default is false. When set to true, will cause all threads to abort (the
Index: src/org/jruby/internal/runtime/ThreadService.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/internal/runtime/ThreadService.java,v
retrieving revision 1.10
diff -u -r1.10 ThreadService.java
--- src/org/jruby/internal/runtime/ThreadService.java	29 Dec 2005 00:33:06 -0000	1.10
+++ src/org/jruby/internal/runtime/ThreadService.java	23 Jan 2006 18:31:36 -0000
@@ -45,6 +45,7 @@
     private ThreadGroup rubyThreadGroup;
     private List rubyThreadList;
     private volatile boolean critical;
+    private Thread mainThread;
 
     public ThreadService(IRuby runtime) {
         this.runtime = runtime;
@@ -54,7 +55,8 @@
         this.rubyThreadList = Collections.synchronizedList(new ArrayList());
         
         // Must be called from main thread (it is currently, but this bothers me)
-        rubyThreadList.add(Thread.currentThread());
+        mainThread = Thread.currentThread();
+        rubyThreadList.add(mainThread);
     }
 
     public void disposeCurrentThread() {
@@ -62,6 +64,20 @@
     }
 
     public ThreadContext getCurrentContext() {
+        ThreadContext tc = (ThreadContext) localContext.get();
+        
+        if (tc == mainContext && Thread.currentThread() != mainThread) {
+            tc = adoptCurrentThread();
+        }
+        
+        return tc;
+    }
+    
+    private ThreadContext adoptCurrentThread() {
+        Thread current = Thread.currentThread();
+        
+        RubyThread.adopt(runtime.getClass("Thread"), current);
+        
         return (ThreadContext) localContext.get();
     }
 
Index: src/org/jruby/runtime/ThreadContext.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/runtime/ThreadContext.java,v
retrieving revision 1.75
diff -u -r1.75 ThreadContext.java
--- src/org/jruby/runtime/ThreadContext.java	23 Jan 2006 06:20:50 -0000	1.75
+++ src/org/jruby/runtime/ThreadContext.java	23 Jan 2006 18:31:37 -0000
@@ -90,7 +90,7 @@
 
         pushDynamicVars();
     }
-    
+
     Visibility lastVis;
     CallType lastCallType;
 
@@ -521,6 +521,13 @@
     
         return backtrace;
     }
+    
+    public void preAdoptThread() {
+        pushIter(Iter.ITER_NOT);
+        pushFrame();
+        pushScope();
+        pushRubyClass(runtime.getObject());
+    }
 
     public void preClassEval(List localNames, RubyModule type) {
         pushRubyClass(type); 
Index: test/org/jruby/test/MainTestSuite.java
===================================================================
RCS file: /cvsroot/jruby/jruby/test/org/jruby/test/MainTestSuite.java,v
retrieving revision 1.12
diff -u -r1.12 MainTestSuite.java
--- test/org/jruby/test/MainTestSuite.java	23 Dec 2005 16:23:22 -0000	1.12
+++ test/org/jruby/test/MainTestSuite.java	23 Jan 2006 18:31:37 -0000
@@ -69,6 +69,7 @@
         suite.addTest(new TestSuite(TestRubyException.class));
         suite.addTest(new TestSuite(TestReflectionCallback.class));
         suite.addTest(new TestSuite(TestRegexpTranslator.class));
+        //suite.addTest(new TestSuite(TestAdoptedThreading.class));
         return suite;
     }
 }
Index: test/org/jruby/test/ITest.java
===================================================================
RCS file: test/org/jruby/test/ITest.java
diff -N test/org/jruby/test/ITest.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ test/org/jruby/test/ITest.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,5 @@
+package org.jruby.test;
+
+public interface ITest {
+    public Object exec(String s);
+}
Index: test/org/jruby/test/TestAdoptedThreading.java
===================================================================
RCS file: test/org/jruby/test/TestAdoptedThreading.java
diff -N test/org/jruby/test/TestAdoptedThreading.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ test/org/jruby/test/TestAdoptedThreading.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,130 @@
+package org.jruby.test;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.bsf.BSFManager;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class TestAdoptedThreading extends TestCase {
+    private static Logger LOGGER = Logger.getLogger(TestAdoptedThreading.class
+            .getName());
+
+    private static final String SCRIPT = "require 'java'\n"
+            + "include_class 'org.jruby.test.ITest'\n"
+            + "class TestImpl < ITest\n" + "    def exec(_value)\n"
+            + "        puts \"start executing!\"\n"
+            + "        1000.times do | item |\n"
+            + "           value = \"#{item}\"\n" + "        end\n"
+            + "        puts \"end executing1!\"\n" + "        exec2(_value)\n"
+            + "    end\n" + "    def exec2(_value)\n"
+            + "        puts \"start executing2!\"\n"
+            + "        5000.times do | item |\n"
+            + "           value = \"#{item}\"\n" + "        end\n"
+            + "        puts \"end executing2!\"\n"
+            + "        \"VALUE: #{_value}\"\n" + "    end\n" + "end";
+
+    public TestAdoptedThreading(String _name) {
+        super(_name);
+    }
+
+    public static Test suite() {
+        TestSuite suite;
+        suite = new TestSuite(TestAdoptedThreading.class);
+
+        return suite;
+    }
+
+    private BSFManager manager_;
+
+    protected void setUp() throws Exception {
+        try {
+            LOGGER.log(Level.INFO, SCRIPT);
+            BSFManager.registerScriptingEngine("ruby",
+                    "org.jruby.javasupport.bsf.JRubyEngine",
+                    new String[] { "rb" });
+            manager_ = new BSFManager();
+            manager_.exec("ruby", "(java)", 1, 1, SCRIPT);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    public void testThreading() {
+        Runner r00 = new Runner("R1", 10);
+        Runner r01 = new Runner("R1", 10);
+        Runner r02 = new Runner("R1", 10);
+        Runner r03 = new Runner("R1", 10);
+        Runner r04 = new Runner("R1", 10);
+        Runner r05 = new Runner("R1", 10);
+        Runner r06 = new Runner("R1", 10);
+        Runner r07 = new Runner("R1", 10);
+        Runner r08 = new Runner("R1", 10);
+        Runner r09 = new Runner("R1", 10);
+
+        r00.start();
+        r01.start();
+        r02.start();
+        r03.start();
+        r04.start();
+        r05.start();
+        r06.start();
+        r07.start();
+        r08.start();
+        r09.start();
+
+        try {
+            r00.join();
+            r01.join();
+            r02.join();
+            r03.join();
+            r04.join();
+            r05.join();
+            r06.join();
+            r07.join();
+            r08.join();
+            r09.join();
+        } catch (InterruptedException ie) {
+            // XXX: do something?
+        }
+    }
+
+    class Runner extends Thread {
+        private int count_;
+
+        public Runner(String _name, int _count) {
+            count_ = _count;
+        }
+
+        public void run() {
+            for (int i = 0; i < count_; i++) {
+                ITest test = getTest();
+                if (test != null) {
+                    LOGGER.log(Level.INFO, "[NAME:" + getName() + "VALUE: "
+                            + test.exec("KABOOM!") + ", COUNT: " + i + "]");
+                }
+            }
+        }
+
+        private ITest getTest() {
+            ITest result = null;
+            synchronized (manager_) {
+                try {
+                    result = (ITest) manager_.eval("ruby", "(java)", 1, 1,
+                            "TestImpl.new");
+                } catch (Exception ex) {
+                    ex.printStackTrace();
+                }
+            }
+            return result;
+        }
+    }
+
+    public static void main(String[] _args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+}
