changeset 222:b76fcb72d97d

add AbstractLuanTable and improve HttpLuan git-svn-id: https://luan-java.googlecode.com/svn/trunk@223 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Mon, 21 Jul 2014 02:23:05 +0000
parents ec016471c6eb
children a9fe265dbac3
files core/src/luan/AbstractLuanTable.java core/src/luan/LuanTableImpl.java core/src/luan/impl/SetTableEntry.java core/src/luan/modules/TableLuan.java web/src/luan/modules/web/HttpLuan.java web/src/luan/modules/web/web_run.luan web/src/luan/modules/web/web_shell.luan
diffstat 7 files changed, 225 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
diff -r ec016471c6eb -r b76fcb72d97d core/src/luan/AbstractLuanTable.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/src/luan/AbstractLuanTable.java	Mon Jul 21 02:23:05 2014 +0000
@@ -0,0 +1,67 @@
+package luan;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.regex.Pattern;
+
+
+public abstract class AbstractLuanTable implements LuanTable {
+
+	@Override public List<Object> asList() {
+		return Collections.emptyList();
+	}
+
+	@Override public Map<Object,Object> asMap() {
+		return Collections.emptyMap();
+	}
+
+	protected abstract String type();
+
+	@Override public final String toString() {
+		return type() + ": " + Integer.toHexString(hashCode());
+	}
+
+	@Override public Object put(Object key,Object val) {
+		throw new UnsupportedOperationException("can't put into a "+type());
+	}
+
+	@Override public void insert(int pos,Object value) {
+		throw new UnsupportedOperationException("can't insert into a "+type());
+	}
+
+	@Override public void add(Object value) {
+		throw new UnsupportedOperationException("can't add to a "+type());
+	}
+
+	@Override public Object remove(int pos) {
+		throw new UnsupportedOperationException("can't remove from a "+type());
+	}
+
+	@Override public void sort(Comparator<Object> cmp) {
+	}
+
+	@Override public int length() {
+		return 0;
+	}
+
+	@Override public LuanTable subList(int from,int to) {
+		throw new UnsupportedOperationException("can't get a sub-list of a "+type());
+	}
+
+	@Override public LuanTable getMetatable() {
+		return null;
+	}
+
+	@Override public void setMetatable(LuanTable metatable) {
+		throw new UnsupportedOperationException("can't set a metatable on a "+type());
+	}
+}
diff -r ec016471c6eb -r b76fcb72d97d core/src/luan/LuanTableImpl.java
--- a/core/src/luan/LuanTableImpl.java	Thu Jul 17 07:49:26 2014 +0000
+++ b/core/src/luan/LuanTableImpl.java	Mon Jul 21 02:23:05 2014 +0000
@@ -3,6 +3,7 @@
 import java.util.Iterator;
 import java.util.ListIterator;
 import java.util.Map;
+import java.util.AbstractMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.ArrayList;
@@ -14,7 +15,7 @@
 import java.util.regex.Pattern;
 
 
