view src/luan/modules/http/LuanHandler.java @ 1000:32d4b569567c

simplify handle()
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 19 Oct 2016 04:22:51 -0600
parents 4de7f6e9c453
children 3fa54d9d19cd
line wrap: on
line source

package luan.modules.http;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.eclipse.jetty.server.Request;
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 request,HttpServletResponse response) 
		throws IOException
	{
//Thread.dumpStack();
		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.getFullMessage();
			logger.error(err);
			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,err);
		} finally {
			lock.readLock().unlock();
			thread.setName(oldName);
		}
		request.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.getFullMessage();
			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);
		}
	}

}