Mercurial Hosting > luan
changeset 251:705d14f4d8ee
start web testing
git-svn-id: https://luan-java.googlecode.com/svn/trunk@252 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Sun, 19 Oct 2014 03:38:47 +0000 |
parents | 2b6f51d7af40 |
children | 3896138955b1 |
files | core/src/luan/cmd_line.luan core/src/luan/modules/BasicLuan.java core/src/luan/modules/StringLuan.java core/src/luan/modules/Utils.java web/src/luan/modules/web/Http.luan web/src/luan/modules/web/HttpLuan.java web/src/luan/modules/web/HttpServicer.java web/src/luan/modules/web/LuanHandler.java |
diffstat | 8 files changed, 540 insertions(+), 509 deletions(-) [+] |
line wrap: on
line diff
diff -r 2b6f51d7af40 -r 705d14f4d8ee core/src/luan/cmd_line.luan --- a/core/src/luan/cmd_line.luan Fri Oct 17 02:17:46 2014 +0000 +++ b/core/src/luan/cmd_line.luan Sun Oct 19 03:38:47 2014 +0000 @@ -1,5 +1,6 @@ import "String" import "Table" +import "Io" local standalone_usage = [=[ @@ -69,7 +70,7 @@ local main_file = load_file(file) main_file( Table.unpack(_G.arg) ) catch e do - print(e) + Io.print_to(Io.stderr, e ) end end if interactive then
diff -r 2b6f51d7af40 -r 705d14f4d8ee core/src/luan/modules/BasicLuan.java --- a/core/src/luan/modules/BasicLuan.java Fri Oct 17 02:17:46 2014 +0000 +++ b/core/src/luan/modules/BasicLuan.java Sun Oct 19 03:38:47 2014 +0000 @@ -88,7 +88,7 @@ } public static LuanFunction pairs(LuanState luan,final LuanTable t) throws LuanException { - Utils.checkNotNull(luan,t,"table"); + Utils.checkNotNull(luan,t); return new LuanFunction() { Iterator<Map.Entry<Object,Object>> iter = t.iterator(); @@ -102,7 +102,7 @@ } public static LuanFunction ipairs(LuanState luan,final LuanTable t) throws LuanException { - Utils.checkNotNull(luan,t,"table"); + Utils.checkNotNull(luan,t); return new LuanFunction() { List<Object> list = t.asList(); int i = 0; @@ -176,17 +176,17 @@ } public static String assert_string(LuanState luan,String v) throws LuanException { - Utils.checkNotNull(luan,v,"string"); + Utils.checkNotNull(luan,v); return v; } public static Number assert_number(LuanState luan,Number v) throws LuanException { - Utils.checkNotNull(luan,v,"number"); + Utils.checkNotNull(luan,v); return v; } public static LuanTable assert_table(LuanState luan,LuanTable v) throws LuanException { - Utils.checkNotNull(luan,v,"table"); + Utils.checkNotNull(luan,v); return v; }
diff -r 2b6f51d7af40 -r 705d14f4d8ee core/src/luan/modules/StringLuan.java --- a/core/src/luan/modules/StringLuan.java Fri Oct 17 02:17:46 2014 +0000 +++ b/core/src/luan/modules/StringLuan.java Sun Oct 19 03:38:47 2014 +0000 @@ -29,7 +29,7 @@ add( module, "match", String.class, String.class, Integer.class ); add( module, "rep", String.class, Integer.TYPE, String.class ); add( module, "reverse", String.class ); - add( module, "sub", String.class, Integer.TYPE, Integer.class ); + add( module, "sub", LuanState.class, String.class, Integer.TYPE, Integer.class ); add( module, "upper", String.class ); } catch(NoSuchMethodException e) { throw new RuntimeException(e); @@ -128,7 +128,8 @@ return buf.toString(); } - public static String sub(String s,int i,Integer j) { + public static String sub(LuanState luan,String s,int i,Integer j) throws LuanException { + Utils.checkNotNull(luan,s); int start = start(s,i); int end = end(s,j,s.length()); return s.substring(start,end);
diff -r 2b6f51d7af40 -r 705d14f4d8ee core/src/luan/modules/Utils.java --- a/core/src/luan/modules/Utils.java Fri Oct 17 02:17:46 2014 +0000 +++ b/core/src/luan/modules/Utils.java Sun Oct 19 03:38:47 2014 +0000 @@ -10,6 +10,7 @@ import java.net.MalformedURLException; import luan.LuanState; import luan.LuanException; +import luan.LuanTable; public final class Utils { @@ -17,11 +18,23 @@ static final int bufSize = 8192; - public static void checkNotNull(LuanState luan,Object v,String expected) throws LuanException { + private static void checkNotNull(LuanState luan,Object v,String expected) throws LuanException { if( v == null ) throw luan.exception("bad argument #1 ("+expected+" expected, got nil)"); } + public static void checkNotNull(LuanState luan,String s) throws LuanException { + checkNotNull(luan,s,"string"); + } + + public static void checkNotNull(LuanState luan,LuanTable t) throws LuanException { + checkNotNull(luan,t,"table"); + } + + public static void checkNotNull(LuanState luan,Number n) throws LuanException { + checkNotNull(luan,n,"number"); + } + public static String readAll(Reader in) throws IOException {
diff -r 2b6f51d7af40 -r 705d14f4d8ee web/src/luan/modules/web/Http.luan --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/src/luan/modules/web/Http.luan Sun Oct 19 03:38:47 2014 +0000 @@ -0,0 +1,36 @@ +import "Java" +import "Table" +import "luan.modules.web.LuanHandler" + +function new_luan_handler() + return LuanHandler.new() +end + + + +function init_for_test() + + function get_page(mod_name) + local mod = require(mod_name) + mod.service() + return Table.concat(result) + end + + request = { + cookies = {} + } + + response = { + text_writer = function() + result = {} + return { + write = function(...) + for _, v in ipairs{...} do + result[#result+1] = v + end + end; + } + end; + } + +end
diff -r 2b6f51d7af40 -r 705d14f4d8ee web/src/luan/modules/web/HttpLuan.java --- a/web/src/luan/modules/web/HttpLuan.java Fri Oct 17 02:17:46 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,499 +0,0 @@ -package luan.modules.web; - -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; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import luan.Luan; -import luan.LuanState; -import luan.LuanFunction; -import luan.LuanElement; -import luan.LuanException; -import luan.LuanTable; -import luan.AbstractLuanTable; -import luan.LuanJavaFunction; -import luan.LuanExitException; -import luan.LuanProperty; -import luan.DeepCloner; -import luan.modules.PackageLuan; -import luan.modules.IoLuan; -import luan.modules.TableLuan; - - -public final class HttpLuan { - - public static final LuanFunction LOADER = new LuanFunction() { - @Override public Object call(LuanState luan,Object[] args) { - LuanTable module = Luan.newTable(); - try { - addStatic( module, "new_luan_handler", LuanState.class ); - } catch(NoSuchMethodException e) { - throw new RuntimeException(e); - } - return module; - } - }; - - private static void addStatic(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException { - t.put( method, new LuanJavaFunction(HttpLuan.class.getMethod(method,parameterTypes),null) ); - } - - public static LuanHandler new_luan_handler(LuanState luan) { - return new LuanHandler(luan); - } - - public static boolean service(LuanState luan,HttpServletRequest request,HttpServletResponse response,String modName) - throws LuanException - { - LuanFunction fn; - synchronized(luan) { - Object mod = PackageLuan.load(luan,modName); - if( mod==null ) - return false; - if( !(mod instanceof LuanTable) ) - throw luan.exception( "module '"+modName+"' must return a table" ); - LuanTable tbl = (LuanTable)mod; - if( Luan.toBoolean( tbl.get("per_session") ) ) { - HttpSession session = request.getSession(); - LuanState sessionLuan = (LuanState)session.getValue("luan"); - if( sessionLuan!=null ) { - luan = sessionLuan; - } else { - DeepCloner cloner = new DeepCloner(); - luan = cloner.deepClone(luan); - session.putValue("luan",luan); - } - tbl = (LuanTable)PackageLuan.require(luan,modName); - fn = (LuanFunction)tbl.get("service"); - } else { - fn = (LuanFunction)tbl.get("service"); - if( fn == null ) - throw luan.exception( "function 'service' is not defined" ); - DeepCloner cloner = new DeepCloner(); - luan = cloner.deepClone(luan); - fn = cloner.get(fn); - } - } - - LuanTable module = (LuanTable)PackageLuan.loaded(luan).get("web/Http"); - if( module == null ) - throw luan.exception( "module 'web/Http' not defined" ); - HttpLuan lib = new HttpLuan(request,response); - try { - module.put( "request", lib.requestTable() ); - module.put( "response", lib.responseTable() ); - module.put( "session", lib.sessionTable() ); -/* - module.put( "write", new LuanJavaFunction( - HttpLuan.class.getMethod( "text_write", LuanState.class, new Object[0].getClass() ), lib - ) ); -*/ - } catch(NoSuchMethodException e) { - throw new RuntimeException(e); - } - - try { - luan.call(fn,"<http>"); - } catch(LuanExitException e) { -// System.out.println("caught LuanExitException"); - } - return true; - } - - - - private final HttpServletRequest request; - private final HttpServletResponse response; -// private PrintWriter writer = null; -// private ServletOutputStream sos = null; - - private HttpLuan(HttpServletRequest request,HttpServletResponse response) { - this.request = request; - this.response = response; - } - - private LuanTable requestTable() throws NoSuchMethodException { - LuanTable tbl = Luan.newPropertyTable(); - tbl.put("java",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( "method", new LuanProperty() { public Object get() { - return request.getMethod(); - } } ); - tbl.put( "servlet_path", new LuanProperty() { public Object get() { - return request.getServletPath(); - } } ); - tbl.put( "server_name", new LuanProperty() { public Object get() { - return request.getServerName(); - } } ); - tbl.put( "current_url", new LuanProperty() { public Object get() { - return getCurrentURL(request); - } } ); - tbl.put( "remote_address", new LuanProperty() { public Object get() { - return request.getRemoteAddr(); - } } ); - LuanTable cookies = new AbstractLuanTable() { - - @Override public final Object get(Object key) { - if( !(key instanceof String) ) - return null; - String name = (String)key; - return getCookieValue(request,name); - } - - @Override public final Iterator<Map.Entry<Object,Object>> iterator() { - return new Iterator<Map.Entry<Object,Object>>() { - final Cookie[] cookies = request.getCookies(); - int i = 0; - - @Override public boolean hasNext() { - return i < cookies.length; - } - @Override public Map.Entry<Object,Object> next() { - Cookie cookie = cookies[i++]; - String name = cookie.getName(); - Object val = unescape(cookie.getValue()); - return new AbstractMap.SimpleEntry<Object,Object>(name,val); - } - @Override public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override protected String type() { - return "request.cookies-table"; - } - }; - tbl.put( "cookies", cookies ); - return tbl; - } - - private LuanTable responseTable() throws NoSuchMethodException { - LuanTable tbl = Luan.newPropertyTable(); - tbl.put("java",response); - add( tbl, "send_redirect", String.class ); - add( tbl, "send_error", Integer.TYPE, String.class ); - LuanTable headers = new NameTable() { - - @Override Object get(String name) { - return response.getHeader(name); - } - - @Override Iterator<String> names() { - return response.getHeaderNames().iterator(); - } - - @Override public void put(Object key,Object val) { - if( !(key instanceof String) ) - throw new IllegalArgumentException("key must be string for headers table"); - String name = (String)key; - if( val instanceof String ) { - response.setHeader(name,(String)val); - return; - } - Integer i = Luan.asInteger(val); - if( i != null ) { - response.setIntHeader(name,i); - return; - } - throw new IllegalArgumentException("value must be string or integer for headers table"); - } - - @Override protected String type() { - return "response.headers-table"; - } - }; - tbl.put( "headers", headers ); - tbl.put( "content_type", new LuanProperty() { - @Override public Object get() { - return response.getContentType(); - } - @Override public boolean set(Object value) { - response.setContentType(string(value)); return true; - } - } ); - tbl.put( "character_encoding", new LuanProperty() { - @Override public Object get() { - return response.getCharacterEncoding(); - } - @Override public boolean set(Object value) { - response.setCharacterEncoding(string(value)); return true; - } - } ); - add( tbl, "text_writer" ); - add( tbl, "set_cookie", String.class, String.class, Boolean.TYPE, String.class ); - add( tbl, "remove_cookie", String.class, String.class ); - return tbl; - } - - private LuanTable sessionTable() throws NoSuchMethodException { - LuanTable tbl = Luan.newTable(); - 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 void 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); - } - - @Override protected String type() { - return "session.attributes-table"; - } - }; - tbl.put( "attributes", attributes ); - return tbl; - } - - private void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException { - t.put( method, new LuanJavaFunction(HttpLuan.class.getMethod(method,parameterTypes),this) ); - } -/* - public void text_write(LuanState luan,Object... args) throws LuanException, IOException { - if( writer == null ) - writer = response.getWriter(); - for( Object obj : args ) { - writer.print( luan.toString(obj) ); - } - } -*/ - public LuanTable text_writer() throws IOException { - return IoLuan.textWriter(response.getWriter()); - } - - public LuanTable get_parameter_values(String name) { - Object[] a = request.getParameterValues(name); - return a==null ? null : TableLuan.pack(a); - } - - public void send_redirect(String redirectUrl) - throws IOException - { - response.sendRedirect(redirectUrl); - throw new LuanExitException(); - } - - public void send_error(int code,String text) - throws IOException - { - response.sendError(code, text); - throw new LuanExitException(); - } - - public void set_cookie(String name,String value,boolean isPersistent, String domain) { - setCookie(request,response,name,value,isPersistent,domain); - } - - public void remove_cookie(String name, String domain) { - removeCookie(request,response,name,domain); - } - - - // static utils - - public static String getQueryString(HttpServletRequest request) { - return getQueryString(request,0); - } - - public static String getQueryString(HttpServletRequest request,int maxValueLen) { - String method = request.getMethod(); - if( method.equals("GET") ) - return request.getQueryString(); - if( !method.equals("POST") && !method.equals("HEAD") ) - throw new RuntimeException(method); - Enumeration en = request.getParameterNames(); - StringBuilder queryBuf = new StringBuilder(); - if( !en.hasMoreElements() ) - return null; - do { - String param = (String)en.nextElement(); - String value = request.getParameter(param); - if( maxValueLen > 0 ) { - int len = value.length(); - if( len > maxValueLen ) - value = value.substring(0,maxValueLen) + "..." + (len-maxValueLen); - } - queryBuf.append(param); - queryBuf.append('='); - queryBuf.append(value); - queryBuf.append('&'); - } while( en.hasMoreElements() ); - queryBuf.deleteCharAt(queryBuf.length() - 1); - return queryBuf.toString(); - } - - public static String getCurrentURL(HttpServletRequest request) { - return getCurrentURL(request,0); - } - - public static String getCurrentURL(HttpServletRequest request,int maxValueLen) { -// StringBuffer buf = HttpUtils.getRequestURL(request); - StringBuffer buf = request.getRequestURL(); - String qStr = getQueryString(request,maxValueLen); - if(qStr != null && qStr.length() > 0) { - buf.append('?'); - buf.append(qStr); - } - return buf.toString(); - } - - 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 String getCookieValue(HttpServletRequest request,String name) { - Cookie cookie = getCookie(request,name); - return cookie==null ? null : unescape(cookie.getValue()); - } - - public static void setCookie(HttpServletRequest request,HttpServletResponse response,String name,String value,boolean isPersistent, String domain) { - Cookie cookie = getCookie(request,name); - if( cookie==null || !cookie.getValue().equals(value) ) { - cookie = new Cookie(name, escape(value)); - cookie.setPath("/"); - if (domain != null && domain.length() > 0) - cookie.setDomain(domain); - if( isPersistent ) - cookie.setMaxAge(10000000); - response.addCookie(cookie); - } - } - - public static void removeCookie(HttpServletRequest request, - HttpServletResponse response, - String name, - String domain - ) { - Cookie cookie = getCookie(request, name); - if(cookie != null) { - Cookie delCookie = new Cookie(name, "delete"); - delCookie.setPath("/"); - delCookie.setMaxAge(0); - if (domain != null && domain.length() > 0) - delCookie.setDomain(domain); - response.addCookie(delCookie); - } - } - - - - // 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(); - } - }; - } - }; - - private static String string(Object value) { - if( !(value instanceof String) ) - throw new IllegalArgumentException("value must be string"); - return (String)value; - } -}
diff -r 2b6f51d7af40 -r 705d14f4d8ee web/src/luan/modules/web/HttpServicer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/src/luan/modules/web/HttpServicer.java Sun Oct 19 03:38:47 2014 +0000 @@ -0,0 +1,479 @@ +package luan.modules.web; + +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; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import luan.Luan; +import luan.LuanState; +import luan.LuanFunction; +import luan.LuanElement; +import luan.LuanException; +import luan.LuanTable; +import luan.AbstractLuanTable; +import luan.LuanJavaFunction; +import luan.LuanExitException; +import luan.LuanProperty; +import luan.DeepCloner; +import luan.modules.PackageLuan; +import luan.modules.IoLuan; +import luan.modules.TableLuan; + + +public final class HttpServicer { + + public static boolean service(LuanState luan,HttpServletRequest request,HttpServletResponse response,String modName) + throws LuanException + { + LuanFunction fn; + synchronized(luan) { + Object mod = PackageLuan.load(luan,modName); + if( mod==null ) + return false; + if( !(mod instanceof LuanTable) ) + throw luan.exception( "module '"+modName+"' must return a table" ); + LuanTable tbl = (LuanTable)mod; + if( Luan.toBoolean( tbl.get("per_session") ) ) { + HttpSession session = request.getSession(); + LuanState sessionLuan = (LuanState)session.getValue("luan"); + if( sessionLuan!=null ) { + luan = sessionLuan; + } else { + DeepCloner cloner = new DeepCloner(); + luan = cloner.deepClone(luan); + session.putValue("luan",luan); + } + tbl = (LuanTable)PackageLuan.require(luan,modName); + fn = (LuanFunction)tbl.get("service"); + } else { + fn = (LuanFunction)tbl.get("service"); + if( fn == null ) + throw luan.exception( "function 'service' is not defined" ); + DeepCloner cloner = new DeepCloner(); + luan = cloner.deepClone(luan); + fn = cloner.get(fn); + } + } + + LuanTable module = (LuanTable)PackageLuan.loaded(luan).get("web/Http"); + if( module == null ) + throw luan.exception( "module 'web/Http' not defined" ); + HttpServicer lib = new HttpServicer(request,response); + try { + module.put( "request", lib.requestTable() ); + module.put( "response", lib.responseTable() ); + module.put( "session", lib.sessionTable() ); +/* + module.put( "write", new LuanJavaFunction( + HttpServicer.class.getMethod( "text_write", LuanState.class, new Object[0].getClass() ), lib + ) ); +*/ + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + + try { + luan.call(fn,"<http>"); + } catch(LuanExitException e) { +// System.out.println("caught LuanExitException"); + } + return true; + } + + + + private final HttpServletRequest request; + private final HttpServletResponse response; +// private PrintWriter writer = null; +// private ServletOutputStream sos = null; + + private HttpServicer(HttpServletRequest request,HttpServletResponse response) { + this.request = request; + this.response = response; + } + + private LuanTable requestTable() throws NoSuchMethodException { + LuanTable tbl = Luan.newPropertyTable(); + tbl.put("java",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( "method", new LuanProperty() { public Object get() { + return request.getMethod(); + } } ); + tbl.put( "servlet_path", new LuanProperty() { public Object get() { + return request.getServletPath(); + } } ); + tbl.put( "server_name", new LuanProperty() { public Object get() { + return request.getServerName(); + } } ); + tbl.put( "current_url", new LuanProperty() { public Object get() { + return getCurrentURL(request); + } } ); + tbl.put( "remote_address", new LuanProperty() { public Object get() { + return request.getRemoteAddr(); + } } ); + LuanTable cookies = new AbstractLuanTable() { + + @Override public final Object get(Object key) { + if( !(key instanceof String) ) + return null; + String name = (String)key; + return getCookieValue(request,name); + } + + @Override public final Iterator<Map.Entry<Object,Object>> iterator() { + return new Iterator<Map.Entry<Object,Object>>() { + final Cookie[] cookies = request.getCookies(); + int i = 0; + + @Override public boolean hasNext() { + return i < cookies.length; + } + @Override public Map.Entry<Object,Object> next() { + Cookie cookie = cookies[i++]; + String name = cookie.getName(); + Object val = unescape(cookie.getValue()); + return new AbstractMap.SimpleEntry<Object,Object>(name,val); + } + @Override public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override protected String type() { + return "request.cookies-table"; + } + }; + tbl.put( "cookies", cookies ); + return tbl; + } + + private LuanTable responseTable() throws NoSuchMethodException { + LuanTable tbl = Luan.newPropertyTable(); + tbl.put("java",response); + add( tbl, "send_redirect", String.class ); + add( tbl, "send_error", Integer.TYPE, String.class ); + LuanTable headers = new NameTable() { + + @Override Object get(String name) { + return response.getHeader(name); + } + + @Override Iterator<String> names() { + return response.getHeaderNames().iterator(); + } + + @Override public void put(Object key,Object val) { + if( !(key instanceof String) ) + throw new IllegalArgumentException("key must be string for headers table"); + String name = (String)key; + if( val instanceof String ) { + response.setHeader(name,(String)val); + return; + } + Integer i = Luan.asInteger(val); + if( i != null ) { + response.setIntHeader(name,i); + return; + } + throw new IllegalArgumentException("value must be string or integer for headers table"); + } + + @Override protected String type() { + return "response.headers-table"; + } + }; + tbl.put( "headers", headers ); + tbl.put( "content_type", new LuanProperty() { + @Override public Object get() { + return response.getContentType(); + } + @Override public boolean set(Object value) { + response.setContentType(string(value)); return true; + } + } ); + tbl.put( "character_encoding", new LuanProperty() { + @Override public Object get() { + return response.getCharacterEncoding(); + } + @Override public boolean set(Object value) { + response.setCharacterEncoding(string(value)); return true; + } + } ); + add( tbl, "text_writer" ); + add( tbl, "set_cookie", String.class, String.class, Boolean.TYPE, String.class ); + add( tbl, "remove_cookie", String.class, String.class ); + return tbl; + } + + private LuanTable sessionTable() throws NoSuchMethodException { + LuanTable tbl = Luan.newTable(); + 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 void 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); + } + + @Override protected String type() { + return "session.attributes-table"; + } + }; + tbl.put( "attributes", attributes ); + return tbl; + } + + private void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException { + t.put( method, new LuanJavaFunction(HttpServicer.class.getMethod(method,parameterTypes),this) ); + } +/* + public void text_write(LuanState luan,Object... args) throws LuanException, IOException { + if( writer == null ) + writer = response.getWriter(); + for( Object obj : args ) { + writer.print( luan.toString(obj) ); + } + } +*/ + public LuanTable text_writer() throws IOException { + return IoLuan.textWriter(response.getWriter()); + } + + public LuanTable get_parameter_values(String name) { + Object[] a = request.getParameterValues(name); + return a==null ? null : TableLuan.pack(a); + } + + public void send_redirect(String redirectUrl) + throws IOException + { + response.sendRedirect(redirectUrl); + throw new LuanExitException(); + } + + public void send_error(int code,String text) + throws IOException + { + response.sendError(code, text); + throw new LuanExitException(); + } + + public void set_cookie(String name,String value,boolean isPersistent, String domain) { + setCookie(request,response,name,value,isPersistent,domain); + } + + public void remove_cookie(String name, String domain) { + removeCookie(request,response,name,domain); + } + + + // static utils + + public static String getQueryString(HttpServletRequest request) { + return getQueryString(request,0); + } + + public static String getQueryString(HttpServletRequest request,int maxValueLen) { + String method = request.getMethod(); + if( method.equals("GET") ) + return request.getQueryString(); + if( !method.equals("POST") && !method.equals("HEAD") ) + throw new RuntimeException(method); + Enumeration en = request.getParameterNames(); + StringBuilder queryBuf = new StringBuilder(); + if( !en.hasMoreElements() ) + return null; + do { + String param = (String)en.nextElement(); + String value = request.getParameter(param); + if( maxValueLen > 0 ) { + int len = value.length(); + if( len > maxValueLen ) + value = value.substring(0,maxValueLen) + "..." + (len-maxValueLen); + } + queryBuf.append(param); + queryBuf.append('='); + queryBuf.append(value); + queryBuf.append('&'); + } while( en.hasMoreElements() ); + queryBuf.deleteCharAt(queryBuf.length() - 1); + return queryBuf.toString(); + } + + public static String getCurrentURL(HttpServletRequest request) { + return getCurrentURL(request,0); + } + + public static String getCurrentURL(HttpServletRequest request,int maxValueLen) { +// StringBuffer buf = HttpUtils.getRequestURL(request); + StringBuffer buf = request.getRequestURL(); + String qStr = getQueryString(request,maxValueLen); + if(qStr != null && qStr.length() > 0) { + buf.append('?'); + buf.append(qStr); + } + return buf.toString(); + } + + 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 String getCookieValue(HttpServletRequest request,String name) { + Cookie cookie = getCookie(request,name); + return cookie==null ? null : unescape(cookie.getValue()); + } + + public static void setCookie(HttpServletRequest request,HttpServletResponse response,String name,String value,boolean isPersistent, String domain) { + Cookie cookie = getCookie(request,name); + if( cookie==null || !cookie.getValue().equals(value) ) { + cookie = new Cookie(name, escape(value)); + cookie.setPath("/"); + if (domain != null && domain.length() > 0) + cookie.setDomain(domain); + if( isPersistent ) + cookie.setMaxAge(10000000); + response.addCookie(cookie); + } + } + + public static void removeCookie(HttpServletRequest request, + HttpServletResponse response, + String name, + String domain + ) { + Cookie cookie = getCookie(request, name); + if(cookie != null) { + Cookie delCookie = new Cookie(name, "delete"); + delCookie.setPath("/"); + delCookie.setMaxAge(0); + if (domain != null && domain.length() > 0) + delCookie.setDomain(domain); + response.addCookie(delCookie); + } + } + + + + // 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(); + } + }; + } + }; + + private static String string(Object value) { + if( !(value instanceof String) ) + throw new IllegalArgumentException("value must be string"); + return (String)value; + } +}
diff -r 2b6f51d7af40 -r 705d14f4d8ee web/src/luan/modules/web/LuanHandler.java --- a/web/src/luan/modules/web/LuanHandler.java Fri Oct 17 02:17:46 2014 +0000 +++ b/web/src/luan/modules/web/LuanHandler.java Sun Oct 19 03:38:47 2014 +0000 @@ -25,7 +25,7 @@ if( target.endsWith("/") ) target += welcomeFile; try { - if( !HttpLuan.service(luan,request,response,target) ) + if( !HttpServicer.service(luan,request,response,target) ) return; response.setStatus(HttpServletResponse.SC_OK); } catch(LuanException e) {