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());
+		}
+	}
+
+}