-public final class LuanTableImpl implements LuanTable, DeepCloneable<LuanTableImpl>, LuanRepr {
+final class LuanTableImpl extends AbstractLuanTable implements LuanTable, DeepCloneable<LuanTableImpl>, LuanRepr {
 	private Map<Object,Object> map = null;
 	private List<Object> list = null;
 	private LuanTable metatable = null;
@@ -123,8 +124,8 @@
 		return rtn;
 	}
 
-	@Override public String toString() {
-		return "table: " + Integer.toHexString(hashCode());
+	@Override protected String type() {
+		return "table";
 	}
 
 	@Override public String repr() {
@@ -277,14 +278,14 @@
 
 	@Override public void insert(int pos,Object value) {
 		if( value==null )
-			throw new UnsupportedOperationException();
+			throw new IllegalArgumentException("can't insert a nil value");
 		list().add(pos-1,value);
 		mapToList();
 	}
 
 	@Override public void add(Object value) {
 		if( value==null )
-			throw new UnsupportedOperationException();
+			throw new IllegalArgumentException("can't add a nil value");
 		list().add(value);
 		mapToList();
 	}
@@ -340,7 +341,7 @@
 			}
 			public Map.Entry<Object,Object> next() {
 				Double key = Double.valueOf(iter.nextIndex()+1);
-				return new MapEntry(key,iter.next());
+				return new AbstractMap.SimpleEntry<Object,Object>(key,iter.next());
 			}
 			public void remove() {
 				throw new UnsupportedOperationException();
@@ -362,28 +363,6 @@
 		this.metatable = metatable;
 	}
 
-	private static final class MapEntry implements Map.Entry<Object,Object> {
-		private final Object key;
-		private final Object value;
-
-		MapEntry(Object key,Object value) {
-			this.key = key;
-			this.value = value;
-		}
-
-		@Override public Object getKey() {
-			return key;
-		}
-
-		@Override public Object getValue() {
-			return value;
-		}
-
-		@Override public Object setValue(Object value) {
-			throw new UnsupportedOperationException();
-		}
-	}
-
 	public boolean isEmpty() {
 		return (list==null || list.isEmpty()) && (map==null || map.isEmpty());
 	}
diff -r ec016471c6eb -r b76fcb72d97d core/src/luan/impl/SetTableEntry.java
--- a/core/src/luan/impl/SetTableEntry.java	Thu Jul 17 07:49:26 2014 +0000
+++ b/core/src/luan/impl/SetTableEntry.java	Mon Jul 21 02:23:05 2014 +0000
@@ -25,7 +25,14 @@
 		Object h;
 		if( t instanceof LuanTable ) {
 			LuanTable table = (LuanTable)t;
-			Object old = table.put(key,value);
+			Object old;
+			try {
+				old = table.put(key,value);
+			} catch(IllegalArgumentException e) {
+				throw luan.bit(se).exception(e);
+			} catch(UnsupportedOperationException e) {
+				throw luan.bit(se).exception(e);
+			}
 			if( old != null )
 				return;
 			h = luan.getHandler("__newindex",t);
diff -r ec016471c6eb -r b76fcb72d97d core/src/luan/modules/TableLuan.java
--- a/core/src/luan/modules/TableLuan.java	Thu Jul 17 07:49:26 2014 +0000
+++ b/core/src/luan/modules/TableLuan.java	Mon Jul 21 02:23:05 2014 +0000
@@ -21,9 +21,9 @@
 			LuanTable module = Luan.newTable();
 			try {
 				add( module, "concat", LuanState.class, LuanTable.class, String.class, Integer.class, Integer.class );
-				add( module, "insert", LuanState.class, LuanTable.class, Integer.TYPE, Object.class );
+				add( module, "insert", LuanTable.class, Integer.TYPE, Object.class );
 				add( module, "pack", new Object[0].getClass() );
-				add( module, "remove", LuanState.class, LuanTable.class, Integer.TYPE );
+				add( module, "remove", LuanTable.class, Integer.TYPE );
 				add( module, "sort", LuanState.class, LuanTable.class, LuanFunction.class );
 				add( module, "sub_list", LuanTable.class, Integer.TYPE, Integer.TYPE );
 				add( module, "unpack", LuanTable.class, Integer.class, Integer.class );
@@ -56,20 +56,12 @@
 		return buf.toString();
 	}
 
-	public static void insert(LuanState luan,LuanTable list,int pos,Object value) throws LuanException {
-		try {
-			list.insert(pos,value);
-		} catch(IndexOutOfBoundsException e) {
-			throw luan.exception(e);
-		}
+	public static void insert(LuanTable list,int pos,Object value){
+		list.insert(pos,value);
 	}
 
-	public static Object remove(LuanState luan,LuanTable list,int pos) throws LuanException {
-		try {
-			return list.remove(pos);
-		} catch(IndexOutOfBoundsException e) {
-			throw luan.exception(e);
-		}
+	public static Object remove(LuanTable list,int pos) {
+		return list.remove(pos);
 	}
 
 	private static interface LessThan {
diff -r ec016471c6eb -r b76fcb72d97d web/src/luan/modules/web/HttpLuan.java
--- a/web/src/luan/modules/web/HttpLuan.java	Thu Jul 17 07:49:26 2014 +0000
+++ b/web/src/luan/modules/web/HttpLuan.java	Mon Jul 21 02:23:05 2014 +0000
@@ -3,8 +3,10 @@
 import java.io.PrintWriter;
 import java.io.IOException;
 import java.util.Map;
+import java.util.AbstractMap;
 import java.util.Set;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.Enumeration;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.Cookie;
@@ -17,11 +19,13 @@
 import luan.LuanElement;
 import luan.LuanException;
 import luan.LuanTable;
+import luan.AbstractLuanTable;
 import luan.LuanJavaFunction;
 import luan.LuanExitException;
 import luan.DeepCloner;
 import luan.modules.PackageLuan;
 import luan.modules.IoLuan;
+import luan.modules.TableLuan;
 
 
 public final class HttpLuan {
@@ -116,10 +120,37 @@
 	private LuanTable requestTable() throws NoSuchMethodException {
 		LuanTable tbl = Luan.newTable();
 		tbl.put("java",request);
-		add( tbl, "get_parameter", String.class );
-		tbl.put( "get_header", new LuanJavaFunction(
-			HttpServletRequest.class.getMethod("getHeader",String.class), request
-		) );
+		LuanTable parameters = new NameTable() {
+
+			@Override Object get(String name) {
+				return request.getParameter(name);
+			}
+
+			@Override Iterator<String> names() {
+				return new EnumerationIterator(request.getParameterNames());
+			}
+
+			@Override protected String type() {
+				return "request.parameters-table";
+			}
+		};
+		tbl.put( "parameters", parameters );
+		add( tbl, "get_parameter_values", String.class );
+		LuanTable headers = new NameTable() {
+
+			@Override Object get(String name) {
+				return request.getHeader(name);
+			}
+
+			@Override Iterator<String> names() {
+				return new EnumerationIterator(request.getHeaderNames());
+			}
+
+			@Override protected String type() {
+				return "request.headers-table";
+			}
+		};
+		tbl.put( "headers", headers );
 		tbl.put( "get_method", new LuanJavaFunction(
 			HttpServletRequest.class.getMethod("getMethod"), request
 		) );
@@ -147,6 +178,23 @@
 		tbl.put( "set_header", new LuanJavaFunction(
 			HttpServletResponse.class.getMethod("setHeader",String.class,String.class), response
 		) );
+/*
+		LuanTable headers = new NameTable() {
+
+			@Override Object get(String name) {
+				return response.getHeader(name);
+			}
+
+			@Override Iterator<String> names() {
+				return response.getHeaderNames().iterator();
+			}
+
+			@Override protected String type() {
+				return "response.headers-table";
+			}
+		};
+		tbl.put( "headers", headers );
+*/
 		tbl.put( "set_content_type", new LuanJavaFunction(
 			HttpServletResponse.class.getMethod("setContentType",String.class), response
 		) );
@@ -173,12 +221,29 @@
 
 	private LuanTable sessionTable() throws NoSuchMethodException {
 		LuanTable tbl = Luan.newTable();
-		tbl.put( "get_attribute", new LuanJavaFunction(
-			HttpLuan.class.getMethod("get_session_attribute",String.class), this
-		) );
-		tbl.put( "set_attribute", new LuanJavaFunction(
-			HttpLuan.class.getMethod("set_session_attribute",String.class, Object.class), this
-		) );
+		LuanTable attributes = new NameTable() {
+
+			@Override Object get(String name) {
+				return request.getSession().getAttribute(name);
+			}
+
+			@Override Iterator<String> names() {
+				return new EnumerationIterator(request.getSession().getAttributeNames());
+			}
+
+			@Override public Object put(Object key,Object val) {
+				if( !(key instanceof String) )
+					throw new IllegalArgumentException("key must be string for session attributes table");
+				String name = (String)key;
+				request.getSession().setAttribute(name,val);
+				return null;
+			}
+
+			@Override protected String type() {
+				return "session.attributes-table";
+			}
+		};
+		tbl.put( "attributes", attributes );
 		return tbl;
 	}
 
@@ -198,9 +263,9 @@
 		return IoLuan.textWriter(response.getWriter());
 	}
 
-	public Object get_parameter(String name) {
-		String[] a = request.getParameterValues(name);
-		return a==null ? null : a.length==1 ? a[0] : a;
+	public LuanTable get_parameter_values(String name) {
+		Object[] a = request.getParameterValues(name);
+		return a==null ? null : TableLuan.pack(a);
 	}
 
 	public String get_cookie(String name) {
@@ -233,14 +298,6 @@
 		removeCookie(request,response,name,domain);
 	}
 
-	public Object get_session_attribute(String name) {
-		return request.getSession().getAttribute(name);
-	}
-
-	public void set_session_attribute(String name,Object value) {
-		request.getSession().setAttribute(name,value);
-	}
-
 
 	// static utils
 
@@ -344,4 +401,59 @@
 		}
 	}
 
+
+
+	// util classes
+
+	static final class EnumerationIterator<E> implements Iterator<E> {
+		private final Enumeration<E> en;
+
+		EnumerationIterator(Enumeration<E> en) {
+			this.en = en;
+		}
+
+		@Override public boolean hasNext() {
+			return en.hasMoreElements();
+		}
+
+		@Override public E next() {
+			return en.nextElement();
+		}
+
+		@Override public void remove() {
+			throw new UnsupportedOperationException();
+		}
+	}
+
+	private static abstract class NameTable extends AbstractLuanTable {
+		abstract Object get(String name);
+		abstract Iterator<String> names();
+
+		@Override public final Object get(Object key) {
+			if( !(key instanceof String) )
+				return null;
+			String name = (String)key;
+			return get(name);
+		}
+
+		@Override public final Iterator<Map.Entry<Object,Object>> iterator() {
+			return new Iterator<Map.Entry<Object,Object>>() {
+				Iterator<String> names = names();
+
+				@Override public boolean hasNext() {
+					return names.hasNext();
+				}
+				@Override public Map.Entry<Object,Object> next() {
+					String name = names.next();
+					Object val = get(name);
+					return new AbstractMap.SimpleEntry<Object,Object>(name,val);
+				}
+				@Override public void remove() {
+					throw new UnsupportedOperationException();
+				}
+			};
+		}
+	};
+
+
 }
diff -r ec016471c6eb -r b76fcb72d97d web/src/luan/modules/web/web_run.luan
--- a/web/src/luan/modules/web/web_run.luan	Thu Jul 17 07:49:26 2014 +0000
+++ b/web/src/luan/modules/web/web_run.luan	Mon Jul 21 02:23:05 2014 +0000
@@ -19,12 +19,12 @@
 end
 
 function service()
-	local content_type = Http.request.get_parameter("content_type")
+	local content_type = Http.request.parameters.content_type
 	if content_type ~= nil then
 		Http.response.set_content_type(content_type)
 	end
 	Io.stdout = Http.response.text_writer()
-	local code = Http.request.get_parameter "code"
+	local code = Http.request.parameters.code
 	local env = {
 		request = Http.request;
 		response = Http.response;
diff -r ec016471c6eb -r b76fcb72d97d web/src/luan/modules/web/web_shell.luan
--- a/web/src/luan/modules/web/web_shell.luan	Thu Jul 17 07:49:26 2014 +0000
+++ b/web/src/luan/modules/web/web_shell.luan	Mon Jul 21 02:23:05 2014 +0000
@@ -15,10 +15,10 @@
 end
 
 function service()
-	if Http.request.get_parameter("clear") ~= nil then
+	if Http.request.parameters.clear ~= nil then
 		history = {}
 	else
-		local cmd = Http.request.get_parameter("cmd")
+		local cmd = Http.request.parameters.cmd
 		if cmd ~= nil then
 			print( "% "..cmd )
 			try