import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.StringReader;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;


/**
* Create and run THREAD_COUNT PHP threads, concurrently accessing a
* shared resource.

* Create 5 script engines, passing each a shared resource allocated
* from Java. Each script engine has to implement Runnable.
*
* Java accesses the Runnable script engine using
* scriptEngine.getInterface() and calls thread.start() to invoke each
* PHP Runnable implementations concurrently.
*/
public class PhpThreads {

    public static final String runnable = new String("<?php\n" +
            "
function run() {\n" +
            " 
$out java_context()->getAttribute('sharedResource'100);\n" +
            " 
$nr = (string)java_context()->getAttribute('nr'100);\n" +
            " 
echo \"started thread: $nr\n\";\n" +
            
" for($i=0; $i<100; $i++) {\n" +
            
"  $out->write(ord($nr));\n" +
            
"  java('java.lang.Thread')->sleep(1);\n" +
            
" }\n" +
            
"}\n" +
            
"?>\n");
    
    static final 
int THREAD_COUNT 5;
    public static 
void main(String[] argsthrows Exception {
    
ScriptEngineManager manager = new ScriptEngineManager();
    
Thread threads[] = new Thread[THREAD_COUNT];
    
ScriptEngine engines[] = new ScriptEngine[THREAD_COUNT];
    
ByteArrayOutputStream sharedResource = new ByteArrayOutputStream();
    
StringReader runnableReader = new StringReader(runnable);

    
// create THREAD_COUNT PHP threads
    
for (int i=0i<THREAD_COUNTi++) {
        
engines[i] = manager.getEngineByName("php-invocable");
        if (
engines[i] == null)
        throw new 
NullPointerException ("php script engine not found");
        
        
engines[i].put("nr", new Integer(i+1));
        
engines[i].put("sharedResource"sharedResource);
        
        
engines[i].eval(runnableReader);
        
runnableReader.reset();

        
// cast the whole script to Runnable; note also getInterface(specificClosure, type)
        
Runnable r = (Runnable) ((Invocable)engines[i]).getInterface(Runnable.class);
        
threads[i] = new Thread(r);
    }
    
    
// run the THREAD_COUNT PHP threads
    
for (int i=0i<THREAD_COUNTi++) {
        
threads[i].start();
    }
    
    
// wait for the THREAD_COUNT PHP threads to finish
    
for (int i=0i<THREAD_COUNTi++) {
        
threads[i].join();
        ((
Closeable)engines[i]).close();
    }
    
    
// print the output generated by the THREAD_COUNT concurrent threads
    
String result sharedResource.toString();
    
System.out.println(result);
    
    
// Check result
    
Object res=manager.getEngineByName("php").eval(
        
"<?php " +
        
"exit((int)('10011002100310041005'!=" +
        
"@system(\"echo -n "+result+"|sed 's/./&\\\n/g'|sort|uniq -c|tr -d ' \\\n'\")));" +
        
"?>");
    
    
System.exit(((Number)res).intValue());
    }
}