changeset 1259:e8020216dee7

add Luan.to_luan and fix multipart/form-data
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 23 Sep 2018 17:58:40 -0600
parents e4d7a3114fa8
children 4b5b84853f6f
files src/luan/Luan.java src/luan/LuanJavaFunction.java src/luan/modules/Luan.luan src/luan/modules/Parsers.luan src/luan/modules/Rpc.luan src/luan/modules/Table.luan src/luan/modules/http/Http.luan src/luan/webserver/Request.java src/luan/webserver/RequestParser.java website/src/examples/upload-and-email.html.luan
diffstat 10 files changed, 113 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/Luan.java	Thu Sep 20 22:11:11 2018 -0600
+++ b/src/luan/Luan.java	Sun Sep 23 17:58:40 2018 -0600
@@ -1,5 +1,6 @@
 package luan;
 
+import java.lang.reflect.Array;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Map;
@@ -130,7 +131,7 @@
 		return load(text,sourceName,null);
 	}
 
-
+/*
 	public static Object toLuan(Object obj) throws LuanException {
 		if( !type(obj).equals("java") )
 			return obj;
@@ -173,6 +174,7 @@
 		}
 		return tbl;
 	}
+*/
 
 	public static Object toJava(Object obj) throws LuanException {
 		if( !(obj instanceof LuanTable) )
@@ -200,6 +202,36 @@
 		return v;
 	}
 
+	public static LuanTable toTable(Object obj) {
+		if( obj == null )
+			return null;
+		if( obj instanceof LuanTable )
+			return (LuanTable)obj;
+		if( obj instanceof List ) {
+			return new LuanTable((List)obj);
+		}
+		if( obj instanceof Map ) {
+			return new LuanTable((Map)obj);
+		}
+		if( obj instanceof Set ) {
+			return new LuanTable((Set)obj);
+		}
+		Class cls = obj.getClass();
+		if( cls.isArray() ) {
+			if( cls.getComponentType().isPrimitive() ) {
+				int len = Array.getLength(obj);
+				List list = new ArrayList();
+				for( int i=0; i<len; i++ ) {
+					list.add(Array.get(obj,i));
+				}
+				return new LuanTable(list);
+			} else {
+				Object[] a = (Object[])obj;
+				return new LuanTable(Arrays.asList(a));
+			}
+		}
+		return null;
+	}
 
 	private Luan() {}  // never
 }
--- a/src/luan/LuanJavaFunction.java	Thu Sep 20 22:11:11 2018 -0600
+++ b/src/luan/LuanJavaFunction.java	Sun Sep 23 17:58:40 2018 -0600
@@ -225,16 +225,7 @@
 		}
 		return RTN_SAME;
 	}
-/*
-	private static boolean isNumber(Class rtnType) {
-		return rtnType == Short.TYPE
-			|| rtnType == Integer.TYPE
-			|| rtnType == Long.TYPE
-			|| rtnType == Float.TYPE
-			|| rtnType == Double.TYPE
-		;
-	}
-*/
+
 	private interface ArgConverter {
 		public Object convert(LuanState luan,Object obj) throws LuanException;
 	}
