1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
|
package org.perl.inline.java ;
import java.util.* ;
import java.io.* ;
/*
Callback to Perl...
*/
public class InlineJavaPerlCaller {
private InlineJavaServer ijs = InlineJavaServer.GetInstance() ;
private Thread creator = null ;
static private Map<Thread, InlineJavaCallbackQueue> thread_callback_queues = Collections.synchronizedMap(new HashMap<Thread, InlineJavaCallbackQueue>()) ;
static private ResourceBundle resources = null ;
static private boolean inited = false ;
/*
Only thread that communicate with Perl are allowed to create PerlCallers because
this is where we get the thread that needs to be notified when the callbacks come in.
*/
public InlineJavaPerlCaller() throws InlineJavaException {
init() ;
Thread t = Thread.currentThread() ;
if (ijs.IsThreadPerlContact(t)){
creator = t ;
}
else{
throw new InlineJavaException("InlineJavaPerlCaller objects can only be created by threads that communicate directly with Perl") ;
}
}
synchronized static protected void init() throws InlineJavaException {
if (! inited){
try {
resources = ResourceBundle.getBundle("InlineJava") ;
inited = true ;
}
catch (MissingResourceException mre){
throw new InlineJavaException("Error loading InlineJava.properties: " + mre.getMessage()) ;
}
}
}
static protected ResourceBundle GetBundle(){
return resources ;
}
/* New interface */
public Object CallPerlSub(String sub, Object args[]) throws InlineJavaException, InlineJavaPerlException {
return CallPerlSub(sub, args, null) ;
}
/* New interface */
public Object CallPerlSub(String sub, Object args[], Class cast) throws InlineJavaException, InlineJavaPerlException {
InlineJavaCallback ijc = new InlineJavaCallback(
(String)null, sub, args, cast) ;
return CallPerl(ijc) ;
}
/* New interface */
public Object CallPerlMethod(InlineJavaPerlObject obj, String method, Object args[]) throws InlineJavaException, InlineJavaPerlException {
return CallPerlMethod(obj, method, args, null) ;
}
/* New interface */
public Object CallPerlMethod(InlineJavaPerlObject obj, String method, Object args[], Class cast) throws InlineJavaException, InlineJavaPerlException {
InlineJavaCallback ijc = new InlineJavaCallback(
obj, method, args, cast) ;
return CallPerl(ijc) ;
}
/* New interface */
public Object CallPerlStaticMethod(String pkg, String method, Object args[]) throws InlineJavaException, InlineJavaPerlException {
return CallPerlStaticMethod(pkg, method, args, null) ;
}
/* New interface */
public Object CallPerlStaticMethod(String pkg, String method, Object args[], Class cast) throws InlineJavaException, InlineJavaPerlException {
InlineJavaCallback ijc = new InlineJavaCallback(
pkg, method, args, cast) ;
return CallPerl(ijc) ;
}
public Object eval(String code) throws InlineJavaPerlException, InlineJavaException {
return eval(code, null) ;
}
public Object eval(String code, Class cast) throws InlineJavaPerlException, InlineJavaException {
return CallPerlSub("Inline::Java::Callback::java_eval", new Object [] {code}, cast) ;
}
public Object require(String module_or_file) throws InlineJavaPerlException, InlineJavaException {
return CallPerlSub("Inline::Java::Callback::java_require", new Object [] {module_or_file}) ;
}
public Object require_file(String file) throws InlineJavaPerlException, InlineJavaException {
return CallPerlSub("Inline::Java::Callback::java_require", new Object [] {file, Boolean.TRUE}) ;
}
public Object require_module(String module) throws InlineJavaPerlException, InlineJavaException {
return CallPerlSub("Inline::Java::Callback::java_require", new Object [] {module, Boolean.FALSE}) ;
}
private Object CallPerl(InlineJavaCallback ijc) throws InlineJavaException, InlineJavaPerlException {
Thread t = Thread.currentThread() ;
if (t == creator){
ijc.Process() ;
return ijc.GetResponse() ;
}
else {
// Enqueue the callback into the creator thread's queue and notify it
// that there is some work for him.
ijc.ClearResponse() ;
InlineJavaCallbackQueue q = GetQueue(creator) ;
InlineJavaUtils.debug(3, "enqueing callback for processing for " + creator.getName() + " in " + t.getName() + "...") ;
q.EnqueueCallback(ijc) ;
InlineJavaUtils.debug(3, "notifying that a callback request is available for " + creator.getName() + " in " + t.getName()) ;
// Now we must wait until the callback is processed and get back the result...
return ijc.WaitForResponse(t) ;
}
}
public void OpenCallbackStream() throws InlineJavaException {
Thread t = Thread.currentThread() ;
if (! ijs.IsThreadPerlContact(t)){
throw new InlineJavaException("InlineJavaPerlCaller.OpenCallbackStream() can only be called by threads that communicate directly with Perl") ;
}
InlineJavaCallbackQueue q = GetQueue(t) ;
q.OpenCallbackStream() ;
}
/*
Blocks until either a callback arrives, timeout seconds has passed or the call is
interrupted by Interrupt?
*/
public int WaitForCallback(double timeout) throws InlineJavaException {
Thread t = Thread.currentThread() ;
if (! ijs.IsThreadPerlContact(t)){
throw new InlineJavaException("InlineJavaPerlCaller.WaitForCallback() can only be called by threads that communicate directly with Perl") ;
}
InlineJavaCallbackQueue q = GetQueue(t) ;
if (timeout == 0.0){
// no wait
return q.GetSize() ;
}
else if (timeout == -1.0){
timeout = 0.0 ;
}
return q.WaitForCallback(timeout) ;
}
public boolean ProcessNextCallback() throws InlineJavaException, InlineJavaPerlException {
Thread t = Thread.currentThread() ;
if (! ijs.IsThreadPerlContact(t)){
throw new InlineJavaException("InlineJavaPerlCaller.ProcessNextCallback() can only be called by threads that communicate directly with Perl") ;
}
InlineJavaCallbackQueue q = GetQueue(t) ;
return q.ProcessNextCallback() ;
}
public void CloseCallbackStream() throws InlineJavaException {
InlineJavaCallbackQueue q = GetQueue(creator) ;
q.CloseCallbackStream() ;
}
public void StartCallbackLoop() throws InlineJavaException, InlineJavaPerlException {
Thread t = Thread.currentThread() ;
if (! ijs.IsThreadPerlContact(t)){
throw new InlineJavaException("InlineJavaPerlCaller.StartCallbackLoop() can only be called by threads that communicate directly with Perl") ;
}
InlineJavaCallbackQueue q = GetQueue(t) ;
InlineJavaUtils.debug(3, "starting callback loop for " + creator.getName() + " in " + t.getName()) ;
q.OpenCallbackStream() ;
while (q.IsStreamOpen()){
q.ProcessNextCallback() ;
}
}
public void StopCallbackLoop() throws InlineJavaException {
Thread t = Thread.currentThread() ;
InlineJavaCallbackQueue q = GetQueue(creator) ;
InlineJavaUtils.debug(3, "stopping callback loop for " + creator.getName() + " in " + t.getName()) ;
q.CloseCallbackStream() ;
}
/*
Here the prototype accepts Threads because the JNI thread
calls this method also.
*/
static synchronized void AddThread(Thread t){
thread_callback_queues.put(t, new InlineJavaCallbackQueue()) ;
}
static synchronized void RemoveThread(InlineJavaServerThread t){
thread_callback_queues.remove(t) ;
}
static private InlineJavaCallbackQueue GetQueue(Thread t) throws InlineJavaException {
InlineJavaCallbackQueue q = (InlineJavaCallbackQueue)thread_callback_queues.get(t) ;
if (q == null){
throw new InlineJavaException("Can't find thread " + t.getName() + "!") ;
}
return q ;
}
}
|