changeset 1211:f67628bd3582

remove jetty
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 12 Mar 2018 16:32:55 -0600
parents 3db95cc00d09
children 220228bf1af9
files lib/jetty-continuation-8.1.15.v20140411.jar lib/jetty-http-8.1.15.v20140411.jar lib/jetty-io-8.1.15.v20140411.jar lib/jetty-server-8.1.15.v20140411.jar lib/jetty-util-8.1.15.v20140411.jar lib/servlet-api-3.0.jar src/luan/host/jetty/Backup.java src/luan/host/jetty/Init.luan src/luan/host/jetty/WebHandler.java src/luan/host/jetty/run.luan src/luan/modules/http/jetty/AuthenticationHandler.java src/luan/modules/http/jetty/Http.luan src/luan/modules/http/jetty/HttpServicer.java src/luan/modules/http/jetty/LuanHandler.java src/luan/modules/http/jetty/NotFound.java src/luan/modules/http/jetty/Server.luan src/luan/modules/http/jetty/serve.luan
diffstat 17 files changed, 0 insertions(+), 1266 deletions(-) [+]
line wrap: on
line diff
diff -r 3db95cc00d09 -r f67628bd3582 lib/jetty-continuation-8.1.15.v20140411.jar
Binary file lib/jetty-continuation-8.1.15.v20140411.jar has changed
diff -r 3db95cc00d09 -r f67628bd3582 lib/jetty-http-8.1.15.v20140411.jar
Binary file lib/jetty-http-8.1.15.v20140411.jar has changed
diff -r 3db95cc00d09 -r f67628bd3582 lib/jetty-io-8.1.15.v20140411.jar
Binary file lib/jetty-io-8.1.15.v20140411.jar has changed
diff -r 3db95cc00d09 -r f67628bd3582 lib/jetty-server-8.1.15.v20140411.jar
Binary file lib/jetty-server-8.1.15.v20140411.jar has changed
diff -r 3db95cc00d09 -r f67628bd3582 lib/jetty-util-8.1.15.v20140411.jar
Binary file lib/jetty-util-8.1.15.v20140411.jar has changed
diff -r 3db95cc00d09 -r f67628bd3582 lib/servlet-api-3.0.jar
Binary file lib/servlet-api-3.0.jar has changed
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/host/jetty/Backup.java
--- a/src/luan/host/jetty/Backup.java	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-package luan.host.jetty;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.util.Map;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.lucene.index.SnapshotDeletionPolicy;
-import org.apache.lucene.index.IndexCommit;
-import org.apache.lucene.store.FSDirectory;
-import luan.LuanState;
-import luan.LuanTable;
-import luan.LuanException;
-import luan.modules.PackageLuan;
-import luan.modules.lucene.LuceneIndex;
-import luan.host.Log4j;
-
-
-public final class Backup {
-	private static final Logger logger = LoggerFactory.getLogger(Backup.class);
-
-	private Backup() {}  // never
-
-	private static void mkdir(File dir) {
-		if( !dir.mkdirs() )
-			throw new RuntimeException("couldn't make "+dir);
-	}
-
-	private static void link(File from,File to) throws IOException {
-		Files.createLink( to.toPath(), from.toPath() );
-	}
-
-	private static void backupNonlocal(File from,File to) throws IOException {
-		mkdir(to);
-		for( File fromChild : from.listFiles() ) {
-			File toChild = new File( to, fromChild.getName() );
-			if( fromChild.isDirectory() ) {
-				if( !fromChild.getName().equals("local") )
-					backupNonlocal( fromChild, toChild );
-			} else if( fromChild.isFile() ) {
-				link( fromChild, toChild );
-			} else {
-				throw new RuntimeException(fromChild+" isn't dir or file");
-			}
-		}
-	}
-
-	private static final String getLucenes =
-		"local Lucene = require 'luan:lucene/Lucene.luan'\n"
-		+"local Table = require 'luan:Table.luan'\n"
-		+"return Table.copy(Lucene.instances)\n"
-	;
-
-	private static void backupLucene(File from,File to) throws IOException {
-		if( !new File(from,"site/init.luan").exists() ) {
-			return;
-		}
-		String fromPath = from.getCanonicalPath() + "/";
-		LuanTable luceneInstances;
-		LuanState luan = null;
-		try {
-			if( WebHandler.isServing() ) {
-				luceneInstances = (LuanTable)WebHandler.runLuan( from.getName(), getLucenes, "getLucenes" );
-			} else {
-				luan = new LuanState();
-				WebHandler.initLuan( luan, from.toString(), from.getName() );
-				PackageLuan.load(luan,"site:/init.luan");
-				luceneInstances = (LuanTable)luan.eval(getLucenes);
-			}
-		} catch(LuanException e) {
-			throw new RuntimeException(e);
-		}
-		for( Map.Entry entry : luceneInstances.rawIterable() ) {
-			LuanTable tbl = (LuanTable)entry.getKey();
-			LuceneIndex li = (LuceneIndex)tbl.rawGet("java");
-			SnapshotDeletionPolicy snapshotDeletionPolicy = li.snapshotDeletionPolicy();
-			IndexCommit ic = snapshotDeletionPolicy.snapshot();
-			try {
-				FSDirectory fsdir = (FSDirectory)ic.getDirectory();
-				File dir = fsdir.getDirectory();
-				String dirPath = dir.toString();
-				if( !dirPath.startsWith(fromPath) )
-					throw new RuntimeException(fromPath+" "+dirPath);
-				File toDir = new File( to, dirPath.substring(fromPath.length()) );
-				mkdir(toDir);
-				for( String name : ic.getFileNames() ) {
-					link( new File(dir,name), new File(toDir,name) );
-				}
-			} finally {
-				snapshotDeletionPolicy.release(ic);
-			}
-		}
-		if( luan != null )
-			luan.close();
-	}
-
-	public static void backup(File sitesDir,File backupDir) throws IOException {
-		mkdir(backupDir);
-		for( File siteDir : sitesDir.listFiles() ) {
-			File to = new File( backupDir, siteDir.getName() );
-			backupNonlocal( siteDir, to );
-			backupLucene( siteDir, to );
-		}
-	}
-
-	public static void main(String[] args) throws Exception {
-		Log4j.initForConsole();
-		backup( new File(args[0]), new File(args[1]) );
-		System.exit(0);
-	}
-}
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/host/jetty/Init.luan
--- a/src/luan/host/jetty/Init.luan	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-local Package = require "luan:Package.luan"
-Package.loaded["luan:http/Http.luan"] = require "luan:http/jetty/Http.luan"
-
-local Luan = require "luan:Luan.luan"
-local error = Luan.error
-local String = require "luan:String.luan"
-local gsub = String.gsub or error()
-local Io = require "luan:Io.luan"
-local Http = require "luan:http/Http.luan"
-local Hosting = require "luan:host/Hosting.luan"
-local Mail = require "luan:mail/Mail.luan"
-
-
-local Init = {}
-
-local dir, domain = ...
-
-Init.password = Luan.do_file(dir.."/info.luan").password or error()
-
-Http.dir = "file:"..dir.."/site"
-
-function Io.schemes.site(path,loading)
-	return Io.uri( Http.dir..path, loading )
-end
-
-Hosting.domain = domain
-Io.password = Init.password
-
-
--- logging
-
-java()
-local Logger = require "java:org.apache.log4j.Logger"
-local Logging = require "luan:logging/Logging.luan"
-
-local root = gsub(domain,"\.",":")
-
-Logging.layout = "%d %-5p %c{-1} - %m%n"
-Logging.file = dir.."/site/private/local/logs/luan.log"
-Logging.max_file_size = "1MB"
-local one_mb = 1048576
-
-local log_dir = dir.."/site/private/local/logs/"
-Logging.appenders = {
-	[log_dir.."error.log"] = "ERROR"
-	[log_dir.."warn.log"] = "WARN"
-	[log_dir.."info.log"] = "INFO"
-}
-
-Logging.log4j_root_logger = Logger.getLogger(root)
-Logging.log4j_root_logger.setAdditivity(false)
-
-local old_log_to_file = Logging.log_to_file
-
-function Logging.log_to_file(file,logger_name)
-	Io.schemes.file(file)  -- security check
-	logger_name = logger_name and root .. "." .. logger_name
-	local appender = old_log_to_file(file,logger_name)
-	appender.getMaximumFileSize() <= one_mb or error "Logging.max_file_size is too big"
-	return appender
-end
-
-local old_init = Logging.init
-
-function Logging.init()
-	Logging.appenders["System.err"] = nil
-	Logging.appenders["System.out"] = nil
-	old_init()
-end
-
-Logging.init()
-
-local old_logger = Logging.logger
-
-function Logging.root_logger()
-	return old_logger(root)
-end
-
-function Logging.logger(name)
-	return old_logger( root .. "." .. name )
-end
-
-Init.logger_root = root.."."
-
-
--- mail  - fix later
-
-Hosting.send_mail = Mail.Sender{
-	host = "smtpcorp.com";
-	username = "smtp@luanhost.com";  -- ?
-	password = "luanhost";
-	port = 2525;
-}.send
-
-
-return Init
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/host/jetty/WebHandler.java
--- a/src/luan/host/jetty/WebHandler.java	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-package luan.host.jetty;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.TimeZone;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-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.Handler;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.NCSARequestLog;
-import org.eclipse.jetty.server.handler.AbstractHandler;
-import org.eclipse.jetty.server.handler.ResourceHandler;
-import org.eclipse.jetty.server.handler.HandlerList;
-import org.eclipse.jetty.server.handler.RequestLogHandler;
-import org.eclipse.jetty.server.handler.DefaultHandler;
-import org.eclipse.jetty.server.handler.HandlerCollection;
-import luan.Luan;
-import luan.LuanState;
-import luan.LuanException;
-import luan.LuanTable;
-import luan.LuanFunction;
-import luan.modules.IoLuan;
-import luan.modules.JavaLuan;
-import luan.modules.PackageLuan;
-import luan.modules.http.jetty.LuanHandler;
-import luan.modules.http.jetty.AuthenticationHandler;
-import luan.modules.http.jetty.NotFound;
-
-
-public class WebHandler extends AbstractHandler {
-	private static final Logger logger = LoggerFactory.getLogger(WebHandler.class);
-
-	private static class Site {
-		final Handler handler;
-		final LuanHandler luanHandler;
-
-		Site(Handler handler,LuanHandler luanHandler) {
-			this.handler = handler;
-			this.luanHandler = luanHandler;
-		}
-	}
-
-	public static String allowJavaFileName = "allow_java";  // change for security
-	private static final String tz = TimeZone.getDefault().getID();
-	private static final Map<String,Site> siteMap = new HashMap<String,Site>();
-	private static String sitesDir = null;
-	private static Server server = null;
-
-	public static boolean isServing() {
-		return sitesDir != null;
-	}
-
-	public WebHandler(String dir,Server server) {
-		if( sitesDir != null )
-			throw new RuntimeException("already set");
-		if( !new File(dir).exists() )
-			throw new RuntimeException();
-		this.sitesDir = dir;
-		this.server = server;
-	}
-
-	public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-		throws IOException, ServletException
-	{
-		String domain = baseRequest.getServerName();
-//		System.out.println("handle "+domain);
-		Site site = getSite(domain);
-		if( site != null ) {
-			site.handler.handle(target,baseRequest,request,response);
-		}
-	}
-
-	public static Object runLuan(String domain,String sourceText,String sourceName) throws LuanException {
-		return getSite(domain).luanHandler.runLuan(sourceText,sourceName);
-	}
-
-	public static Object callSite(String domain,String fnName,Object... args) throws LuanException {
-		return getSite(domain).luanHandler.call_rpc(fnName,args);
-	}
-
-	private static Site getSite(String domain) {
-		synchronized(siteMap) {
-			Site site = siteMap.get(domain);
-			if( site == null ) {
-				if( sitesDir==null )
-					throw new NullPointerException("sitesDir");
-				File dir = new File(sitesDir,domain);
-				if( !dir.exists() /* && !recover(dir) */ )
-					return null;
-				site = newSite(dir.toString(),domain);
-				siteMap.put(domain,site);
-			}
-			return site;
-		}
-	}
-/*
-	private static boolean recover(File dir) {
-		File backups = new File(dir.getParentFile().getParentFile(),"backups");
-		if( !backups.exists() )
-			return false;
-		String name = dir.getName();
-		File from = null;
-		for( File backup : backups.listFiles() ) {
-			File d = new File(backup,"current/"+name);
-			if( d.exists() && (from==null || from.lastModified() < d.lastModified()) )
-				from = d;
-		}
-		if( from == null )
-			return false;
-		if( !from.renameTo(dir) )
-			throw new RuntimeException("couldn't rename "+from+" to "+dir);
-		logger.info("recovered "+name+" from "+from);
-		return true;
-	}
-*/
-	static LuanTable initLuan(LuanState luan,String dir,String domain) {
-		LuanTable init;
-		try {
-			init = (LuanTable)luan.eval(
-				"local Luan = require 'luan:Luan.luan'\n"
-				+"local f = Luan.load_file 'classpath:luan/host/jetty/Init.luan'\n"
-				+"return f('"+dir+"','"+domain+"')\n"
-			);
-		} catch(LuanException e) {
-			throw new RuntimeException(e);
-		}
-		File allowJavaFile = new File(dir,"site/private/"+allowJavaFileName);
-		if( !allowJavaFile.exists() ) {
-			JavaLuan.setSecurity( luan, javaSecurity );
-			IoLuan.setSecurity( luan, ioSecurity(dir) );
-		}
-		return init;
-	}
-
-	private static Site newSite(String dir,String domain) {
-		LuanState luan = new LuanState();
-		LuanTable init = initLuan(luan,dir,domain);
-		String password = (String)init.rawGet("password");
-
-		AuthenticationHandler authenticationHandler = new AuthenticationHandler("/private/");
-		authenticationHandler.setPassword(password);
-		String loggerRoot = (String)init.rawGet("logger_root");
-		LuanHandler luanHandler = new LuanHandler(luan,loggerRoot);
-
-		ResourceHandler resourceHandler = new ResourceHandler();
-		resourceHandler.setResourceBase(dir+"/site");
-		resourceHandler.setDirectoriesListed(true);
-		resourceHandler.setAliases(true);
-
-		NotFound notFoundHandler = new NotFound(luanHandler);
-		DefaultHandler defaultHandler = new DefaultHandler();
-
-		HandlerList handlers = new HandlerList();
-		handlers.setHandlers(new Handler[]{authenticationHandler,luanHandler,resourceHandler,notFoundHandler,defaultHandler});
-
-		String logDir = dir+"/site/private/local/logs/web";
-		new File(logDir).mkdirs();
-		NCSARequestLog log = new NCSARequestLog(logDir+"/yyyy_mm_dd.log");
-		log.setExtended(false);
-		log.setLogTimeZone(tz);
-		RequestLogHandler logHandler = new RequestLogHandler();
-		logHandler.setRequestLog(log);
-
-		HandlerCollection hc = new HandlerCollection();
-		hc.setHandlers(new Handler[]{handlers,logHandler});
-//		hc.setServer(getServer());
-
-		try {
-			hc.start();
-		} catch(Exception e) {
-			throw new RuntimeException(e);
-		}
-		return new Site(hc,luanHandler);
-	}
-
-	public static void removeHandler(String domain) throws Exception {
-		synchronized(siteMap) {
-			Site site = siteMap.remove(domain);
-			if( site != null ) {
-				site.handler.stop();
-				site.handler.destroy();
-			}
-		}
-	}
-
-	public static void loadHandler(String domain) {
-		getSite(domain);
-	}
-
-	public static Server server() {
-		return server;
-	}
-
-	private static final IoLuan.Security ioSecurity(String dir) {
-		final String siteUri = "file:" + dir + "/site";
-		return new IoLuan.Security() {
-			public void check(LuanState luan,String name) throws LuanException {
-				if( name.startsWith("file:") ) {
-					if( name.contains("..") )
-						throw new LuanException("Security violation - '"+name+"' contains '..'");
-					if( !(name.equals(siteUri) || name.startsWith(siteUri+"/")) )
-						throw new LuanException("Security violation - '"+name+"' outside of site dir");
-				}
-				else if( name.startsWith("classpath:luan/host/") ) {
-					throw new LuanException("Security violation");
-				}
-				else if( name.startsWith("os:") || name.startsWith("bash:") ) {
-					throw new LuanException("Security violation");
-				}
-			}
-		};
-	}
-
-	private static final JavaLuan.Security javaSecurity = new JavaLuan.Security() {
-		public void check(LuanState luan,String name) throws LuanException {
-			if( !name.startsWith("luan:") )
-				throw new LuanException("Security violation - only luan:* modules can load Java");
-			if( name.equals("luan:logging/Logging") )
-				throw new LuanException("Security violation - cannot reload Logging");
-		}
-	};
-}
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/host/jetty/run.luan
--- a/src/luan/host/jetty/run.luan	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-require "luan:logging/init.luan"  -- initialize logging
-local Luan = require "luan:Luan.luan"
-local error = Luan.error
-local do_file = Luan.do_file or error()
-local ipairs = Luan.ipairs or error()
-local Io = require "luan:Io.luan"
-local print = Io.print or error()
-local String = require "luan:String.luan"
-local Hosting = require "luan:host/Hosting.luan"
-local Logging = require "luan:logging/Logging.luan"
-local logger = Logging.logger "run"
-java()
-local WebHandler = require "java:luan.host.jetty.WebHandler"
-Hosting.WebHandler = WebHandler
-
-local here = Io.schemes.file(".").canonical().to_string()
-Hosting.sites_dir = here.."/sites/"
-
--- tmp
-local Util = require "classpath:luan/host/Util.luan"
-local sites_dir = Io.schemes.file(Hosting.sites_dir)
-for _, site in ipairs(sites_dir.children()) do
-	local password_file = site.child("password")
-	if password_file.exists() then
-		local domain = site.name()
-		local password = password_file.read_text()
-		Util.write_password(domain,password)
-		password_file.delete()
-		logger.info("fixed password for "..domain)
-	end
-end
-
-do_file "classpath:luan/host/main.luan"
-
-
--- web server
-
-local Server = require "java:org.eclipse.jetty.server.Server"
-local DefaultHandler = require "java:org.eclipse.jetty.server.handler.DefaultHandler"
-local HandlerCollection = require "java:org.eclipse.jetty.server.handler.HandlerCollection"
-local SessionHandler = require "java:org.eclipse.jetty.server.session.SessionHandler"
-local SslSelectChannelConnector = require "java:org.eclipse.jetty.server.ssl.SslSelectChannelConnector"
-
-local server = Server.new(8080)
-
-local handlers = HandlerCollection.new()
-handlers.setHandlers {
-	SessionHandler.new(),
-	WebHandler.new(Hosting.sites_dir,server),
-	DefaultHandler.new()
-}
-server.setHandler(handlers);
-
-server.start()
-
-
---[[
-local tp = server.getThreadPool() 
-print(tp)
-print(tp.getClass())
-print("max "..tp.getMaxThreads())
-print("getMaxQueued "..tp.getMaxQueued())
-
-for _, c in ipairs(server.getConnectors()) do
-	print(c)
-	tp = c.getThreadPool() 
-	print(tp)
-end
-
-print "done"
-]]
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/modules/http/jetty/AuthenticationHandler.java
--- a/src/luan/modules/http/jetty/AuthenticationHandler.java	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-package luan.modules.http.jetty;
-
-import java.io.IOException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.AbstractHandler;
-import org.eclipse.jetty.util.B64Code;
-
-
-public class AuthenticationHandler extends AbstractHandler {
-	private final String path;
-	private String password = "password";
-
-	public AuthenticationHandler(String path) {
-		this.path = path;
-	}
-
-	public void setPassword(String password) {
-		this.password = password;
-	}
-
-	public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-		throws IOException
-	{
-		if( !target.startsWith(path) )
-			return;
-		String pwd = getPassword(request);
-		if( password.equals(pwd) )
-			return;
-		response.setHeader("WWW-Authenticate","Basic realm=\""+path+"\"");
-		response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
-		baseRequest.setHandled(true);
-	}
-
-	private static String getPassword(HttpServletRequest request) {
-		String auth = request.getHeader("Authorization");
-		if( auth==null )
-			return null;
-		String[] a = auth.split(" +");
-		if( a.length != 2 )
-			throw new RuntimeException("auth = "+auth);
-		if( !a[0].equals("Basic") )
-			throw new RuntimeException("auth = "+auth);
-		auth = new String(B64Code.decode(a[1]));
-		a = auth.split(":");
-		if( a.length != 2 )
-			throw new RuntimeException("auth = "+auth);
-		return a[1];
-	}
-}
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/modules/http/jetty/Http.luan
--- a/src/luan/modules/http/jetty/Http.luan	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-java()
-local Luan = require "luan:Luan.luan"
-local error = Luan.error
-local ipairs = Luan.ipairs or error()
-local pairs = Luan.pairs or error()
-local set_metatable = Luan.set_metatable or error()
-local type = Luan.type or error()
-local Io = require "luan:Io.luan"
-local Html = require "luan:Html.luan"
-local url_encode = Html.url_encode or error()
-local Table = require "luan:Table.luan"
-local clear = Table.clear or error()
-local Package = require "luan:Package.luan"
-local String = require "luan:String.luan"
-local matches = String.matches or error()
-local HttpServicer = require "java:luan.modules.http.jetty.HttpServicer"
-local IoLuan = require "java:luan.modules.IoLuan"
-
-
-local Http = {}
-
-Http.version = "jetty"
-
-local function sent_error(_,_,_)
-	error "headers are not accessible after you start writing content"
-end
-
-local sent_error_metatable = { __index=sent_error, __new_index=sent_error }
-
-function Http.sent_headers(headers)
-	clear(headers)
-	set_metatable(headers,sent_error_metatable)
-end
-
-
-local function new_common(this)
-	this = this or {}
-	this.headers = {}
-	return this
-end
-
-local function to_list(input)
-	return type(input) == "table" and input or {input}
-end
-
-
-function Http.new_request(this)
-	this = new_common(this)
-	this.method = "GET"  -- default
-	-- this.path
-	-- this.protocol
-	this.scheme = "http"  -- default
-	this.port = 80  -- default
-	this.parameters = {}
-	this.cookies = {}
-
-	function this.query_string()
-		local string_uri = Io.uri "string:"
-		local out = string_uri.text_writer()
-		local and_char = ""
-		for name, values in pairs(this.parameters) do
-			for _, value in ipairs(to_list(values)) do
-				out.write( and_char, url_encode(name), "=", url_encode(value) )
-				and_char = "&"
-			end
-		end
-		out.close()
-		local s = string_uri.read_text()
-		return s ~= "" and s or nil
-	end
-
-	function this.full_path()  -- compatible with impl
-		local path = this.path
-		if this.method ~= "POST" then
-			local query = this.query_string()
-			if query ~= nil then
-				path = path.."?"..query
-			end
-		end
-		return path
-	end
-
-	function this.url()
-		return this.scheme.."://"..this.headers["host"]..this.full_path()
-	end
-
-	return this
-end
-
-local STATUS = {
-	OK = 200
-	MOVED_PERMANENTLY = 301
-	-- add more as needed
-}
-Http.STATUS = STATUS
-
-function Http.new_response(this)
-	this = new_common(this)
-	this.status = STATUS.OK
-	if this.java ~= nil then
-		this.send_redirect = this.java.sendRedirect
-		this.send_error = this.java.sendError
-
-		function this.set_cookie(name,value,attributes)
-			HttpServicer.setCookie(Http.request.java,this.java,name,value,attributes)
-		end
-
-		function this.set_persistent_cookie(name,value,attributes)
-			attributes = attributes or {}
-			attributes["Max-Age"] = "10000000"
-			this.set_cookie(name,value,attributes)
-		end
-
-		function this.remove_cookie(name,attributes)
-			attributes = attributes or {}
-			attributes["Max-Age"] = "0"
-			this.set_cookie(name,"delete",attributes)
-		end
-
-		function this.set()
-			HttpServicer.setResponse(this,this.java)
-			Http.sent_headers(this.headers)
-		end
-
-		function this.text_writer()
-			this.java.setCharacterEncoding "UTF-8"
-			this.java.setContentType "text/html; charset=UTF-8"
-			this.set()
-			return IoLuan.textWriter(this.java.getWriter())
-		end
-
-		function this.binary_writer()
-			this.set()
-			return IoLuan.binaryWriter(this.java.getOutputStream())
-		end
-
-		function this.reset()
-			this.java.reset()
-			set_metatable(this.headers,nil)
-		end
-	end
-	return this
-end
-
--- request = new_request{}  -- filled in by HttpServicer
--- response = new_response{}  -- filled in by HttpServicer
-
-
-function Http.uncache_site()
-	for k in pairs(Table.copy(Package.loaded)) do
-		if matches(k,"^site:") then
-			Package.loaded[k] = nil
-		end
-	end
-end
-
-return Http
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/modules/http/jetty/HttpServicer.java
--- a/src/luan/modules/http/jetty/HttpServicer.java	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-package luan.modules.http.jetty;
-
-import java.io.InputStream;
-import java.io.BufferedInputStream;
-import java.io.PrintWriter;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Set;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Enumeration;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.ServletException;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.Part;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.eclipse.jetty.util.MultiPartInputStream;
-import luan.Luan;
-import luan.LuanState;
-import luan.LuanFunction;
-import luan.LuanException;
-import luan.LuanTable;
-import luan.LuanCloner;
-import luan.modules.PackageLuan;
-import luan.modules.IoLuan;
-import luan.modules.TableLuan;
-import luan.modules.Utils;
-import luan.modules.url.LuanUrl;
-
-
-public final class HttpServicer {
-	private static final Logger logger = LoggerFactory.getLogger(HttpServicer.class);
-
-	public static boolean service(LuanState luan,HttpServletRequest request,HttpServletResponse response,String modName)
-		throws LuanException
-	{
-		LuanFunction fn;
-		synchronized(luan) {
-			PackageLuan.enableLoad(luan,"luan:http/Http.luan",modName);
-			LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http.luan");
-			Object mod = PackageLuan.load(luan,modName);
-			if( mod.equals(Boolean.FALSE) )
-				return false;
-			if( !(mod instanceof LuanFunction) )
-				throw new LuanException( "module '"+modName+"' must return a function" );
-			LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
-			luan = (LuanState)cloner.clone(luan);
-			fn = (LuanFunction)cloner.get(mod);
-		}
-
-		LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http.luan");
-
-		// request
-		LuanFunction newRequestFn = (LuanFunction)module.rawGet("new_request");
-		LuanTable requestTbl = (LuanTable)newRequestFn.call(luan);
-		module.rawPut("request",requestTbl);
-		requestTbl.rawPut("java",request);
-		requestTbl.rawPut("method",request.getMethod());
-		requestTbl.rawPut("path",request.getRequestURI());
-		requestTbl.rawPut("protocol",request.getProtocol());
-		requestTbl.rawPut("scheme",request.getScheme());
-		requestTbl.rawPut("port",request.getServerPort());
-
-		LuanTable headersTbl = (LuanTable)requestTbl.rawGet("headers");
-		for( Enumeration<String> enKeys = request.getHeaderNames(); enKeys.hasMoreElements(); ) {
-			String key = enKeys.nextElement();
-			List<String> values = new ArrayList<String>();
-			for( Enumeration<String> en = request.getHeaders(key); en.hasMoreElements(); ) {
-				values.add(en.nextElement());
-			}
-			int size = values.size();
-			if(size==0) throw new RuntimeException();
-			key = key.toLowerCase();
-			Object value = size==1 ? values.get(0) : new LuanTable(values);
-			headersTbl.rawPut(key,value);
-		}
-
-		LuanTable parametersTbl = (LuanTable)requestTbl.rawGet("parameters");
-		String contentType = request.getContentType();
-		if( contentType==null || !contentType.startsWith("multipart/form-data") ) {
-			for( Map.Entry<String,String[]> entry : request.getParameterMap().entrySet() ) {
-				String[] a = entry.getValue();
-				Object value = a.length==1 ? a[0] : new LuanTable(Arrays.asList(a));
-				parametersTbl.rawPut(entry.getKey(),value);
-			}
-		} else {  // multipart
-			try {
-				InputStream in = new BufferedInputStream(request.getInputStream());
-				final MultiPartInputStream mpis = new MultiPartInputStream(in,contentType,null,null);
-				mpis.setDeleteOnExit(true);
-				for( Part p : mpis.getParts() ) {
-					final MultiPartInputStream.MultiPart part = (MultiPartInputStream.MultiPart)p;
-					String name = part.getName();
-/*
-System.out.println("name = "+name);
-System.out.println("getContentType = "+part.getContentType());
-System.out.println("getHeaderNames = "+part.getHeaderNames());
-System.out.println("content-disposition = "+part.getHeader("content-disposition"));
-System.out.println();
-*/
-					Object value;
-					String filename = part.getContentDispositionFilename();
-					if( filename == null ) {
-						value = new String(part.getBytes());
-					} else {
-						LuanTable partTbl = new LuanTable();
-						partTbl.rawPut("filename",filename);
-						partTbl.rawPut("content_type",part.getContentType());
-						{
-							InputStream inPart = part.getInputStream();
-							byte[] content = Utils.readAll(inPart);
-							inPart.close();
-							partTbl.rawPut("content",content);
-						}
-						value = partTbl;
-					}
-					Object obj = parametersTbl.rawGet(name);
-					if( obj == null ) {
-						parametersTbl.rawPut(name,value);
-					} else if( obj instanceof LuanTable && ((LuanTable)obj).isList() ) {
-						LuanTable list = (LuanTable)obj;
-						list.rawPut(list.rawLength()+1,value);
-					} else {
-						LuanTable list = new LuanTable();
-						list.rawPut(1,obj);
-						list.rawPut(2,value);
-						parametersTbl.rawPut(name,list);
-					}
-				}
-			} catch(IOException e) {
-				throw new RuntimeException(e);
-			} catch(ServletException e) {
-				throw new RuntimeException(e);
-			}
-		}
-
-		LuanTable cookieTbl = (LuanTable)requestTbl.rawGet("cookies");
-		for( Cookie cookie : request.getCookies() ) {
-			cookieTbl.rawPut( cookie.getName(), unescape(cookie.getValue()) );
-		}
-
-
-		// response
-		LuanTable responseTbl = new LuanTable();
-		responseTbl.rawPut("java",response);
-		LuanFunction newResponseFn = (LuanFunction)module.rawGet("new_response");
-		newResponseFn.call( luan, new Object[]{responseTbl} );
-		module.rawPut("response",responseTbl);
-
-		fn.call(luan);
-		return true;
-	}
-
-	public static void setResponse(LuanTable responseTbl,HttpServletResponse response) throws LuanException {
-		int status = Luan.asInteger(responseTbl.rawGet("status"));
-		response.setStatus(status);
-		LuanTable responseHeaders = (LuanTable)responseTbl.rawGet("headers");
-		for( Map.Entry<Object,Object> entry : responseHeaders.rawIterable() ) {
-			String name = (String)entry.getKey();
-			Object val = entry.getValue();
-			if( val instanceof LuanTable ) {
-				LuanTable values = (LuanTable)val;
-				for( Object value : values.asList() ) {
-					setResponse(response,name,value);
-				}
-			} else {
-				setResponse(response,name,val);
-			}
-		}
-	}
-
-	private static void setResponse(HttpServletResponse response,String name,Object value) throws LuanException {
-		if( value instanceof String ) {
-			response.setHeader(name,(String)value);
-			return;
-		}
-		Integer i = Luan.asInteger(value);
-		if( i != null ) {
-			response.setIntHeader(name,i);
-			return;
-		}
-		throw new IllegalArgumentException("value must be string or integer for headers table");
-	}
-
-
-
-	// static utils
-
-	private static String escape(String value) {
-		return value.replaceAll(";", "%3B");
-	}
-
-	private static String unescape(String value) {
-		return value.replaceAll("%3B", ";");
-	}
-
-	private static Cookie getCookie(HttpServletRequest request,String name) {
-		Cookie[] cookies = request.getCookies();
-		if( cookies == null )
-			return null;
-		for (Cookie cookie : cookies) {
-			if (cookie.getName().equals(name))
-				return cookie;
-		}
-		return null;
-	}
-
-	public static void setCookie(HttpServletRequest request,HttpServletResponse response,String name,String value,LuanTable attributes) {
-		Cookie cookie = getCookie(request,name);
-		if( cookie==null || !cookie.getValue().equals(value) ) {
-			cookie = new Cookie(name, escape(value));
-			if( attributes != null ) {
-				String path = (String)attributes.rawGet("Path");
-				if( path != null )
-					cookie.setPath(path);
-				String domain = (String)attributes.rawGet("Domain");
-				if (domain != null && domain.length() > 0)
-					cookie.setDomain(domain);
-				String maxAge = (String)attributes.rawGet("Max-Age");
-				if( maxAge != null )
-					cookie.setMaxAge(Integer.parseInt(maxAge));
-			}
-			response.addCookie(cookie);
-		}
-	}
-
-}
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/modules/http/jetty/LuanHandler.java
--- a/src/luan/modules/http/jetty/LuanHandler.java	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-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());
-		}
-	}
-
-}
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/modules/http/jetty/NotFound.java
--- a/src/luan/modules/http/jetty/NotFound.java	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-package luan.modules.http.jetty;
-
-import java.io.IOException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.AbstractHandler;
-
-
-public class NotFound extends AbstractHandler {
-	private final LuanHandler luanHandler;
-
-	public NotFound(LuanHandler luanHandler) {
-		this.luanHandler = luanHandler;
-	}
-
-	@Override public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
-		throws IOException
-	{
-		luanHandler.handle("/not_found",baseRequest,request,response);
-	}
-
-}
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/modules/http/jetty/Server.luan
--- a/src/luan/modules/http/jetty/Server.luan	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-local Luan = require "luan:Luan.luan"
-local error = Luan.error
-local String = require "luan:String.luan"
-local gsub = String.gsub or error()
-local matches = String.matches or error()
-local Io = require "luan:Io.luan"
-local Package = require "luan:Package.luan"
-local Rpc = require "luan:Rpc.luan"
-local Thread = require "luan:Thread.luan"
-local Http = require "luan:http/Http.luan"
-require "luan:logging/init.luan"  -- initialize logging
-local Logging = require "luan:logging/Logging.luan"
-local logger = Logging.logger "http/Server"
-
-java()
-local TimeZone = require "java:java.util.TimeZone"
-local JavaServer = require "java:org.eclipse.jetty.server.Server"
-local NCSARequestLog = require "java:org.eclipse.jetty.server.NCSARequestLog"
-local DefaultHandler = require "java:org.eclipse.jetty.server.handler.DefaultHandler"
-local HandlerList = require "java:org.eclipse.jetty.server.handler.HandlerList"
-local HandlerCollection = require "java:org.eclipse.jetty.server.handler.HandlerCollection"
-local ResourceHandler = require "java:org.eclipse.jetty.server.handler.ResourceHandler"
-local RequestLogHandler = require "java:org.eclipse.jetty.server.handler.RequestLogHandler"
-local ContextHandler = require "java:org.eclipse.jetty.server.handler.ContextHandler"
-local GzipHandler = require "java:org.eclipse.jetty.server.handler.GzipHandler"
-local HandlerWrapper = require "java:org.eclipse.jetty.server.handler.HandlerWrapper"
-local SessionHandler = require "java:org.eclipse.jetty.server.session.SessionHandler"
-local AuthenticationHandler = require "java:luan.modules.http.jetty.AuthenticationHandler"
-local LuanHandler = require "java:luan.modules.http.jetty.LuanHandler"
-local NotFound = require "java:luan.modules.http.jetty.NotFound"
-
-local Server = {}
-
-Server.port = 8080
-
-Server.welcome_file = "index.html"
-
-
-Server.luan_handler = LuanHandler.new()
-
-Server.resource_handler = ResourceHandler.new()
-Server.resource_handler.setDirectoriesListed(true)
-
-Server.handlers = HandlerList.new()
-Server.handlers.setHandlers { Server.luan_handler, Server.resource_handler }
-
-function Server.add_folder(context,dir)
-	local rh = ResourceHandler.new()
-	rh.setResourceBase(dir)
-	rh.setDirectoriesListed(true)
-	local ch = ContextHandler.new(context)
-	ch.setHandler(rh)
-	Server.handlers.addHandler(ch)
-	return rh
-end
-
-Server.handler_wrapper = HandlerWrapper.new()
-Server.handler_wrapper.setHandler(Server.handlers)
-
-function Server.zip()
-	local h = GzipHandler.new()
-	h.setHandler(Server.handler_wrapper.getHandler())
-	Server.handler_wrapper.setHandler(h)
-end
-
-Server.log = NCSARequestLog.new()
-Server.log.setExtended(false)
-Server.log.setLogTimeZone(TimeZone.getDefault().getID())
-Server.log_handler = RequestLogHandler.new()
-Server.log_handler.setRequestLog(Server.log)
-
-function Server.set_log_file(file_name)
-	Server.log.setFilename(file_name)
-end
-
-local hc = HandlerCollection.new()
-hc.setHandlers { SessionHandler.new(), Server.handler_wrapper, DefaultHandler.new(), Server.log_handler }
-
-
-function Server.init(dir)
-	dir = gsub(dir,"/$","")  -- remove trailing '/' if any
-	Http.dir = dir
-	function Io.schemes.site(path)
-		return Io.uri( dir..path )
-	end
-	local base = dir
-	if matches(base,"^classpath:") then
-		base = dir.."#"..Server.welcome_file.."#"..Server.welcome_file..".luan"
-	end
-	Server.resource_handler.setResourceBase(Io.uri(base).to_string())
-	Server.resource_handler.setWelcomeFiles {Server.welcome_file}
-	Server.luan_handler.setWelcomeFile(Server.welcome_file)
-	Server.handlers.addHandler(NotFound.new(Server.luan_handler))
-	Server.server = JavaServer.new(Server.port)
-	Server.server.setHandler(hc)
-end
-
-function Server.start()
-	LuanHandler.start(Server.server)
-end
-
-function Server.start_rpc()
-	function Rpc.functions.call(domain,fn_name,...)
-		return Server.luan_handler.call_rpc(fn_name,...)
-	end
-
-	Thread.fork(Rpc.serve)
-end
-
-function Server.serve(dir)
-	Server.init(dir)
-	Server.start_rpc()
-	Server.start()
-end
-
-return Server
diff -r 3db95cc00d09 -r f67628bd3582 src/luan/modules/http/jetty/serve.luan
--- a/src/luan/modules/http/jetty/serve.luan	Fri Mar 09 15:21:12 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-local Package = require "luan:Package.luan"
-Package.loaded["luan:http/Http.luan"] = require "luan:http/jetty/Http.luan"
-Package.loaded["luan:http/Server.luan"] = require "luan:http/jetty/Server.luan"
-
-local Luan = require "luan:Luan.luan"
-Luan.load_file("luan:http/serve.luan")(...)