comparison src/luan/modules/http/LuanHandler.java @ 1263:382c444a6c77

add Http.eval_in_root and Http.handle_error
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 24 Sep 2018 22:06:25 -0600
parents e38f5869e9df
children d41997776788
comparison
equal deleted inserted replaced
1262:81d3a01fbd09 1263:382c444a6c77
4 import java.io.Writer; 4 import java.io.Writer;
5 import java.io.PrintWriter; 5 import java.io.PrintWriter;
6 import java.io.IOException; 6 import java.io.IOException;
7 import java.lang.reflect.Method; 7 import java.lang.reflect.Method;
8 import java.net.BindException; 8 import java.net.BindException;
9 import java.util.concurrent.locks.ReadWriteLock;
10 import java.util.concurrent.locks.ReentrantReadWriteLock;
11 import org.slf4j.Logger; 9 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory; 10 import org.slf4j.LoggerFactory;
13 import luan.webserver.Request; 11 import luan.webserver.Request;
14 import luan.webserver.Response; 12 import luan.webserver.Response;
15 import luan.webserver.Server; 13 import luan.webserver.Server;
21 import luan.LuanFunction; 19 import luan.LuanFunction;
22 import luan.LuanJavaFunction; 20 import luan.LuanJavaFunction;
23 import luan.LuanCloner; 21 import luan.LuanCloner;
24 import luan.LuanException; 22 import luan.LuanException;
25 import luan.modules.PackageLuan; 23 import luan.modules.PackageLuan;
24 import luan.modules.BasicLuan;
26 25
27 26
28 public class LuanHandler implements Handler, Closeable { 27 public final class LuanHandler implements Handler, Closeable {
29 private final LuanState luanInit; 28 private final LuanState luanInit;
30 private final Logger logger; 29 private final Logger logger;
31 private final HttpServicer httpServicer; 30 private volatile LuanState luan;
32 private final ReadWriteLock lock = new ReentrantReadWriteLock();
33 private LuanState luan;
34 31
35 private static final Method resetLuanMethod; 32 private static final Method resetLuanMethod;
33 private static final Method evalInRootMethod;
36 static { 34 static {
37 try { 35 try {
38 resetLuanMethod = LuanHandler.class.getMethod("reset_luan"); 36 resetLuanMethod = LuanHandler.class.getMethod( "reset_luan" );
37 evalInRootMethod = LuanHandler.class.getMethod( "eval_in_root", String.class );
39 } catch(NoSuchMethodException e) { 38 } catch(NoSuchMethodException e) {
40 throw new RuntimeException(e); 39 throw new RuntimeException(e);
41 } 40 }
42 } 41 }
43 42
44 public LuanHandler(LuanState luanInit,String loggerRoot,HttpServicer httpServicer) { 43 public LuanHandler(LuanState luanInit,String loggerRoot) {
45 this.luanInit = luanInit; 44 this.luanInit = luanInit;
46 if( loggerRoot==null ) 45 if( loggerRoot==null )
47 loggerRoot = ""; 46 loggerRoot = "";
48 logger = LoggerFactory.getLogger(loggerRoot+LuanHandler.class.getName()); 47 logger = LoggerFactory.getLogger(loggerRoot+LuanHandler.class.getName());
49 try { 48 try {
50 LuanTable Http = (LuanTable)PackageLuan.require(luanInit,"luan:http/Http.luan"); 49 LuanTable Http = (LuanTable)PackageLuan.require(luanInit,"luan:http/Http.luan");
51 Http.rawPut( "reset_luan", new LuanJavaFunction(resetLuanMethod,this) ); 50 Http.rawPut( "reset_luan", new LuanJavaFunction(resetLuanMethod,this) );
51 Http.rawPut( "eval_in_root", new LuanJavaFunction(evalInRootMethod,this) );
52 } catch(LuanException e) { 52 } catch(LuanException e) {
53 throw new RuntimeException(e); 53 throw new RuntimeException(e);
54 } 54 }
55 this.httpServicer = httpServicer!=null ? httpServicer : new HttpServicer();
56 setLuan(); 55 setLuan();
57 luanInit.onClose(this); 56 luanInit.onClose(this);
58 } 57 }
59 58
60 public LuanState getLuan() { 59 public LuanState getLuan() {
81 80
82 Response handle(Request request,String modName) { 81 Response handle(Request request,String modName) {
83 Thread thread = Thread.currentThread(); 82 Thread thread = Thread.currentThread();
84 String oldName = thread.getName(); 83 String oldName = thread.getName();
85 thread.setName(request.headers.get("host")+request.path); 84 thread.setName(request.headers.get("host")+request.path);
86 lock.readLock().lock();
87 try { 85 try {
88 return httpServicer.service(luan,request,modName); 86 return HttpServicer.service(luan,request,modName);
89 } finally { 87 } finally {
90 lock.readLock().unlock();
91 thread.setName(oldName); 88 thread.setName(oldName);
92 } 89 }
93 } 90 }
94 91
95 public void close() { 92 public void close() {
97 luan.close(); 94 luan.close();
98 } 95 }
99 } 96 }
100 97
101 public Object call_rpc(String fnName,Object... args) throws LuanException { 98 public Object call_rpc(String fnName,Object... args) throws LuanException {
102 lock.readLock().lock(); 99 LuanFunction fn;
103 try { 100 LuanState luan = this.luan;
104 LuanFunction fn; 101 synchronized(luan) {
105 LuanState luan = this.luan; 102 PackageLuan.enableLoad(luan,"luan:Rpc.luan");
106 synchronized(luan) { 103 LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan");
107 PackageLuan.enableLoad(luan,"luan:Rpc.luan"); 104 LuanTable fns = (LuanTable)rpc.get(luan,"functions");
108 LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan"); 105 fn = (LuanFunction)fns.get(luan,fnName);
109 LuanTable fns = (LuanTable)rpc.get(luan,"functions"); 106 if( fn == null )
110 fn = (LuanFunction)fns.get(luan,fnName); 107 throw new LuanException( "function not found: " + fnName );
111 if( fn == null ) 108 LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
112 throw new LuanException( "function not found: " + fnName ); 109 luan = (LuanState)cloner.clone(luan);
113 LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); 110 fn = (LuanFunction)cloner.get(fn);
114 luan = (LuanState)cloner.clone(luan);
115 fn = (LuanFunction)cloner.get(fn);
116 }
117 return fn.call(luan,args);
118 } finally {
119 lock.readLock().unlock();
120 } 111 }
112 return fn.call(luan,args);
121 } 113 }
122 114
123 public void reset_luan() { 115 public void reset_luan() {
124 new Thread() { 116 setLuan();
125 public void run() {
126 lock.writeLock().lock();
127 try {
128 synchronized(luan) {
129 luan.close();
130 setLuan();
131 }
132 } finally {
133 lock.writeLock().unlock();
134 }
135 }
136 }.start();
137 } 117 }
138 118
139 public Object runLuan(String sourceText,String sourceName) throws LuanException { 119 public Object runLuan(String sourceText,String sourceName) throws LuanException {
140 LuanFunction fn = Luan.load(sourceText,sourceName); 120 LuanFunction fn = Luan.load(sourceText,sourceName);
141 synchronized(luan) { 121 synchronized(luan) {
143 LuanState luan = (LuanState)cloner.clone(this.luan); 123 LuanState luan = (LuanState)cloner.clone(this.luan);
144 return fn.call(luan); 124 return fn.call(luan);
145 } 125 }
146 } 126 }
147 127
128 public void eval_in_root(String text) throws LuanException {
129 LuanState luan;
130 synchronized(this.luan) {
131 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
132 luan = (LuanState)cloner.clone(this.luan);
133 }
134 BasicLuan.load(text,"<eval_in_root>",null).call(luan);
135 this.luan = luan;
136 }
137
148 public static void start(Server server) throws Exception { 138 public static void start(Server server) throws Exception {
149 try { 139 try {
150 server.start(); 140 server.start();
151 } catch(BindException e) { 141 } catch(BindException e) {
152 throw new LuanException(e.toString()); 142 throw new LuanException(e.toString());