Mercurial Hosting > luan
annotate src/luan/modules/http/LuanHandler.java @ 1264:d41997776788
fix onClose issues
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 25 Sep 2018 17:03:57 -0600 |
parents | 382c444a6c77 |
children | 3f4644246e39 |
rev | line source |
---|---|
1171 | 1 package luan.modules.http; |
175
bdbd4740121f
finish web server
fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
parents:
diff
changeset
|
2 |
1231 | 3 import java.io.Closeable; |
1160 | 4 import java.io.Writer; |
5 import java.io.PrintWriter; | |
175
bdbd4740121f
finish web server
fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
parents:
diff
changeset
|
6 import java.io.IOException; |
1264 | 7 import java.lang.ref.Reference; |
8 import java.lang.ref.WeakReference; | |
786
fe63c508a177
add Http.reset_luan()
Franklin Schmidt <fschmidt@gmail.com>
parents:
785
diff
changeset
|
9 import java.lang.reflect.Method; |
1004
3fa54d9d19cd
better handling of BindException
Franklin Schmidt <fschmidt@gmail.com>
parents:
1000
diff
changeset
|
10 import java.net.BindException; |
1264 | 11 import java.util.List; |
12 import java.util.ArrayList; | |
13 import java.util.concurrent.locks.ReadWriteLock; | |
14 import java.util.concurrent.locks.ReentrantReadWriteLock; | |
280
2164b4479661
log web exceptions
fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
parents:
264
diff
changeset
|
15 import org.slf4j.Logger; |
2164b4479661
log web exceptions
fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
parents:
264
diff
changeset
|
16 import org.slf4j.LoggerFactory; |
1160 | 17 import luan.webserver.Request; |
18 import luan.webserver.Response; | |
19 import luan.webserver.Server; | |
20 import luan.webserver.Handler; | |
21 import luan.webserver.ResponseOutputStream; | |
786
fe63c508a177
add Http.reset_luan()
Franklin Schmidt <fschmidt@gmail.com>
parents:
785
diff
changeset
|
22 import luan.Luan; |
175
bdbd4740121f
finish web server
fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
parents:
diff
changeset
|
23 import luan.LuanState; |
743
2c41f2aec92f
improve Rpc and implement rpc call for local webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
693
diff
changeset
|
24 import luan.LuanTable; |
2c41f2aec92f
improve Rpc and implement rpc call for local webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
693
diff
changeset
|
25 import luan.LuanFunction; |
786
fe63c508a177
add Http.reset_luan()
Franklin Schmidt <fschmidt@gmail.com>
parents:
785
diff
changeset
|
26 import luan.LuanJavaFunction; |
781
fbbdd369a13a
rename DeepCloner to LuanCloner
Franklin Schmidt <fschmidt@gmail.com>
parents:
777
diff
changeset
|
27 import luan.LuanCloner; |
175
bdbd4740121f
finish web server
fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
parents:
diff
changeset
|
28 import luan.LuanException; |
743
2c41f2aec92f
improve Rpc and implement rpc call for local webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
693
diff
changeset
|
29 import luan.modules.PackageLuan; |
1263
382c444a6c77
add Http.eval_in_root and Http.handle_error
Franklin Schmidt <fschmidt@gmail.com>
parents:
1257
diff
changeset
|
30 import luan.modules.BasicLuan; |
175
bdbd4740121f
finish web server
fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
parents:
diff
changeset
|
31 |
bdbd4740121f
finish web server
fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
parents:
diff
changeset
|
32 |
1264 | 33 public final class LuanHandler implements Handler { |
34 | |
35 private class Instance implements LuanState.OnClose { | |
36 private final List<Reference<Closeable>> onClose; | |
37 private final LuanState luan; | |
38 private final ReadWriteLock lock = new ReentrantReadWriteLock(); | |
39 | |
40 Instance() { | |
41 onClose = new ArrayList<Reference<Closeable>>(); | |
42 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); | |
43 luan = (LuanState)cloner.clone(luanInit); | |
44 luan.onClose = this; | |
45 try { | |
46 PackageLuan.load(luan,"site:/init.luan"); | |
47 } catch(LuanException e) { | |
48 String err = e.getLuanStackTraceString(); | |
49 logger.error(err); | |
50 } | |
51 } | |
52 | |
53 Response handle(Request request,String modName) { | |
54 Thread thread = Thread.currentThread(); | |
55 String oldName = thread.getName(); | |
56 thread.setName(request.headers.get("host")+request.path); | |
57 lock.readLock().lock(); | |
58 try { | |
59 return HttpServicer.service(luan,request,modName); | |
60 } finally { | |
61 lock.readLock().unlock(); | |
62 thread.setName(oldName); | |
63 } | |
64 } | |
65 | |
66 Object call_rpc(String fnName,Object... args) throws LuanException { | |
67 lock.readLock().lock(); | |
68 try { | |
69 LuanFunction fn; | |
70 LuanState luan = this.luan; | |
71 synchronized(luan) { | |
72 PackageLuan.enableLoad(luan,"luan:Rpc.luan"); | |
73 LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan"); | |
74 LuanTable fns = (LuanTable)rpc.get(luan,"functions"); | |
75 fn = (LuanFunction)fns.get(luan,fnName); | |
76 if( fn == null ) | |
77 throw new LuanException( "function not found: " + fnName ); | |
78 LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); | |
79 luan = (LuanState)cloner.clone(luan); | |
80 fn = (LuanFunction)cloner.get(fn); | |
81 } | |
82 return fn.call(luan,args); | |
83 } finally { | |
84 lock.readLock().unlock(); | |
85 } | |
86 } | |
87 | |
88 public Object runLuan(String sourceText,String sourceName) throws LuanException { | |
89 lock.readLock().lock(); | |
90 try { | |
91 LuanFunction fn = Luan.load(sourceText,sourceName); | |
92 synchronized(luan) { | |
93 LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); | |
94 LuanState luan = (LuanState)cloner.clone(this.luan); | |
95 return fn.call(luan); | |
96 } | |
97 } finally { | |
98 lock.readLock().unlock(); | |
99 } | |
100 } | |
101 | |
102 public void onClose(Closeable c) { | |
103 synchronized(onClose) { | |
104 onClose.add(new WeakReference<Closeable>(c)); | |
105 } | |
106 } | |
107 | |
108 public void close() { | |
109 synchronized(onClose) { | |
110 for( Reference<Closeable> ref : onClose ) { | |
111 Closeable c = ref.get(); | |
112 if( c != null ) { | |
113 try { | |
114 c.close(); | |
115 } catch(IOException e) { | |
116 logger.error(c.toString(),e); | |
117 } | |
118 } | |
119 } | |
120 onClose.clear(); | |
121 } | |
122 } | |
123 | |
124 Instance cloneInstance() { | |
125 synchronized(luan) { | |
126 return new Instance(this); | |
127 } | |
128 } | |
129 | |
130 private Instance(Instance instance) { | |
131 onClose = instance.onClose; | |
132 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); | |
133 luan = (LuanState)cloner.clone(instance.luan); | |
134 luan.onClose = this; | |
135 } | |
136 } | |
137 | |
1186 | 138 private final LuanState luanInit; |
627
a98812908fbc
add loggerRoot param to LuanHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
531
diff
changeset
|
139 private final Logger logger; |
1264 | 140 private volatile Instance instance; |
786
fe63c508a177
add Http.reset_luan()
Franklin Schmidt <fschmidt@gmail.com>
parents:
785
diff
changeset
|
141 |
1186 | 142 private static final Method resetLuanMethod; |
1263
382c444a6c77
add Http.eval_in_root and Http.handle_error
Franklin Schmidt <fschmidt@gmail.com>
parents:
1257
diff
changeset
|
143 private static final Method evalInRootMethod; |
1186 | 144 static { |
145 try { | |
1263
382c444a6c77
add Http.eval_in_root and Http.handle_error
Franklin Schmidt <fschmidt@gmail.com>
parents:
1257
diff
changeset
|
146 resetLuanMethod = LuanHandler.class.getMethod( "reset_luan" ); |
382c444a6c77
add Http.eval_in_root and Http.handle_error
Franklin Schmidt <fschmidt@gmail.com>
parents:
1257
diff
changeset
|
147 evalInRootMethod = LuanHandler.class.getMethod( "eval_in_root", String.class ); |
1186 | 148 } catch(NoSuchMethodException e) { |
149 throw new RuntimeException(e); | |
150 } | |
151 } | |
152 | |
1263
382c444a6c77
add Http.eval_in_root and Http.handle_error
Franklin Schmidt <fschmidt@gmail.com>
parents:
1257
diff
changeset
|
153 public LuanHandler(LuanState luanInit,String loggerRoot) { |
1231 | 154 this.luanInit = luanInit; |
627
a98812908fbc
add loggerRoot param to LuanHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
531
diff
changeset
|
155 if( loggerRoot==null ) |
a98812908fbc
add loggerRoot param to LuanHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
531
diff
changeset
|
156 loggerRoot = ""; |
a98812908fbc
add loggerRoot param to LuanHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
531
diff
changeset
|
157 logger = LoggerFactory.getLogger(loggerRoot+LuanHandler.class.getName()); |
1186 | 158 try { |
159 LuanTable Http = (LuanTable)PackageLuan.require(luanInit,"luan:http/Http.luan"); | |
160 Http.rawPut( "reset_luan", new LuanJavaFunction(resetLuanMethod,this) ); | |
1263
382c444a6c77
add Http.eval_in_root and Http.handle_error
Franklin Schmidt <fschmidt@gmail.com>
parents:
1257
diff
changeset
|
161 Http.rawPut( "eval_in_root", new LuanJavaFunction(evalInRootMethod,this) ); |
1186 | 162 } catch(LuanException e) { |
163 throw new RuntimeException(e); | |
164 } | |
1264 | 165 instance = new Instance(); |
1186 | 166 } |
1264 | 167 /* |
1257
e38f5869e9df
don't reset in send_redirect and other improvements
Franklin Schmidt <fschmidt@gmail.com>
parents:
1256
diff
changeset
|
168 public LuanState getLuan() { |
e38f5869e9df
don't reset in send_redirect and other improvements
Franklin Schmidt <fschmidt@gmail.com>
parents:
1256
diff
changeset
|
169 return luan; |
e38f5869e9df
don't reset in send_redirect and other improvements
Franklin Schmidt <fschmidt@gmail.com>
parents:
1256
diff
changeset
|
170 } |
1264 | 171 */ |
1160 | 172 @Override public Response handle(Request request) { |
1167 | 173 if( request.path.endsWith("/") ) |
174 return null; | |
175 String modName = "site:" + request.path +".luan"; | |
176 return handle(request,modName); | |
177 } | |
178 | |
179 Response handle(Request request,String modName) { | |
1264 | 180 return instance.handle(request,modName); |
175
bdbd4740121f
finish web server
fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
parents:
diff
changeset
|
181 } |
786
fe63c508a177
add Http.reset_luan()
Franklin Schmidt <fschmidt@gmail.com>
parents:
785
diff
changeset
|
182 |
1231 | 183 public void close() { |
1264 | 184 instance.close(); |
517
8dcf9e12446b
add Luan.on_luan_close()
Franklin Schmidt <fschmidt@gmail.com>
parents:
494
diff
changeset
|
185 } |
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1171
diff
changeset
|
186 |
743
2c41f2aec92f
improve Rpc and implement rpc call for local webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
693
diff
changeset
|
187 public Object call_rpc(String fnName,Object... args) throws LuanException { |
1264 | 188 return instance.call_rpc(fnName,args); |
743
2c41f2aec92f
improve Rpc and implement rpc call for local webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
693
diff
changeset
|
189 } |
2c41f2aec92f
improve Rpc and implement rpc call for local webserver
Franklin Schmidt <fschmidt@gmail.com>
parents:
693
diff
changeset
|
190 |
1186 | 191 public void reset_luan() { |
1264 | 192 new Thread() { |
193 public void run() { | |
194 instance.lock.writeLock().lock(); | |
195 try { | |
196 instance.close(); | |
197 instance = new Instance(); | |
198 } finally { | |
199 instance.lock.writeLock().unlock(); | |
200 } | |
201 } | |
202 }.start(); | |
1186 | 203 } |
204 | |
786
fe63c508a177
add Http.reset_luan()
Franklin Schmidt <fschmidt@gmail.com>
parents:
785
diff
changeset
|
205 public Object runLuan(String sourceText,String sourceName) throws LuanException { |
1264 | 206 return instance.runLuan(sourceText,sourceName); |
786
fe63c508a177
add Http.reset_luan()
Franklin Schmidt <fschmidt@gmail.com>
parents:
785
diff
changeset
|
207 } |
fe63c508a177
add Http.reset_luan()
Franklin Schmidt <fschmidt@gmail.com>
parents:
785
diff
changeset
|
208 |
1263
382c444a6c77
add Http.eval_in_root and Http.handle_error
Franklin Schmidt <fschmidt@gmail.com>
parents:
1257
diff
changeset
|
209 public void eval_in_root(String text) throws LuanException { |
1264 | 210 Instance newInstance = this.instance.cloneInstance(); |
211 BasicLuan.load(text,"<eval_in_root>",null).call(newInstance.luan); | |
212 this.instance = newInstance; | |
1263
382c444a6c77
add Http.eval_in_root and Http.handle_error
Franklin Schmidt <fschmidt@gmail.com>
parents:
1257
diff
changeset
|
213 } |
382c444a6c77
add Http.eval_in_root and Http.handle_error
Franklin Schmidt <fschmidt@gmail.com>
parents:
1257
diff
changeset
|
214 |
1004
3fa54d9d19cd
better handling of BindException
Franklin Schmidt <fschmidt@gmail.com>
parents:
1000
diff
changeset
|
215 public static void start(Server server) throws Exception { |
3fa54d9d19cd
better handling of BindException
Franklin Schmidt <fschmidt@gmail.com>
parents:
1000
diff
changeset
|
216 try { |
3fa54d9d19cd
better handling of BindException
Franklin Schmidt <fschmidt@gmail.com>
parents:
1000
diff
changeset
|
217 server.start(); |
3fa54d9d19cd
better handling of BindException
Franklin Schmidt <fschmidt@gmail.com>
parents:
1000
diff
changeset
|
218 } catch(BindException e) { |
3fa54d9d19cd
better handling of BindException
Franklin Schmidt <fschmidt@gmail.com>
parents:
1000
diff
changeset
|
219 throw new LuanException(e.toString()); |
3fa54d9d19cd
better handling of BindException
Franklin Schmidt <fschmidt@gmail.com>
parents:
1000
diff
changeset
|
220 } |
3fa54d9d19cd
better handling of BindException
Franklin Schmidt <fschmidt@gmail.com>
parents:
1000
diff
changeset
|
221 } |
1077
ca968ef1747a
better handling of BindException
Franklin Schmidt <fschmidt@gmail.com>
parents:
800
diff
changeset
|
222 |
175
bdbd4740121f
finish web server
fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
parents:
diff
changeset
|
223 } |