Mercurial Hosting > luan
diff src/luan/modules/http/jetty/LuanHandler.java @ 1136:d30d400fd43d
add http/jetty
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 29 Jan 2018 17:50:49 -0700 |
parents | src/luan/modules/http/LuanHandler.java@e15be31cee92 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/modules/http/jetty/LuanHandler.java Mon Jan 29 17:50:49 2018 -0700 @@ -0,0 +1,171 @@ +package luan.modules.http.jetty; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.BindException; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.AbstractHandler; +import luan.Luan; +import luan.LuanState; +import luan.LuanTable; +import luan.LuanFunction; +import luan.LuanJavaFunction; +import luan.LuanCloner; +import luan.LuanException; +import luan.modules.PackageLuan; + + +public class LuanHandler extends AbstractHandler { + private final LuanState luanInit; + private final Logger logger; + private String welcomeFile = "index.html"; + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private LuanState luan; + + private static final Method resetLuanMethod; + static { + try { + resetLuanMethod = LuanHandler.class.getMethod("reset_luan"); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public LuanHandler(LuanState luan,String loggerRoot) { + this.luanInit = luan; + if( loggerRoot==null ) + loggerRoot = ""; + logger = LoggerFactory.getLogger(loggerRoot+LuanHandler.class.getName()); + try { + LuanTable Http = (LuanTable)PackageLuan.require(luanInit,"luan:http/Http.luan"); + Http.rawPut( "reset_luan", new LuanJavaFunction(resetLuanMethod,this) ); + } catch(LuanException e) { + throw new RuntimeException(e); + } + } + + @Override public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) + throws IOException + { + if( target.endsWith("/") ) + target += welcomeFile; + Thread thread = Thread.currentThread(); + String oldName = thread.getName(); + thread.setName(request.getHeader("host")+request.getRequestURI()); + lock.readLock().lock(); + try { + if( !HttpServicer.service(luan,request,response,"site:"+target+".luan") ) + return; + } catch(LuanException e) { +//e.printStackTrace(); + String err = e.getLuanStackTraceString(); + logger.error(err); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,err); + } finally { + lock.readLock().unlock(); + thread.setName(oldName); + } + baseRequest.setHandled(true); + } + + public void setWelcomeFile(String welcomeFile) { + this.welcomeFile = welcomeFile; + } + + @Override protected void doStart() throws Exception { +// Thread.dumpStack(); +//System.out.println("qqqqqqqqqqqqqqqqqqqq doStart "+this); + setLuan(); + super.doStart(); + } + + @Override protected void doStop() throws Exception { + synchronized(luan) { + luan.close(); + } +//System.out.println("qqqqqqqqqqqqqqqqqqqq doStop "+this); + super.doStop(); + } +/* + @Override public void destroy() { +System.out.println("qqqqqqqqqqqqqqqqqqqq destroy "+this); + super.destroy(); + } +*/ + + public Object call_rpc(String fnName,Object... args) throws LuanException { + lock.readLock().lock(); + try { + LuanFunction fn; + LuanState luan = this.luan; + synchronized(luan) { + PackageLuan.enableLoad(luan,"luan:Rpc.luan"); + LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan"); + LuanTable fns = (LuanTable)rpc.get(luan,"functions"); + fn = (LuanFunction)fns.get(luan,fnName); + if( fn == null ) + throw new LuanException( "function not found: " + fnName ); + LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); + luan = (LuanState)cloner.clone(luan); + fn = (LuanFunction)cloner.get(fn); + } + return fn.call(luan,args); + } finally { + lock.readLock().unlock(); + } + } + + public void reset_luan() { + new Thread() { + public void run() { + lock.writeLock().lock(); + try { + synchronized(luan) { + luan.close(); + setLuan(); + } + } catch(IOException e) { + logger.error("reset_luan failed",e); + } finally { + lock.writeLock().unlock(); + } + } + }.start(); + } + + private void setLuan() { + LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); + luan = (LuanState)cloner.clone(luanInit); + try { + PackageLuan.load(luan,"site:/init.luan"); + } catch(LuanException e) { + String err = e.getLuanStackTraceString(); + logger.error(err); + } + } + + public Object runLuan(String sourceText,String sourceName) throws LuanException { + LuanFunction fn = Luan.load(sourceText,sourceName); + synchronized(luan) { + LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); + LuanState luan = (LuanState)cloner.clone(this.luan); + return fn.call(luan); + } + } + + public static void start(Server server) throws Exception { + try { + server.start(); + } catch(BindException e) { + throw new LuanException(e.toString()); + } + } + +}