@@ -348,32 +339,8 @@
 
 	private static final ArgConverter ARG_TABLE = new ArgConverter() {
 		public Object convert(LuanState luan,Object obj) {
-			if( obj == null )
-				return null;
-			if( obj instanceof List ) {
-				return new LuanTable((List)obj);
-			}
-			if( obj instanceof Map ) {
-				return new LuanTable((Map)obj);
-			}
-			if( obj instanceof Set ) {
-				return new LuanTable((Set)obj);
-			}
-			Class cls = obj.getClass();
-			if( cls.isArray() ) {
-				if( cls.getComponentType().isPrimitive() ) {
-					int len = Array.getLength(obj);
-					List list = new ArrayList();
-					for( int i=0; i<len; i++ ) {
-						list.add(Array.get(obj,i));
-					}
-					return new LuanTable(list);
-				} else {
-					Object[] a = (Object[])obj;
-					return new LuanTable(Arrays.asList(a));
-				}
-			}
-			return obj;
+			LuanTable tbl = Luan.toTable(obj);
+			return tbl!=null ? tbl : obj;
 		}
 		@Override public String toString() {
 			return "ARG_TABLE";
--- a/src/luan/modules/Luan.luan	Thu Sep 20 22:11:11 2018 -0600
+++ b/src/luan/modules/Luan.luan	Sun Sep 23 17:58:40 2018 -0600
@@ -1,5 +1,6 @@
 java()
 local BasicLuan = require "java:luan.modules.BasicLuan"
+local LuanJava = require "java:luan.Luan"
 
 local Luan = {}
 
@@ -37,4 +38,33 @@
 	return Luan.load( "return "..s, source_name or "eval" )()
 end
 
+
+local error = Luan.error
+local type = Luan.type or error()
+local pairs = Luan.pairs or error()
+
+-- tries to convert to luan
+function Luan.java_to_luan(obj)
+	return LuanJava.toTable(obj) or obj
+end
+
+function Luan.to_luan(obj,java_to_luan)
+	if type(obj) ~= "java" then
+		return obj
+	end
+	java_to_luan = java_to_luan or Luan.java_to_luan
+	obj = java_to_luan(obj)
+	type(obj) ~= "java" or error("can't convert type "..obj.getClass().getName().." to luan")
+	if type(obj) ~= "table" then
+		return obj
+	end
+	local tbl = {}
+	for key, value in pairs(obj) do
+		key = Luan.to_luan(key,java_to_luan)
+		value = Luan.to_luan(value,java_to_luan)
+		tbl[key] = value
+	end
+	return tbl
+end
+
 return Luan
--- a/src/luan/modules/Parsers.luan	Thu Sep 20 22:11:11 2018 -0600
+++ b/src/luan/modules/Parsers.luan	Sun Sep 23 17:58:40 2018 -0600
@@ -11,22 +11,23 @@
 Parsers.csv_to_list = Csv.toList
 Parsers.theme_to_luan = Theme.toLuan
 
-local JavaLuan = require "java:luan.Luan"
+local Luan = require "luan:Luan.luan"
+local LuanJava = require "java:luan.Luan"
 local JsonParser = require "java:luan.lib.json.JsonParser"
 local JsonToString = require "java:luan.lib.json.JsonToString"
 
 -- converts json string to luan object
 function Parsers.json_parse(s)
-	return JavaLuan.toLuan(JsonParser.parse(s))
+	return Luan.to_luan(JsonParser.parse(s))
 end
 
 -- converts luan object to json string
 function Parsers.json_string(obj)
-	return JsonToString.toString(JavaLuan.toJava(obj))
+	return JsonToString.toString(LuanJava.toJava(obj))
 end
 
 function Parsers.json_compressed_string(obj)
-	return JsonToString.toCompressedString(JavaLuan.toJava(obj))
+	return JsonToString.toCompressedString(LuanJava.toJava(obj))
 end
 
 return Parsers
--- a/src/luan/modules/Rpc.luan	Thu Sep 20 22:11:11 2018 -0600
+++ b/src/luan/modules/Rpc.luan	Sun Sep 23 17:58:40 2018 -0600
@@ -9,7 +9,7 @@
 local RpcResult = require "java:luan.lib.rpc.RpcResult"
 local RpcException = require "java:luan.lib.rpc.RpcException"
 local JavaRpc = require "java:luan.lib.rpc.Rpc"
-local JavaLuan = require "java:luan.Luan"
+local LuanJava = require "java:luan.Luan"
 local JavaUtils = require "java:luan.modules.Utils"
 local IoLuan = require "java:luan.modules.IoLuan"
 local ByteArrayInputStream = require "java:java.io.ByteArrayInputStream"
@@ -19,6 +19,7 @@
 local try = Luan.try or error()
 local ipairs = Luan.ipairs or error()
 local type = Luan.type or error()
+local to_luan = Luan.to_luan or error()
 local Io = require "luan:Io.luan"
 local Thread = require "luan:Thread.luan"
 local Table = require "luan:Table.luan"
@@ -47,15 +48,15 @@
 
 local function java_args(list)
 	for i,v in ipairs(list) do
-		list[i] = JavaLuan.toJava(v)
+		list[i] = LuanJava.toJava(v)
 	end
 	return unpack(list)
 end
 
 local function luan_args(list,binary_in)
-	list = JavaLuan.table(list)
+	list = LuanJava.table(list)
 	for i,v in ipairs(list) do
-		list[i] = JavaLuan.toLuan(v)
+		list[i] = to_luan(v)
 	end
 	if binary_in ~= nil then
 		local i_in = list[#list]
--- a/src/luan/modules/Table.luan	Thu Sep 20 22:11:11 2018 -0600
+++ b/src/luan/modules/Table.luan	Sun Sep 23 17:58:40 2018 -0600
@@ -1,10 +1,10 @@
 java()
 local TableLuan = require "java:luan.modules.TableLuan"
-local JavaLuan = require "java:luan.Luan"
+local LuanJava = require "java:luan.Luan"
 
 local Table = {}
 
-Table.as_table = JavaLuan.table
+Table.as_table = LuanJava.table
 Table.clear = TableLuan.clear
 Table.concat = TableLuan.concat
 Table.copy = TableLuan.copy
--- a/src/luan/modules/http/Http.luan	Thu Sep 20 22:11:11 2018 -0600
+++ b/src/luan/modules/http/Http.luan	Sun Sep 23 17:58:40 2018 -0600
@@ -4,6 +4,7 @@
 local ipairs = Luan.ipairs or error()
 local pairs = Luan.pairs or error()
 local type = Luan.type or error()
+local to_luan = Luan.to_luan or error()
 local Io = require "luan:Io.luan"
 local Html = require "luan:Html.luan"
 local Table = require "luan:Table.luan"
@@ -13,7 +14,8 @@
 local lower = String.lower or error()
 local matches = String.matches or error()
 local IoLuan = require "java:luan.modules.IoLuan"
-local JavaLuan = require "java:luan.Luan"
+local LuanJava = require "java:luan.Luan"
+local Request = require "java:luan.webserver.Request"
 local Response = require "java:luan.webserver.Response"
 local ResponseOutputStream = require "java:luan.webserver.ResponseOutputStream"
 local Status = require "java:luan.webserver.Status"
@@ -23,6 +25,20 @@
 
 local Http = {}
 
+local old_java_to_luan = Luan.java_to_luan or error()
+
+local function java_to_luan(obj)
+	obj = old_java_to_luan(obj)
+	if type(obj)=="java" and obj.instanceof(Request.MultipartFile) then
+		return {
+			filename = obj.filename
+			content_type = obj.contentType
+			content = obj.content
+		}
+	end
+	return obj
+end
+
 function Http.new_request(java)
 	local this = {}
 	Http.request = this
@@ -40,9 +56,9 @@
 		this.path = java.path or error()
 		this.protocol = java.protocol or error()
 		this.scheme = java.scheme or error()
-		this.headers = JavaLuan.toLuan(java.headers)
-		this.parameters = JavaLuan.toLuan(java.parameters)
-		this.cookies = JavaLuan.toLuan(java.cookies)
+		this.headers = to_luan(java.headers)
+		this.parameters = to_luan(java.parameters,java_to_luan)
+		this.cookies = to_luan(java.cookies)
 	end
 
 	function this.url()
@@ -135,7 +151,7 @@
 	for name, value in pairs(response.headers) do
 		type(name)=="string" or "header name must be string"
 		name = lower(name)
-		value = JavaLuan.toJava(value)
+		value = LuanJava.toJava(value)
 		java.headers.put(name,value)
 	end
 	response.writer and response.writer.close()
--- a/src/luan/webserver/Request.java	Thu Sep 20 22:11:11 2018 -0600
+++ b/src/luan/webserver/Request.java	Sun Sep 23 17:58:40 2018 -0600
@@ -19,10 +19,12 @@
 
 	public static final class MultipartFile {
 		public final String filename;
+		public final String contentType;
 		public final Object content;  // byte[] or String
 
-		MultipartFile(String filename,Object content) {
+		MultipartFile(String filename,String contentType,Object content) {
 			this.filename = filename;
+			this.contentType = contentType;
 			this.content = content;
 		}
 
--- a/src/luan/webserver/RequestParser.java	Thu Sep 20 22:11:11 2018 -0600
+++ b/src/luan/webserver/RequestParser.java	Sun Sep 23 17:58:40 2018 -0600
@@ -201,6 +201,7 @@
 			throw new RuntimeException(contentType);
 		String boundary = "--"+contentType.substring(contentTypeStart.length());
 		this.parser = new Parser(Util.toString(request.body));
+//System.out.println(this.parser.text);
 		require( parser.match(boundary) );
 		boundary = "\r\n" + boundary;
 		while( !parser.match("--\r\n") ) {
@@ -213,12 +214,15 @@
 				filename = quotedString();
 				require( parser.match("\r\n") );
 				require( parser.match("Content-Type: ") );
-				if( parser.match("application/octet-stream") ) {
+				int start = parser.currentIndex();
+				if( parser.match("application/") ) {
 					isBinary = true;
-				} else if( parser.match("text/plain") ) {
+				} else if( parser.match("text/") ) {
 					isBinary = false;
 				} else
 					throw new ParseException(parser,"bad file content-type");
+				while( parser.inCharRange('a','z') || parser.anyOf("-.") );
+				contentType = parser.textFrom(start);
 			}
 			require( parser.match("\r\n") );
 			require( parser.match("\r\n") );
@@ -231,7 +235,7 @@
 				Util.add(request.parameters,name,value);
 			} else {
 				Object content = isBinary ? Util.toBytes(value) : value;
-				Request.MultipartFile mf = new Request.MultipartFile(filename,content);
+				Request.MultipartFile mf = new Request.MultipartFile(filename,contentType,content);
 				Util.add(request.parameters,name,mf);
 			}
 			require( parser.match(boundary) );
--- a/website/src/examples/upload-and-email.html.luan	Thu Sep 20 22:11:11 2018 -0600
+++ b/website/src/examples/upload-and-email.html.luan	Sun Sep 23 17:58:40 2018 -0600
@@ -4,10 +4,10 @@
 
 
 local send = Mail.Sender{
-	host = "smtpcorp.com";
-	username = "smtp@luanhost.com";
-	password = "luanhost";
-	port = 2525;
+	host = "smtpcorp.com"
+	username = "smtp@luanhost.com"
+	password = "luanhost"
+	port = 2525
 }.send
 
 local function form()