You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by cb...@apache.org on 2012/03/09 17:23:32 UTC

svn commit: r1298906 [4/14] - in /velocity/sandbox/velosurf: ./ docs/ examples/ examples/ant-vpp/ examples/ant-vpp/lib/ examples/auth-l10n/ examples/auth-l10n/WEB-INF/ examples/auth-l10n/WEB-INF/lib/ examples/auth-l10n/WEB-INF/src/ examples/auth-l10n/e...

Added: velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/model.xml
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/model.xml?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/model.xml (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/model.xml Fri Mar  9 16:23:25 2012
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<database user="foo" password="bar" url="jdbc:mysql://127.0.0.1/mydatabase" read-only="false" loglevel="info" reverse="full">
+
+  <attribute name="user_by_login" result="row/user">
+    select * from user where login=<login/>
+  </attribute>
+
+</database>

Added: velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/src/DBAuthenticator.java
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/src/DBAuthenticator.java?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/src/DBAuthenticator.java (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/src/DBAuthenticator.java Fri Mar  9 16:23:25 2012
@@ -0,0 +1,55 @@
+package auth;
+
+import auth.Authenticator;
+import util.Logger;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+
+import velosurf.context.DBReference;
+import velosurf.context.RowIterator;
+import velosurf.sql.PooledPreparedStatement;
+import velosurf.sql.Database;
+import velosurf.web.VelosurfTool;
+import org.apache.velocity.tools.view.context.ViewContext;
+
+public class DBAuthenticator extends Authenticator {
+
+    private static Database sDb = null;
+
+    public void init(Object initData) {
+        super.init(initData);
+
+        // init only if there was no error in super class
+        if (initData instanceof ViewContext) {
+            if (sDb == null) {
+                sDb = VelosurfTool.getDefaultConnection(((ViewContext)initData).getServletContext());
+            }
+        }
+    }
+
+    protected String getPassword(String login) {
+        try {
+            PooledPreparedStatement stmt = sDb.prepare("select password from user where login = ?");
+            RowIterator ri = stmt.query(Arrays.asList(new String[] {login}));
+            while (ri.hasNext()) {
+                return ""+ri.get("password");
+            }
+        } catch (SQLException sqle) {
+            Logger.log(sqle);
+        }
+        return null;
+    }
+
+    protected Object getUser(String login) {
+        try {
+            DBReference dbr = new DBReference(sDb);
+            dbr.put("login", login);
+            return sDb.getAttribute("user_by_login").fetch(dbr);
+        } catch (SQLException sqle) {
+            Logger.log(sqle);
+        }
+        return null;
+    }
+
+}

Added: velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/src/DBLocalizer.java
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/src/DBLocalizer.java?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/src/DBLocalizer.java (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/src/DBLocalizer.java Fri Mar  9 16:23:25 2012
@@ -0,0 +1,57 @@
+import javax.servlet.ServletContext;
+
+import org.apache.velocity.tools.view.context.ViewContext;
+
+import velosurf.model.Entity;
+import velosurf.sql.Database;
+import velosurf.util.Logger;
+
+public class DBLocalizer extends HTTPLocalizerTool
+{
+	public DBLocalizer() {}
+
+    public void init(Object initData) {
+		super.init(initData);
+		if (!initialized) {
+	        ServletContext ctx = 
+	          inViewContext instanceof ServletContext ?
+    	        ctx = (ServletContext)inViewContext   :
+        	    ctx = ((ViewContext)inViewContext).getServletContext();
+			readLocales(ctx);
+		}
+	}
+
+	private static synchronized readLocales(ServletContext ctx) {
+		if (_initialized) return;
+
+		try {
+			Database db = VelosurfTool.getDefaultInstance(ctx);
+			if (db==null) throw new Exception("Cannot find database!");
+			Entity entity = db.getEntity("localized");
+			if (entity==null) throw new Exception("Cannot find 'localized' database entity!");
+			_localeStrings = new Map<<Locale,Map<Object,String>>;
+			RowIterator locales = entity.query();
+			while (locales.hasNext()) {
+				Instance row = (Instance)locales.next();
+				String locale = (String)row.get("locale");
+				String string = (String)row.get("string");
+				
+			}
+
+			_initialized = true;
+		} catch (Exception e) {
+			Logger.log(e);
+		}
+	}
+
+	public String get(Object id) {
+		return "";
+	}
+
+	private static boolean _initialized = false;
+
+	protected static Map<Locale,Map<Object,String>> _localeStrings = null;
+	protected static Map<Object,String> _
+}
+
+

Added: velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/toolbox.xml
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/toolbox.xml?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/toolbox.xml (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/toolbox.xml Fri Mar  9 16:23:25 2012
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<toolbox>
+
+  <tool>
+    <key>db</key>
+    <scope>request</scope>
+    <class>velosurf.web.VelosurfTool</class>
+  </tool>
+
+  <tool>
+    <key>query</key>
+    <scope>request</scope>
+    <class>velosurf.web.HttpQueryTool</class>
+  </tool>
+
+  <tool>
+    <key>logger</key>
+    <scope>application</scope>
+    <class>velosurf.util.Logger</class>
+  </tool>
+
+  <tool>
+    <key>local</key>
+    <scope>session</scope>
+    <class>velosurf.web.l10n.SimpleDBLocalizer</class>
+  </tool>
+
+  <tool>
+    <key>auth</key>
+    <scope>session</scope>
+    <class>velosurf.web.auth.SimpleDBAuthenticator</class>
+    <parameter name='method' value='HmacMD5'/>
+  </tool>
+
+</toolbox>

Added: velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/velocity.properties
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/velocity.properties?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/velocity.properties (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/velocity.properties Fri Mar  9 16:23:25 2012
@@ -0,0 +1,5 @@
+# VelocityViewServlet uses the WebappLoader.
+
+resource.loader = webapp
+webapp.resource.loader.class = org.apache.velocity.tools.view.servlet.WebappLoader
+webapp.resource.loader.path = /

Added: velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/web.xml?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/web.xml (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/WEB-INF/web.xml Fri Mar  9 16:23:25 2012
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" 
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+  <!-- Filters -->
+
+  <!-- filter used to map .html.vtl towards .vtl -->
+  <filter>
+    <filter-name>templatename</filter-name>
+    <filter-class>velosurf.util.TemplateNameFilter</filter-class>
+    <init-param>
+      <param-name>reset-method</param-name>
+      <param-value>manual</param-value>
+    </init-param>
+  </filter>
+
+  <!-- filter used to redirect /foo.html towards /en/foo.html or /fr/foo.html -->
+  <filter>
+    <filter-name>localization</filter-name>
+    <filter-class>velosurf.web.l10n.LocalizationFilter</filter-class>
+    <init-param>
+      <param-name>localization-method</param-name>
+      <param-value>redirect</param-value>
+    </init-param>
+  </filter>
+
+  <!-- filter used to require authentication for /en/auth/* and /fr/auth/* -->
+  <!-- the '@' in parameter values is a placeholder for 'en' or 'fr' -->
+  <filter>
+    <filter-name>authentication</filter-name>
+    <filter-class>velosurf.web.auth.AuthenticationFilter</filter-class>
+    <init-param>
+      <param-name>index-page</param-name>
+      <param-value>/@/index.html</param-value>
+    </init-param>
+    <init-param>
+      <param-name>login-page</param-name>
+      <param-value>/@/login.html</param-value>
+    </init-param>
+    <init-param>
+      <param-name>authenticated-index-page</param-name>
+      <param-value>/@/auth/index.html</param-value>
+    </init-param>
+  </filter>
+
+  <!-- Filter Mapping -->
+
+  <filter-mapping>
+    <filter-name>templatename</filter-name>
+    <url-pattern>/*</url-pattern>
+    <dispatcher>REQUEST</dispatcher>
+  </filter-mapping>
+
+  <filter-mapping>
+    <filter-name>localization</filter-name>
+    <url-pattern>/*</url-pattern>
+    <dispatcher>REQUEST</dispatcher>
+    <dispatcher>FORWARD</dispatcher>
+  </filter-mapping>
+
+  <filter-mapping>
+    <filter-name>authentication</filter-name>
+    <url-pattern>/en/auth/*</url-pattern>
+    <dispatcher>REQUEST</dispatcher>
+    <dispatcher>FORWARD</dispatcher>
+  </filter-mapping>
+
+  <filter-mapping>
+    <filter-name>authentication</filter-name>
+    <url-pattern>/fr/auth/*</url-pattern>
+    <dispatcher>REQUEST</dispatcher>
+    <dispatcher>FORWARD</dispatcher>
+  </filter-mapping>
+
+  <filter-mapping>
+    <filter-name>authentication</filter-name>
+    <url-pattern>*.do</url-pattern>
+    <dispatcher>REQUEST</dispatcher>
+    <dispatcher>FORWARD</dispatcher>
+  </filter-mapping>
+
+  <!-- Servlets -->
+
+  <servlet>
+    <servlet-name>velocityview</servlet-name> 
+    <servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet</servlet-class>
+    <load-on-startup/>
+  </servlet>
+
+  <!-- Servlet Mapping -->
+
+  <servlet-mapping>
+    <servlet-name>velocityview</servlet-name> 
+    <url-pattern>*.vtl</url-pattern> 
+  </servlet-mapping>
+
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file> 
+    <welcome-file>index.html.vtl</welcome-file> 
+  </welcome-file-list>
+
+  <!-- context params -->
+
+  <context-param>
+    <param-name>org.apache.velocity.properties</param-name>
+    <param-value>/WEB-INF/velocity.properties</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>org.apache.velocity.toolbox</param-name>
+    <param-value>/WEB-INF/toolbox.xml</param-value>
+  </context-param>
+
+</web-app>

Added: velocity/sandbox/velosurf/examples/auth-l10n/en/auth/index.html.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/en/auth/index.html.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/en/auth/index.html.vtl (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/en/auth/index.html.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,8 @@
+<html>
+<body>
+Loggued!
+<br>
+<a href="logout.do">Logout</a>
+</body>
+</html>
+

Added: velocity/sandbox/velosurf/examples/auth-l10n/en/index.html.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/en/index.html.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/en/index.html.vtl (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/en/index.html.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,7 @@
+<html>
+<body>
+Hello.
+<br>
+<a href="./login.html">Login</a>
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/auth-l10n/en/login.html.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/en/login.html.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/en/login.html.vtl (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/en/login.html.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,26 @@
+<html>
+<head>
+<title>Login</title>
+<script type='text/javascript' src='./md5.js'></script>
+<script type='text/javascript'>
+    function sendLogin() {
+        document.hidden.elements['login'].value = document.login.elements['login'].value;
+        document.hidden.elements['password'].value = b64_hmac_md5(document.login.elements['password'].value,'$auth.challenge');
+        document.hidden.submit();
+    }
+</script>
+</head>
+<body>
+$!loginMessage<br>
+Identification:<br>
+<form name='login' action='javascript:sendLogin()' method=POST>
+    Login: <input type=text name=login size=25 maxlength=30><br>
+    Password: <input type=password name=password  size=15 maxlenght=50"><br>
+    <input type=submit value="Ok"><br>
+</form>
+<form name='hidden' action='login.do' method=POST>
+  <input type=hidden name=login>
+  <input type=hidden name=password>
+</form>
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/auth-l10n/en/md5.js
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/en/md5.js?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/en/md5.js (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/en/md5.js Fri Mar  9 16:23:25 2012
@@ -0,0 +1,256 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+  var bkey = str2binl(key);
+  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+  return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}

Added: velocity/sandbox/velosurf/examples/auth-l10n/fr/auth/index.html.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/fr/auth/index.html.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/fr/auth/index.html.vtl (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/fr/auth/index.html.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,9 @@
+<html>
+<body>
+loggué !
+<br>
+<a href="logout.do">se déconnecter</a>
+
+</body>
+</html>
+

Added: velocity/sandbox/velosurf/examples/auth-l10n/fr/index.html.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/fr/index.html.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/fr/index.html.vtl (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/fr/index.html.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,6 @@
+<html>
+<body>
+Salut !
+<a href="./login.html">S'identifier</a>
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/auth-l10n/fr/login.html.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/fr/login.html.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/fr/login.html.vtl (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/fr/login.html.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,28 @@
+<html>
+<head>
+<title>Login</title>
+<script type='text/javascript' src='./md5.js'></script>
+<script type='text/javascript'>
+    function sendLogin() {
+        document.hidden.elements['login'].value = document.login.elements['login'].value;
+        document.hidden.elements['password'].value = b64_hmac_md5(document.login.elements['password'].value,'$auth.challenge');
+        document.hidden.submit();
+    }
+</script>
+</head>
+<body>
+$!loginMessage<br>
+Identification:<br>
+<form name='login' action='javascript:sendLogin()' method=POST>
+<table>
+<tr><td>Login :</td><td><input type=text name=login size=25 maxlength=30></td></tr>
+<tr><td>Mot de passe :</td><td><input type=password name=password  size=15 maxlenght=50"></td></tr>
+<tr><td>&nbsp;</td><td><input type=submit value="Ok"></td></tr>
+</table>
+</form>
+<form name='hidden' action='login.do' method=POST>
+  <input type=hidden name=login>
+  <input type=hidden name=password>
+</form>
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/auth-l10n/fr/md5.js
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/fr/md5.js?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/auth-l10n/fr/md5.js (added)
+++ velocity/sandbox/velosurf/examples/auth-l10n/fr/md5.js Fri Mar  9 16:23:25 2012
@@ -0,0 +1,256 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+  var bkey = str2binl(key);
+  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+  return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}

Added: velocity/sandbox/velosurf/examples/auth-l10n/index.html
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/auth-l10n/index.html?rev=1298906&view=auto
==============================================================================
    (empty)

Added: velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/macros.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/macros.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/macros.vtl (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/macros.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1 @@
+## global macros definition

Added: velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/model.xml
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/model.xml?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/model.xml (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/model.xml Fri Mar  9 16:23:25 2012
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<database read-only="false" loglevel="debug" reverse="full" url="jdbc:mysql://127.0.0.1/my_database?useUnicode=true&amp;characterEncoding=utf-8" user="the_user" password="foobar">
+</database>

Added: velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/tools.xml
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/tools.xml?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/tools.xml (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/tools.xml Fri Mar  9 16:23:25 2012
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+
+<tools>
+  <toolbox scope="request">
+    <tool key="db" class="velosurf.web.VelosurfTool"/>
+  </toolbox>
+  <toolbox scope="session">
+  </toolbox>
+  <toolbox scope="application">
+    <tool key="date" class="org.apache.velocity.tools.generic.ComparisonDateTool" locale="en_US"/>
+    <tool key="log" class="org.apache.velocity.velosurf.util.Logger"/>
+    <tool key="coll" class="org.apache.velocity.velosurf.util.StringLists"/>
+    <tool key="number" class="org.apache.velocity.tools.generic.NumberTool" locale="en_US"/>
+  </toolbox>
+</tools>

Added: velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/velocity.properties
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/velocity.properties?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/velocity.properties (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/velocity.properties Fri Mar  9 16:23:25 2012
@@ -0,0 +1,39 @@
+# resource loading
+#webapp.resource.loader.cache = false
+resource.manager.logwhenfound = false
+
+# global macros file
+velocimacro.library=/WEB-INF/macros.vtl
+
+# allow inline definition of macros
+velocimacro.permissions.allowInline=true
+
+## TODO review this
+# VMs can be defined inline in templates
+velocimacro.permissions.allowInline = true
+velocimacro.permissions.allow.inline = true
+# VMs defined inline may NOT replace previous VM definitions
+velocimacro.permissions.allowInlineToOverride = true
+velocimacro.permissions.allow.inline.to.replace.global = true
+# VMs defined inline will be global in scope if allowed.
+velocimacro.permissions.allowInlineLocal = true
+velocimacro.permissions.allow.inline.local.scope = true
+
+directive.set.null.allowed = true
+
+# encoding
+input.encoding = UTF8
+output.encoding = UTF8
+
+# content type
+default.contentType = text/html
+
+# relative loading
+eventhandler.include.class = org.apache.velocity.app.event.implement.IncludeRelativePath
+
+# Use the VelosurfUberspector to allow parametrized getters
+runtime.introspector.uberspect = org.apache.velocity.util.introspection.UberspectImpl,org.apache.velocity.tools.view.WebappUberspector,org.apache.velocity.velosurf.util.VelosurfUberspector
+
+# default to servletlogger, which logs to the servlet engines log
+runtime.log.logsystem.class = org.apache.velocity.runtime.log.ServletLogChute
+runtime.log.logsystem.servlet.level = info

Added: velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/web.xml?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/web.xml (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/WEB-INF/web.xml Fri Mar  9 16:23:25 2012
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+  <!-- Filters -->
+
+  <!-- Filter Mapping -->
+
+  <!-- Servlets -->
+
+  <servlet>
+    <servlet-name>view</servlet-name>
+    <servlet-class>org.apache.velocity.tools.view.VelocityViewServlet</servlet-class>
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+
+  <!-- Servlet Mapping -->
+
+  <servlet-mapping>
+    <servlet-name>view</servlet-name>
+    <url-pattern>*.vhtml</url-pattern>
+  </servlet-mapping>
+
+  <!-- Listeners -->
+
+  <!-- Welcome Files -->
+
+  <welcome-file-list>
+    <welcome-file>index.vhtml</welcome-file>
+  </welcome-file-list>
+
+  <!-- context params -->
+
+</web-app>

Added: velocity/sandbox/velosurf/examples/blank-webapp/doctype.inc
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/doctype.inc?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/doctype.inc (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/doctype.inc Fri Mar  9 16:23:25 2012
@@ -0,0 +1 @@
+<!DOCTYPE html>

Added: velocity/sandbox/velosurf/examples/blank-webapp/footer.inc
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/footer.inc?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/footer.inc (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/footer.inc Fri Mar  9 16:23:25 2012
@@ -0,0 +1,3 @@
+<div class="footer">
+&copy; 2005-2012 Guo Juan. All rights reserved. <a href="/terms.vhtml">Terms of Use</a>
+</div>

Added: velocity/sandbox/velosurf/examples/blank-webapp/header.inc
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/header.inc?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/header.inc (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/header.inc Fri Mar  9 16:23:25 2012
@@ -0,0 +1,7 @@
+#if(!$title)#set($title="Blank Webapp")#end
+<title>Velosurf - $title</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<meta name="author" content="Claude Brisson"/>
+<meta name="description" content="Velosurf Blank Example Webapp" />
+<meta name="keywords" content="Velocity Veelosurf Tools Webapp Dynamic Content Template Templating" />
+<link href="/main.css" rel="stylesheet" type="text/css" />

Added: velocity/sandbox/velosurf/examples/blank-webapp/index.vhtml
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/index.vhtml?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/index.vhtml (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/index.vhtml Fri Mar  9 16:23:25 2012
@@ -0,0 +1,15 @@
+#parse("doctype.inc")
+<html>
+  <head>
+#parse("header.inc")
+  </head>
+  <body>
+    <div class="container">
+#parse("top.inc")
+      <div class="content">
+        Now add some content!
+      </div>
+#parse("footer.inc")
+    </div>
+  </body>
+</html>

Added: velocity/sandbox/velosurf/examples/blank-webapp/main.css
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/main.css?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/main.css (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/main.css Fri Mar  9 16:23:25 2012
@@ -0,0 +1 @@
+@charset "UTF-8";

Added: velocity/sandbox/velosurf/examples/blank-webapp/top.inc
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/blank-webapp/top.inc?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/blank-webapp/top.inc (added)
+++ velocity/sandbox/velosurf/examples/blank-webapp/top.inc Fri Mar  9 16:23:25 2012
@@ -0,0 +1 @@
+<h1>$title</h1>

Added: velocity/sandbox/velosurf/examples/bookstore/README
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/README?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/README (added)
+++ velocity/sandbox/velosurf/examples/bookstore/README Fri Mar  9 16:23:25 2012
@@ -0,0 +1,35 @@
+PREREQUISITES :
+
+You know how to install a web-app in your servlet container (and you have one,
+don't you ? tomcat, resin, jetty, weblogic, websphere....).
+
+You know how to create a database in your DBMS, you've got the appropriate
+jdbc driver, and you know the user/password/url combination to get access to
+the bookstore database
+
+INSTALLATION :
+
+1. copy the 'bookstore' directory to your webapps directory and configure your
+servlets container ; don't forget to set up the web-app log (specific to your
+container), it might be usefull
+
+2. copy necessary libs to the /WEB-INF/lib directory (/velosurf-x.y.jar,
+along with those provided in the /lib/ directory should be ok, but
+don't forget the libraries of your JDBC driver)
+
+3. create the 'bookstore' database or schema using your favourite DBMS and the
+provided bookstore.sql. You may have to adapt a little bit the file so that it
+fits with your dmbs rules (just try and catch SQL errors...).
+
+4. edit the first line of /WEB-INF/velosurf.xml, don't forget to add
+schema="bookstore" if 'bookstore' is a schema.
+
+5. check it works by pointing your browser to http://your_server/bookstore and
+by browsing a bit. If yes, shout "YEEEEEEEEEEES !", else crawl the logs, debug
+your config, and retry...
+
+REMARKS :
+
+As you may notice, the IDs of new objects are randomly choosen - it's because
+this method is database independant. It is somewhat redundant with the use of
+IDs obfuscation, and not recommended in a real app, but this is a sample !

Added: velocity/sandbox/velosurf/examples/bookstore/WEB-INF/toolbox.xml
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/WEB-INF/toolbox.xml?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/WEB-INF/toolbox.xml (added)
+++ velocity/sandbox/velosurf/examples/bookstore/WEB-INF/toolbox.xml Fri Mar  9 16:23:25 2012
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+
+<toolbox>
+
+  <tool>
+    <key>db</key>
+    <scope>request</scope>
+    <class>velosurf.web.VelosurfTool</class>
+  </tool>
+
+  <tool>
+    <key>query</key>
+    <scope>request</scope>
+    <class>velosurf.web.HttpQueryTool</class>
+  </tool>
+
+  <tool>
+    <key>logger</key>
+    <scope>application</scope>
+    <class>velosurf.util.Logger</class>
+  </tool>
+
+  <tool>
+	  <key>random</key>
+	  <scope>application</scope>
+	  <class>java.util.Random</class>
+  </tool>
+
+</toolbox>

Added: velocity/sandbox/velosurf/examples/bookstore/WEB-INF/velocity.properties
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/WEB-INF/velocity.properties?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/WEB-INF/velocity.properties (added)
+++ velocity/sandbox/velosurf/examples/bookstore/WEB-INF/velocity.properties Fri Mar  9 16:23:25 2012
@@ -0,0 +1,7 @@
+# VelocityViewServlet uses the WebappLoader.
+
+resource.loader = webapp
+
+webapp.resource.loader.class = org.apache.velocity.tools.view.servlet.WebappLoader
+webapp.resource.loader.path = /
+

Added: velocity/sandbox/velosurf/examples/bookstore/WEB-INF/velosurf.xml
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/WEB-INF/velosurf.xml?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/WEB-INF/velosurf.xml (added)
+++ velocity/sandbox/velosurf/examples/bookstore/WEB-INF/velosurf.xml Fri Mar  9 16:23:25 2012
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<database user="USER" password="PASSWORD" url="jdbc:MY_DBMS://127.0.0.1/bookstore" default-access="rw" >
+
+	<entity name="publisher" obfuscate="publisher_id" autofetch="publisher_id">
+		<attribute name="books" result="rowset/book" xml:space="preserve">
+			SELECT * FROM book WHERE publisher_id=<publisher_id/>
+		</attribute>
+	</entity>
+
+	<entity name="author" obfuscate="author_id" autofetch="author_id">
+		<attribute name="books" result="rowset/book" xml:space="preserve">
+			SELECT * FROM book WHERE author_id=<author_id/>
+		</attribute>
+		<attribute name="full_name" result="scalar" xml:space="preserve">
+		    SELECT CONCAT(first_name,CONCAT(' ',last_name)) FROM author WHERE author_id=<author_id/>
+		</attribute>
+	</entity>
+
+	<entity name="book" obfuscate="book_id,author_id,publisher_id" autofetch="book_id">
+		<attribute name="publisher" result="row/publisher" foreign-key="publisher_id"/>
+		<attribute name="author" result="row/author" foreign-key="author_id"/>
+	</entity>
+
+	<attribute name="books_nb" result="scalar">
+		select count(*) from book
+	</attribute>
+
+</database>

Added: velocity/sandbox/velosurf/examples/bookstore/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/WEB-INF/web.xml?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/WEB-INF/web.xml (added)
+++ velocity/sandbox/velosurf/examples/bookstore/WEB-INF/web.xml Fri Mar  9 16:23:25 2012
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+  <servlet>
+    <servlet-name>velocity</servlet-name> 
+    <servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet</servlet-class>
+    <init-param>
+      <param-name>org.apache.velocity.toolbox</param-name> 
+      <param-value>/WEB-INF/toolbox.xml</param-value> 
+    </init-param>
+    <init-param>
+      <param-name>org.apache.velocity.properties</param-name> 
+      <param-value>/WEB-INF/velocity.properties</param-value> 
+    </init-param>
+    <init-param>
+      <param-name>velosurf.config</param-name> 
+      <param-value>/WEB-INF/velosurf.xml</param-value> 
+    </init-param>
+    <load-on-startup>10</load-on-startup> 
+  </servlet>
+
+<servlet-mapping>
+  <servlet-name>velocity</servlet-name> 
+  <url-pattern>*.vm</url-pattern> 
+</servlet-mapping>
+
+<welcome-file-list>
+  <welcome-file>index.vm</welcome-file> 
+</welcome-file-list>
+
+</web-app>

Added: velocity/sandbox/velosurf/examples/bookstore/author_commit.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/author_commit.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/author_commit.vtl (added)
+++ velocity/sandbox/velosurf/examples/bookstore/author_commit.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,27 @@
+## please note than in a strict MVC design pattern, modifications should NOT be triggered from inside templates
+## but rather by an assermented controller object !!!
+
+<html>
+<head>
+<title>The Bookstore Sample</title>
+</head>
+<body>
+#if($query.author_id)
+  #set($success = $db.author.update($query))
+#else
+  ## automatic id generation is not standardized among DBMS
+  ## here since it's a demo we'll use random numbers
+  ## and obfuscate it, since it will be deobfuscated...
+  #set($query.author_id = $db.obfuscate($random.nextInt()))
+  #set($success = $db.author.insert($query))
+#end
+
+#if($success)
+  Operation successfull.
+#else
+  Error encountered : $db.error
+#end
+<br>
+[<a href="./index.vtl">home</a>]
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/bookstore/author_delete.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/author_delete.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/author_delete.vtl (added)
+++ velocity/sandbox/velosurf/examples/bookstore/author_delete.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,18 @@
+## please note than in a strict MVC design pattern, modifications should NOT be triggered from inside templates
+## but rather by an assermented controller object !!!
+
+<html>
+<head>
+<title>The Bookstore Sample</title>
+</head>
+<body>
+#set($success = $db.author.delete($query))
+#if($success)
+  Operation successfull.
+#else
+  Error encountered : $!db.error
+#end
+<br>
+[<a href="./index.vtl">home</a>]
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/bookstore/author_form.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/author_form.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/author_form.vtl (added)
+++ velocity/sandbox/velosurf/examples/bookstore/author_form.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>The Bookstore Sample</title>
+</head>
+<body>
+#if($query.author_id) #set( $author = $db.author.fetch($query.author_id) ) #end
+
+#if($author)
+<h2>Edit author</h2>
+#else
+<h2>Add author</h2>
+#end
+<ul>
+<form method="post" action="./author_commit.vtl">
+<input type="hidden" name="author_id" value="$!author.author_id">
+<li>First Name : <input type="text" name="first_name" value="$!author.first_name">
+<li>Last Name : <input type="text" name="last_name" value="$!author.last_name">
+</ul>
+<input type="submit" value="Ok">
+</form>
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/bookstore/book_commit.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/book_commit.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/book_commit.vtl (added)
+++ velocity/sandbox/velosurf/examples/bookstore/book_commit.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,27 @@
+## please note than in a strict MVC design pattern, modifications should NOT be triggered from inside templates
+## but rather by an assermented controller object !!!
+
+<html>
+<head>
+<title>The Bookstore Sample</title>
+</head>
+<body>
+#if($query.book_id.length() > 0)
+  #set($success = $db.book.update($query))
+#else
+  ## automatic id generation is not standardized among DBMS
+  ## here since it's a demo we'll use random numbers
+  ## and obfuscate it, since it will be deobfuscated...
+  #set($query.book_id = $db.obfuscate($random.nextInt()))
+  #set($success = $db.book.insert($query))
+#end
+
+#if($success)
+  Operation successfull.
+#else
+  Error encountered : $db.error
+#end
+<br>
+[<a href="./index.vtl">home</a>]
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/bookstore/book_delete.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/book_delete.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/book_delete.vtl (added)
+++ velocity/sandbox/velosurf/examples/bookstore/book_delete.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,17 @@
+## please note than in a strict MVC design pattern, modifications should NOT be triggered from inside templates
+## but rather by an assermented controller object !!!
+
+<html>
+<head>
+<title>The Bookstore Sample</title>
+</head>
+<body>
+#set($success = $db.book.delete($query))
+#if($success == 1)
+  Operation successfull.
+#else
+  Error encountered : $db.error
+#end<br>
+[<a href="./index.vtl">home</a>]
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/bookstore/book_form.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/book_form.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/book_form.vtl (added)
+++ velocity/sandbox/velosurf/examples/bookstore/book_form.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,38 @@
+<html>
+<head>
+<title>The Bookstore Sample</title>
+</head>
+<body>
+#if($query.book_id) #set( $book = $db.book.fetch($query.book_id) ) #end
+
+#if($book)
+<h2>Edit book</h2>
+#else
+<h2>Add book</h2>
+#end
+<ul>
+<form method="post" action="./book_commit.vtl">
+<input type="hidden" name="book_id" value="$!book.book_id">
+<li>Title : <input type="text" name="title" value="$!book.title">
+<li>Author :
+  <select name="author_id">
+  #set( $db.author.order = "last_name" )
+    <option value="0" #if(!$query.book_id) selected #end>choose author</option>
+  #foreach($author in $db.author)
+    <option value="$author.author_id" #if($book && $book.author_id == $author.author_id) selected #end>$!author.full_name</option>
+  #end
+  </select>
+<li>Publisher :
+  <select name="publisher_id">
+  #set( $db.publisher.order = "name" )
+    <option value="0" #if(!$query.book_id) selected #end>choose publisher</option>
+  #foreach($publisher in $db.publisher)
+    <option value="$publisher.publisher_id" #if($book && $book.publisher_id == $publisher.publisher_id) selected #end>$publisher.name</option>
+  #end
+  </select>
+<li>ISBN Code : <input type="text" name="isbn" value="$!book.isbn">
+</ul>
+<input type="submit" value="Ok">
+</form>
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/bookstore/bookstore.sql
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/bookstore.sql?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/bookstore.sql (added)
+++ velocity/sandbox/velosurf/examples/bookstore/bookstore.sql Fri Mar  9 16:23:25 2012
@@ -0,0 +1,39 @@
+
+---- For Oracle (add an attribute << schema="BOOKSTORE" >> to the database element in velosurf.xml)
+-- CREATE USER BOOKSTORE IDENTIFIED GLOBALLY AS '' DEFAULT TABLESPACE USERS;
+-- ALTER USER BOOKSTORE QUOTA 1M ON USERS;
+-- ALTER SESSION SET CURRENT_SCHEMA = BOOKSTORE;
+
+---- Some databases (like Postgresql) don't like the CONCAT function, but only like the concatenation operator '||' (not recognized by others like mysql...)
+---- So you may have to adapt this.
+
+CREATE TABLE publisher (
+	publisher_id INTEGER NOT NULL PRIMARY KEY,
+	name VARCHAR(128) NOT NULL
+);
+
+CREATE TABLE author (
+	author_id INTEGER NOT NULL PRIMARY KEY,
+	first_name VARCHAR(128) NOT NULL,
+	last_name VARCHAR(128) NOT NULL
+);
+
+CREATE TABLE book (
+	book_id INTEGER NOT NULL PRIMARY KEY,
+	title VARCHAR(255) NOT NULL,
+	isbn VARCHAR(24) NOT NULL,
+    publisher_id INTEGER NOT NULL,
+    author_id INTEGER NOT NULL,
+    FOREIGN KEY(publisher_id) REFERENCES publisher(publisher_id),
+    FOREIGN KEY(author_id) REFERENCES author(author_id)
+#	publisher_id INTEGER NOT NULL REFERENCES publisher(publisher_id),
+#	author_id INTEGER NOT NULL REFERENCES author(author_id)
+);
+
+INSERT INTO publisher (publisher_id,name) VALUES (1,'Addison Wesley Professional');
+
+INSERT INTO author (author_id,first_name,last_name) VALUES (1,'Joshua','Bloch');
+INSERT INTO author (author_id,first_name,last_name) VALUES (2,'W.','Stevens');
+
+INSERT INTO book (book_id,title,isbn,publisher_id,author_id) VALUES (1,'Effective Java','0-618-12902-2',1,1);
+INSERT INTO book (book_id,title,isbn,publisher_id,author_id) VALUES (2,'TCP/IP Illustrated, Volume 1','0-201-63346-9',1,2);

Added: velocity/sandbox/velosurf/examples/bookstore/index.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/index.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/index.vtl (added)
+++ velocity/sandbox/velosurf/examples/bookstore/index.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,54 @@
+<html>
+<head>
+<title>The Bookstore Sample</title>
+</head>
+<body>
+<h2>Welcome to the bookstore !</h2>
+
+#if($query.by_publisher)
+  #if($publisher)
+    <p>Books published by <b>$publisher.name</b> :</p>
+    <ul>
+    #foreach($book in $publisher.books)
+      <li><b>$book.title</b> by <i>$book.author.full_name</i> (ISBN $book.isbn) [<a href="./book_form.vtl?book_id=$book.book_id">edit</a>] [<a href="./book_delete.vtl?book_id=$book.book_id" onClick="return confirm('Are you sure ?')">delete</a>]
+    #end
+    </ul>
+  #else
+    <p>Publishers :</p>
+    <ul>
+    #foreach($publisher in $db.publisher)
+      <li><b>$publisher.name</b> [<a href="./index.vtl?by_publisher=1&publisher_id=$publisher.publisher_id">see books</a>] [<a href="./publisher_form.vtl?publisher_id=$publisher.publisher_id">edit</a>] [<a href="./publisher_delete.vtl?publisher_id=$publisher.publisher_id" onClick="return confirm('Are you sure ?')">delete</a>]
+    #end
+    </ul>
+  #end
+[<a href="./index.vtl">home</a>]
+#elseif($query.by_author)
+  #if($author)
+    <p>Books written by <b>$author.full_name</b> :</p>
+    <ul>
+    #foreach($book in $author.books)
+      <li><b>$book.title</b> by <i>$book.author.full_name</i> (ISBN $book.isbn) [<a href="./book_form.vtl?book_id=$book.book_id">edit</a>] [<a href="./book_delete.vtl?book_id=$book.book_id" onClick="return confirm('Are you sure ?')">delete</a>]
+    #end
+    </ul>
+  #else
+    <p>Authors :</p>
+    <ul>
+    #foreach($author in $db.author)
+      <li><b>$author.full_name</b> [<a href="./index.vtl?by_author=1&author_id=$author.author_id">see books</a>] [<a href="./author_form.vtl?author_id=$author.author_id">edit</a>] [<a href="./author_delete.vtl?author_id=$author.author_id" onClick="return confirm('Are you sure ?')">delete</a>]
+    #end
+    </ul>
+  #end
+[<a href="./index.vtl">home</a>]
+#else
+  <p>We have $db.books_nb books in stock.</p>
+  <p>You can browse the books [<a href="./index.vtl?by_publisher=1">by publisher</a>] or [<a href="./index.vtl?by_author=1">by author</a>].</p>
+  <p>You can also :</p>
+    <ul>
+      <li>[<a href="./publisher_form.vtl">add a new publisher</a>]
+      <li>[<a href="./author_form.vtl">add a new author</a>]
+      <li>[<a href="./book_form.vtl">add a new book</a>]
+    </ul>
+#end
+
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/bookstore/publisher_commit.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/publisher_commit.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/publisher_commit.vtl (added)
+++ velocity/sandbox/velosurf/examples/bookstore/publisher_commit.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,27 @@
+## please note than in a strict MVC design pattern, modifications should NOT be triggered from inside templates
+## but rather by an assermented controller object !!!
+
+<html>
+<head>
+<title>The Bookstore Sample</title>
+</head>
+<body>
+#if($query.publisher_id.length() > 0)
+  #set($success = $db.publisher.update($query))
+#else
+  ## automatic id generation is not standardized among DBMS
+  ## here we'll use random numbers
+  ## and obfuscate it, since it will be deobfuscated...
+  #set($query.publisher_id = $db.obfuscate($random.nextInt()))
+  #set($success = $db.publisher.insert($query))
+#end
+
+#if($success)
+  Operation successfull.
+#else
+  Error encountered : $db.error
+#end
+<br>
+[<a href="./index.vtl">home</a>]
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/bookstore/publisher_delete.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/publisher_delete.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/publisher_delete.vtl (added)
+++ velocity/sandbox/velosurf/examples/bookstore/publisher_delete.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,18 @@
+## please note than in a strict MVC design pattern, modifications should NOT be triggered from inside templates
+## but rather by an assermented controller object !!!
+
+<html>
+<head>
+<title>The Bookstore Sample</title>
+</head>
+<body>
+#set($success = $db.publisher.delete($query))
+#if($success == 1)
+  Operation successfull.
+#else
+  Error encountered : $db.error
+#end
+<br>
+[<a href="./index.vtl">home</a>]
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/bookstore/publisher_form.vtl
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/bookstore/publisher_form.vtl?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/bookstore/publisher_form.vtl (added)
+++ velocity/sandbox/velosurf/examples/bookstore/publisher_form.vtl Fri Mar  9 16:23:25 2012
@@ -0,0 +1,21 @@
+<html>
+<head>
+<title>The Bookstore Sample</title>
+</head>
+<body>
+#if($query.publisher_id) #set( $publisher = $db.publisher.fetch($query.publisher_id) ) #end
+
+#if($publisher)
+<h2>Edit publisher</h2>
+#else
+<h2>Add publisher</h2>
+#end
+<ul>
+<form method="post" action="./publisher_commit.vtl">
+<input type="hidden" name="publisher_id" value="$!publisher.publisher_id">
+<li>Name : <input type="text" name="name" value="$!publisher.name">
+</ul>
+<input type="submit" value="Ok">
+</form>
+</body>
+</html>

Added: velocity/sandbox/velosurf/examples/validation/README
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/examples/validation/README?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/examples/validation/README (added)
+++ velocity/sandbox/velosurf/examples/validation/README Fri Mar  9 16:23:25 2012
@@ -0,0 +1,3 @@
+To find an example for the validation filter, check the test webapp that
+you will find in the ./test/webapp directory.
+

Added: velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/Velosurf.java
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/Velosurf.java?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/Velosurf.java (added)
+++ velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/Velosurf.java Fri Mar  9 16:23:25 2012
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2003 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+package org.apache.velocity.velosurf;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.SQLException;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.velosurf.context.DBReference;
+import org.apache.velocity.velosurf.sql.Database;
+import org.apache.velocity.velosurf.util.Logger;
+import org.apache.velocity.velosurf.util.XIncludeResolver;
+
+/**
+ * <p>This class is the Velosurf main entry class if you do not use the toolbox.xml mechanism.
+ *  Unless you specify the model file to use, it will successively search for a model file :</p>
+ *  <ul>
+ *  <li><p>from the java property "config.velosurf" (like in 'java -Dconfig.velosurf=/.../velosurf.xml ...' )</p>
+ *  <li><p>from the Velocity property "config.velosurf" (entry of the velocity.properties file)</p>
+ *  <li><p>as './velosurf.xml', './conf/velosurf.xml', './WEB-INF/velosurf.xml', './cfg/velosurf.xml'
+ * </ul>
+ *
+ * @author <a href="mailto:claude.brisson@gmail.com">Claude Brisson</a>
+ *
+ */
+public class Velosurf extends DBReference
+{
+    /**
+     * Initialization flag.
+     */
+    private boolean initialized = false;
+
+    /**
+     * Configuration file.
+     */
+    private File configFile = null;
+
+    /**
+     * Empty constructor.
+     */
+    public Velosurf()
+    {
+        initLogging();
+    }
+
+    /**
+     * Constructor taking a File object as model configuration file.
+     * @param configFile model configuration file
+     * @throws IOException
+     * @throws SQLException
+     */
+    public Velosurf(String config) throws IOException, SQLException
+    {
+        initLogging();
+        configFile = new File(config);
+        init();
+    }
+
+    /**
+     * Constructor taking a File object as model configuration file.
+     * @param configFile model configuration file
+     * @throws IOException
+     * @throws SQLException
+     */
+    public Velosurf(File configFile) throws IOException, SQLException
+    {
+        initLogging();
+        this.configFile = configFile;
+        init();
+    }
+
+    /**
+     * Constructor taking an InputStream object as model configuration.
+     * @param config
+     * @throws IOException
+     * @throws SQLException
+     * @deprecated use others constructor
+     */
+     public Velosurf(InputStream config) throws IOException, SQLException
+    {
+        initLogging();
+        init(config);
+    }
+
+    /**
+     * Explicitely set the model configuration file.
+     * @param config model configuration pathname
+     */
+    public void setConfigFile(String config)
+    {
+        configFile = new File(config);
+    }
+
+    /**
+     * Initializes the logger.
+     */
+    private void initLogging()
+    {
+        if(!Logger.isInitialized())
+        {
+            Logger.log2Stderr();
+        }
+    }
+
+    /**
+     * Tries to find a model configuration file using some default locations.
+     * @return the pathname of the model configuration file, if found - null otherwise
+     */
+    private void findConfig()
+    {
+        String pathname = null;
+        File file = null;
+
+        /* first, ask Java */
+        pathname = System.getProperty("velosurf.config");
+        if(pathname != null)
+        {
+            file = new File(pathname);
+            if(file.exists())
+            {
+                configFile = file;
+            }
+        }
+
+        /* then Velocity */
+        pathname = (String)Velocity.getProperty("velosurf.config");
+        if(pathname != null)
+        {
+            file = new File(pathname);
+            if(file.exists())
+            {
+                configFile = file;
+            }
+        }
+
+        /* then try some standard pathes */
+        String[] guesses =
+        {
+            "./velosurf.xml", "./conf/velosurf.xml", "./WEB-INF/velosurf.xml", "./cfg/velosurf.xml", "./model.xml",
+            "./conf/model.xml", "./WEB-INF/model.xml", "./cfg/model.xml"
+        };
+
+        for(int i = 0; i < guesses.length; i++)
+        {
+            file = new File(guesses[i]);
+            if(file.exists())
+            {
+                configFile = file;
+                break;
+            }
+        }
+    }
+
+    /**
+     * Lazzy initialization.
+     * @param config model configuration file input stream
+     * @throws SQLException
+     * @throws IOException
+     */
+    private void init(InputStream config) throws SQLException, IOException
+    {
+        Database db = Database.getInstance(config);
+
+        super.init(db);
+        initialized = true;
+    }
+
+    /**
+     * Lazzy initialization.
+     * @throws SQLException
+     * @throws IOException
+     */
+    private void init() throws SQLException, IOException
+    {
+        if(configFile == null)
+        {
+            findConfig();
+        }
+        if(configFile == null)
+        {
+            throw new IOException("No Velosurf config file found. Please specify one using setConfig(pathname).");
+        }
+
+        Database db = Database.getInstance(new FileInputStream(configFile), new XIncludeResolver(configFile.getAbsoluteFile().getParent()));
+
+        super.init(db);
+        initialized = true;
+    }
+
+    /**
+     * Allows to access the underlying velosurf.sql.Database object
+     * @return a Database object
+     */
+    public Database getDatabase()
+    {
+        return db;
+    }
+
+    /**
+     * Generic getter.
+     * @param key
+     * @return property
+     */
+    public Object get(Object key)
+    {
+        if(!initialized)
+        {
+            try
+            {
+                init();
+            }
+            catch(Exception e)
+            {
+                Logger.log(e);
+                return null;
+            }
+        }
+        return super.get(key);
+    }
+
+    /**
+     * Generic setter.
+     * @param key
+     * @param value
+     * @return old value
+     */
+    public Object put(String key, Object value)
+    {
+        if(!initialized)
+        {
+            try
+            {
+                init();
+            }
+            catch(Exception e)
+            {
+                Logger.log(e);
+                return null;
+            }
+        }
+        return super.put(key, value);
+    }
+
+    /**
+     * Schema name getter.
+     * @return the name of the current schema
+     */
+    public String getSchema()
+    {
+        if(!initialized)
+        {
+            try
+            {
+                init();
+            }
+            catch(Exception e)
+            {
+                Logger.log(e);
+                return null;
+            }
+        }
+        return super.getSchema();
+    }
+
+    /**
+     * Obfuscate the given value.
+     * @param value value to obfuscate
+     * @return obfuscated value
+     */
+    public String obfuscate(Object value)
+    {
+        if(!initialized)
+        {
+            try
+            {
+                init();
+            }
+            catch(Exception e)
+            {
+                Logger.log(e);
+                return null;
+            }
+        }
+        return super.obfuscate(value);
+    }
+
+    /**
+     * De-obfuscate the given value.
+     * @param value value to de-obfuscate
+     * @return obfuscated value
+     */
+    public String deobfuscate(Object value)
+    {
+        if(!initialized)
+        {
+            try
+            {
+                init();
+            }
+            catch(Exception e)
+            {
+                Logger.log(e);
+                return null;
+            }
+        }
+        return super.deobfuscate(value);
+    }
+}

Added: velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/cache/Cache.java
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/cache/Cache.java?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/cache/Cache.java (added)
+++ velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/cache/Cache.java Fri Mar  9 16:23:25 2012
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2003 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+package org.apache.velocity.velosurf.cache;
+
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>Cache that keeps fetched instances in memory.</p>
+ *
+ * <p>Three modes (defined for &lt;<code>database</code>&gt; or for &lt;<code>entity</code>&gt; in <code>model.xml</code>:</p>
+ * <ul>
+ * <li>NO_CACHE (cache='none', the default) : no caching occurs on this entity.
+ * <li>SOFT_CACHE (cache='soft') : caching occurs as long as memory is ont reclaimed (see the behaviour of java soft references).
+ * <li>FULL_CACHE (cache='full') : the whole table is loaded into the cache at startup.
+ * </ul>
+ *
+ * <p>For an entity's instances to be cached, the associated table must have a primary key (even if multivalued).</p>
+ *
+ * <p><b>Warning</b>: Velosurf will invalidate entries on single row update and delete queries, but global updates and deletes are not taken into account.</p>
+ * <p>This caching mechanism is meant for straightforward optimizations in read-only or very simple situations, for instance to
+ * avoid re-fetching data related to the logged user at each request.</p>
+ *
+ *  @author <a href=mailto:claude.brisson@gmail.com>Claude Brisson</a>
+ *
+ */
+public class Cache
+{
+    /**
+     * Constant used to specify the "no cache" mode.
+     */
+    public static final int NO_CACHE = 0;
+
+    /**
+     * Constant used to specify the "soft cache" mode.
+     */
+    public static final int SOFT_CACHE = 1;
+
+    /**
+     * Constant used to specify the "full cache" mode.
+     */
+    public static final int FULL_CACHE = 2;
+
+    /**
+     * Cache constructor.
+     *
+     * @param cachingMethod required caching mode
+     */
+    public Cache(int cachingMethod)
+    {
+        this.cachingMethod = cachingMethod;
+        innerCache = new HashMap();
+    }
+
+    /**
+     * Put an instance in the cache.
+     *
+     * @param key key field(s) of this instance
+     * @param value instance
+     */
+    public void put(Object key, Object value)
+    {
+        key = (key.getClass().isArray() ? new ArrayKey((Object[])key) : key);
+        value = (cachingMethod == SOFT_CACHE ? new SoftReference<Object>(value) : value);
+        synchronized(innerCache)
+        {
+            innerCache.put(key, value);
+        }
+    }
+
+    /**
+     * Getter for the size of the cache.
+     *
+     * @return the size of the cache
+     */
+    public int size()
+    {
+        return innerCache.size();
+    }
+
+    /**
+     * Try to get an instance from the cache.
+     *
+     * @param key key field(s) of the asked instance
+     * @return Asked instance or null if not found
+     */
+    public Object get(Object key)
+    {
+        key = (key.getClass().isArray() ? new ArrayKey((Object[])key) : key);
+
+        Object ret;
+
+        synchronized(innerCache)
+        {
+            ret = innerCache.get(key);
+        }
+        if(ret != null && cachingMethod == SOFT_CACHE)
+        {
+            ret = ((SoftReference<Object>)ret).get();
+
+            /* if null, clean cache */
+            if(ret == null)
+            {
+                synchronized(innerCache)
+                {
+                    innerCache.remove(key);
+                }
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Clear the cache.
+     *
+     */
+    public void clear()
+    {
+        innerCache.clear();
+    }
+
+    /**
+     * invalidates an entry
+     * (used after an insert or an update)
+     */
+    public void invalidate(Object key)
+    {
+        synchronized(innerCache)
+        {
+            innerCache.remove(key);
+        }
+    }
+
+    /**
+     * The caching method this cache uses.
+     */
+    private int cachingMethod;
+
+    /**
+     * the inner map that stores associations.
+     */
+    private Map<Object, Object> innerCache = null;
+
+    /**
+     * ArrayKey is a simple wrapper that provides a field-to-field equal method between encapsulated arrays.
+     */
+    public static final class ArrayKey
+    {
+        /**
+         * Constructor.
+         * @param keys key values
+         */
+        public ArrayKey(Object[] keys)
+        {
+            this.keys = keys;
+        }
+
+        /**
+         * Checks the cell-to-cell equality of two arrays.
+         *
+         * @param source source array
+         * @return a boolean indicating the equality
+         */
+        public boolean equals(Object source)
+        {
+            if(source instanceof ArrayKey)
+            {
+                ArrayKey k = (ArrayKey)source;
+
+                if(k.keys.length == keys.length)
+                {
+                    for(int i = 0; i < keys.length; i++)
+                    {
+                        if(!keys[i].equals(k.keys[i]))
+                        {
+                            return false;
+                        }
+                    }
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Hashcode of an array, based on the hashcode of its members.
+         *
+         * @return the hashcode
+         */
+        public int hashCode()
+        {
+            int hash = 0;
+
+            for(int i = 0; i < keys.length; i++)
+            {
+                hash += keys[i].hashCode();
+            }
+            return hash;
+        }
+
+        /**
+         * The wrapped array.
+         */
+        private Object[] keys = null;
+
+    }    /* end of inner class ArrayKey */
+}

Added: velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/cache/package.html
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/cache/package.html?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/cache/package.html (added)
+++ velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/cache/package.html Fri Mar  9 16:23:25 2012
@@ -0,0 +1,23 @@
+<html>
+<body bgcolor="white">
+
+Contains all classes that implement caching.
+
+<h2>Package Specification</h2>
+
+<!-- ANY SPECS NEEDED BY JAVA COMPATIBILITY KIT GO THERE 
+<ul>
+  <li><a href="">##### REFER TO ANY FRAMEMAKER SPECIFICATION HERE #####</a>
+</ul>
+
+<h2>Related Documentation</h2>
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+  <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
+</ul>
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>