Mercurial Hosting > luan
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()); |