You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by ms...@apache.org on 2007/07/04 21:27:48 UTC

svn commit: r553306 - in /tapestry/tapestry4/trunk/tapestry-framework/src: descriptor/META-INF/ java/org/apache/tapestry/ java/org/apache/tapestry/dojo/html/ java/org/apache/tapestry/event/ java/org/apache/tapestry/html/ java/org/apache/tapestry/util/i...

Author: mschulte
Date: Wed Jul  4 12:27:47 2007
New Revision: 553306

URL: http://svn.apache.org/viewvc?view=rev&rev=553306
Log:
Better fix for TAPESTRY-1202

Added:
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/event/BrowserEventTest.java
Removed:
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/util/io/JSONAdaptor.java
Modified:
    tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.data.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/ComponentEvent.script
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/event/BrowserEvent.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/html/ElementEvent.script
    tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.data.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.data.xml?view=diff&rev=553306&r1=553305&r2=553306
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.data.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.data.xml Wed Jul  4 12:27:47 2007
@@ -94,7 +94,6 @@
     <adaptor object="service:SerializableAdaptor"/>
     <adaptor object="instance:ShortAdaptor"/>
     <adaptor object="instance:StringAdaptor"/>
-    <adaptor object="instance:JSONAdaptor"/>
   </contribution>
 
 </module>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/ComponentEvent.script
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/ComponentEvent.script?view=diff&rev=553306&r1=553305&r2=553306
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/ComponentEvent.script (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/ComponentEvent.script Wed Jul  4 12:27:47 2007
@@ -17,25 +17,18 @@
         <if expression="events">
             <foreach expression="events" key="event">
                 tapestry.cleanConnect(dojo.byId("${clientId}"), "${event[0]}", "event${event[1]}");
-                tapestry.event${event[1]}=function( inv ){
-                    result = inv.proceed();
+                tapestry.event${event[1]}=function( event ){
                     
                     var content={beventname:"${event[0]}"};
-                    var event = inv.args[0];
-                    tapestry.event.buildEventProperties( event, content);                    
+                   
+                    tapestry.event.buildEventProperties( event, content, arguments);                    
                     if (!content["beventtarget.id"]) {
                     	content["beventtarget.id"]="${clientId}";
-                    }
-                    
-                    if (! dojo.event.browser.isEvent(event)){
-                    	tapestry.event.buildMethodInterceptionProperties( inv.args, content );
-                    }
+                    }                                 
                     
                     tapestry.bind("${url}", content);
-
-                    return result;
                 };
-                dojo.event.connect("around", dojo.byId("${clientId}"), "${event[0]}", tapestry, "event${event[1]}");
+                dojo.event.connect(dojo.byId("${clientId}"), "${event[0]}", tapestry, "event${event[1]}");
             </foreach>
         </if>
         <if expression="formEvents">
@@ -44,7 +37,7 @@
                                      "${formEvent[0]}", "formEvent${formEvent[4]}");
                 tapestry.formEvent${formEvent[4]}=function(e){
                     var content={beventname:"${formEvent[0]}"};
-                    tapestry.event.buildEventProperties(e, content);
+                    tapestry.event.buildEventProperties(e, content, arguments);
                     if (!content["beventtarget.id"]){
                     	content["beventtarget.id"]="${clientId}";
                     }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script?view=diff&rev=553306&r1=553305&r2=553306
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/dojo/html/WidgetEvent.script Wed Jul  4 12:27:47 2007
@@ -19,7 +19,7 @@
                 tapestry.cleanConnect(dojo.widget.byId("${clientId}"), "${event[0]}", "event${event[1]}");
                 tapestry.event${event[1]}=function(e){
                     var content={beventname:"${event[0]}"};
-                    tapestry.event.buildEventProperties(e, content);
+                    tapestry.event.buildEventProperties(e, content, arguments);
                     if (!content["beventtarget.id"]) content["beventtarget.id"]="${clientId}";
                     tapestry.bind("${url}", content);
                 };
@@ -32,7 +32,7 @@
                                      "${formEvent[0]}", "formEvent${formEvent[4]}");
                 tapestry.formEvent${formEvent[4]}=function(e){
                     var content={beventname:"${formEvent[0]}"};
-                    tapestry.event.buildEventProperties(e, content);
+                    tapestry.event.buildEventProperties(e, content, arguments);
                     if (!content["beventtarget.id"]) content["beventtarget.id"]="${clientId}";
 
                   <foreach expression="formEvent[1]" key="formName">

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/event/BrowserEvent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/event/BrowserEvent.java?view=diff&rev=553306&r1=553305&r2=553306
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/event/BrowserEvent.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/event/BrowserEvent.java Wed Jul  4 12:27:47 2007
@@ -13,13 +13,16 @@
 // limitations under the License.
 package org.apache.tapestry.event;
 
+import java.text.ParseException;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.commons.lang.builder.ToStringStyle;
+import org.apache.hivemind.ApplicationRuntimeException;
 import org.apache.hivemind.util.Defense;
 import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.json.JSONArray;
 
 
 /**
@@ -41,6 +44,8 @@
     public static final String TARGET="beventtarget";
     public static final String TARGET_ATTR_ID="id";
     
+    public static final String METHOD_ARGUMENTS="methodArguments";
+    
     private String _name;
     private String _type;
     private String[] _keys;
@@ -51,6 +56,9 @@
     private String _layerY;
     private EventTarget _target;
     
+    private String _methodArguments;
+    private JSONArray _methodArgumentsArray;
+    
     /**
      * Creates a new browser event that will extract its own
      * parameters.
@@ -78,6 +86,8 @@
         if (targetId != null) {
             props.put(TARGET_ATTR_ID, targetId);
         }
+        
+        _methodArguments = cycle.getParameter(METHOD_ARGUMENTS);
     }
     
     /**
@@ -171,6 +181,33 @@
     {
         return _type;
     }
+    
+    
+    /**
+     * @return the method arguments of an intercepted method-call, if any. If none
+     *         are available, return an empty JSONArray, never null.
+     *         
+     * @throws ApplicationRuntimeException when the JSON-String could not be
+     *         parsed.
+     */
+    public JSONArray getMethodArguments() 
+    {   
+        if ( _methodArgumentsArray == null)
+        {
+            try 
+            {
+                _methodArgumentsArray =
+                        _methodArguments != null ?
+                                new JSONArray( _methodArguments )
+                              : new JSONArray();
+            } 
+            catch (ParseException ex) 
+            {
+                throw new ApplicationRuntimeException(ex);
+            }
+        }
+        return _methodArgumentsArray;
+    }
 
     /**
      * Utility method to check if the current request contains
@@ -198,6 +235,7 @@
         .append("layerX", _layerX)
         .append("layerY", _layerY)
         .append("target", _target)
+        .append("methodArguments", _methodArguments)
         .toString();
     }
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/html/ElementEvent.script
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/html/ElementEvent.script?view=diff&rev=553306&r1=553305&r2=553306
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/html/ElementEvent.script (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/html/ElementEvent.script Wed Jul  4 12:27:47 2007
@@ -18,7 +18,7 @@
                 tapestry.cleanConnect(dojo.byId("${target}"), "${event[0]}", "event${event[1]}");
                 tapestry.event${event[1]}=function(e){
                     var content={beventname:"${event[0]}"};
-                    tapestry.event.buildEventProperties(e, content);
+                    tapestry.event.buildEventProperties(e, content, arguments);
                     if (!content["beventtarget.id"]) content["beventtarget.id"]="${target}";
                     tapestry.bind("${url}", content);
                 };
@@ -31,7 +31,7 @@
                                      "${formEvent[0]}", "formEvent${formEvent[4]}");
                 tapestry.formEvent${formEvent[4]}=function(e){
                     var content={beventname:"${formEvent[0]}"};
-                    tapestry.event.buildEventProperties(e, content);
+                    tapestry.event.buildEventProperties(e, content, arguments);
                     if (!content["beventtarget.id"]) content["beventtarget.id"]="${target}";
                     
                     <foreach expression="formEvent[1]" key="formName">

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js?view=diff&rev=553306&r1=553305&r2=553306
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/tapestry/core.js Wed Jul  4 12:27:47 2007
@@ -7,7 +7,8 @@
 dojo.require("dojo.io.BrowserIO");
 dojo.require("dojo.event.browser");
 dojo.require("dojo.html.style");
-dojo.require("dojo.json");
+
+
 
 // redirect logging calls to standard debug if logging not enabled
 if (dj_undef("logging", dojo)) {
@@ -532,7 +533,7 @@
 	},
 
 	_getContentAsStringIE:function(node){
-		var s="";
+		var s=" "; //blank works around an IE-bug
     	for (var i = 0; i < node.childNodes.length; i++){
         	s += node.childNodes[i].xml;
     	}
@@ -600,59 +601,34 @@
 	 * 				browser event it will be ignored.
 	 *	props - The existing property object to set the values on, if it doesn't
 	 * 				exist one will be created.
+	 *  args  - The arguments from an method-call interception 
 	 * Returns:
 	 *
 	 * The desired event properties bound to an object. Ie obj.target,obj.charCode, etc..
 	 */
-	buildEventProperties:function(event, props){
+	buildEventProperties:function(event, props, args){
 		if (!props) props={};
-		if (!dojo.event.browser.isEvent(event)) return props;
-
-		if(event["type"]) props.beventtype=event.type;
-		if(event["keys"]) props.beventkeys=event.keys;
-		if(event["charCode"]) props.beventcharCode=event.charCode;
-		if(event["pageX"]) props.beventpageX=event.pageX;
-		if(event["pageY"]) props.beventpageY=event.pageY;
-		if(event["layerX"]) props.beventlayerX=event.layerX;
-		if(event["layerY"]) props.beventlayerY=event.layerY;
-
-		if (event["target"]) this.buildTargetProperties(props, event.target);
+		if (dojo.event.browser.isEvent(event)) {
 
+			if(event["type"]) props.beventtype=event.type;
+			if(event["keys"]) props.beventkeys=event.keys;
+			if(event["charCode"]) props.beventcharCode=event.charCode;
+			if(event["pageX"]) props.beventpageX=event.pageX;
+			if(event["pageY"]) props.beventpageY=event.pageY;
+			if(event["layerX"]) props.beventlayerX=event.layerX;
+			if(event["layerY"]) props.beventlayerY=event.layerY;
+
+			if (event["target"]) this.buildTargetProperties(props, event.target);
+
+		} else if ( args != undefined ) {
+		
+			props.methodArguments = dojo.json.serialize( args );
+			
+		}
 		return props;
 	},
 	
 	
-	/**
-	 * Function: buildMethodInterceptionProperties
-	 *
-	 * Stuffs the parameters of an @EventListener-intercepted method into
-	 * a property object suitable to be passed as the content-argument to 
-	 * the bind-function. Arguments will be passed as service-parameters (sp)
-	 * so that the usual listener-invocation mechanism can do its work. 
-	 * String parameters are encoded as such (StringAdaptor, prefix "S")
-	 * Other types/objects will be serialised to a JSON-String which is
-	 * to be handled by the JSONAdaptor on the server side (prefix "J").  
-	 *
-	 * Parameters:
-	 *
-	 *	args - the arguments array.
-	 *	props - The existing property object to set the values on, if it doesn't
-	 * 				exist one will be created.
-	 * Returns:
-	 *
-	 * The passed in properties object augmented in the way described above
-	 */
-	buildMethodInterceptionProperties:function( args, props ){
-	    if (!props) props={};
-	    props.sp = new Array();
-		for ( var i=0; i < args.length; i++ ) {
-			if ( typeof(args[i]) == "string" )
-				props.sp[i] = "S"+String(args[i]);
-			else
-				props.sp[i] = "J"+dojo.json.serialize( args[i] );	
-		}
-		return props;
-	},
 
 	/**
 	 * Function: buildTargetProperties
@@ -737,4 +713,134 @@
 		}
 		return true;
 	}
-}
\ No newline at end of file
+}
+
+/*
+  ** dojo json support just dumped in here until we build dojo anew for T4 **
+
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+
+
+dojo.require("dojo.lang.func");
+dojo.require("dojo.string.extras");
+
+dojo.AdapterRegistry = function (returnWrappers) {
+	this.pairs = [];
+	this.returnWrappers = returnWrappers || false;
+};
+dojo.lang.extend(dojo.AdapterRegistry, {register:function (name, check, wrap, directReturn, override) {
+	var type = (override) ? "unshift" : "push";
+	this.pairs[type]([name, check, wrap, directReturn]);
+}, match:function () {
+	for (var i = 0; i < this.pairs.length; i++) {
+		var pair = this.pairs[i];
+		if (pair[1].apply(this, arguments)) {
+			if ((pair[3]) || (this.returnWrappers)) {
+				return pair[2];
+			} else {
+				return pair[2].apply(this, arguments);
+			}
+		}
+	}
+	throw new Error("No match found");
+}, unregister:function (name) {
+	for (var i = 0; i < this.pairs.length; i++) {
+		var pair = this.pairs[i];
+		if (pair[0] == name) {
+			this.pairs.splice(i, 1);
+			return true;
+		}
+	}
+	return false;
+}});
+
+
+dojo.json = {jsonRegistry:new dojo.AdapterRegistry(), register:function (name, check, wrap, override) {
+	dojo.json.jsonRegistry.register(name, check, wrap, override);
+}, evalJson:function (json) {
+	try {
+		return eval("(" + json + ")");
+	}
+	catch (e) {
+		dojo.debug(e);
+		return json;
+	}
+}, serialize:function (o) {
+	var objtype = typeof (o);
+	if (objtype == "undefined") {
+		return "undefined";
+	} else {
+		if ((objtype == "number") || (objtype == "boolean")) {
+			return o + "";
+		} else {
+			if (o === null) {
+				return "null";
+			}
+		}
+	}
+	if (objtype == "string") {
+		return dojo.string.escapeString(o);
+	}
+	var me = arguments.callee;
+	var newObj;
+	if (typeof (o.__json__) == "function") {
+		newObj = o.__json__();
+		if (o !== newObj) {
+			return me(newObj);
+		}
+	}
+	if (typeof (o.json) == "function") {
+		newObj = o.json();
+		if (o !== newObj) {
+			return me(newObj);
+		}
+	}
+	if (objtype != "function" && typeof (o.length) == "number") {
+		var res = [];
+		for (var i = 0; i < o.length; i++) {
+			var val = me(o[i]);
+			if (typeof (val) != "string") {
+				val = "undefined";
+			}
+			res.push(val);
+		}
+		return "[" + res.join(",") + "]";
+	}
+	try {
+		window.o = o;
+		newObj = dojo.json.jsonRegistry.match(o);
+		return me(newObj);
+	}
+	catch (e) {
+	}
+	if (objtype == "function") {
+		return null;
+	}
+	res = [];
+	for (var k in o) {
+		var useKey;
+		if (typeof (k) == "number") {
+			useKey = "\"" + k + "\"";
+		} else {
+			if (typeof (k) == "string") {
+				useKey = dojo.string.escapeString(k);
+			} else {
+				continue;
+			}
+		}
+		val = me(o[k]);
+		if (typeof (val) != "string") {
+			continue;
+		}
+		res.push(useKey + ":" + val);
+	}
+	return "{" + res.join(",") + "}";
+}};
\ No newline at end of file

Added: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/event/BrowserEventTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/event/BrowserEventTest.java?view=auto&rev=553306
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/event/BrowserEventTest.java (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/event/BrowserEventTest.java Wed Jul  4 12:27:47 2007
@@ -0,0 +1,93 @@
+// Copyright 2004, 2005 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.tapestry.event;
+
+import static org.easymock.EasyMock.expect;
+
+import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.tapestry.BaseComponentTestCase;
+import org.apache.tapestry.IRequestCycle;
+import org.testng.annotations.Test;
+
+/**
+ * Tests how BrowserEvent extracts itself from the RequestCycle
+ * 
+ */
+@Test
+public class BrowserEventTest extends BaseComponentTestCase
+{
+    public void testConstructAndReadMethodArguments() {
+        IRequestCycle cycle = newCycle();
+        
+        trainCycleForStandardBrowserEvent(cycle);
+
+        expect(cycle.getParameter(BrowserEvent.METHOD_ARGUMENTS))
+                .andReturn("[1,2]");
+        
+        replay();
+        
+        BrowserEvent event = new BrowserEvent(cycle);
+        
+        verify();
+        
+        assertEquals(1, event.getMethodArguments().getInt(0));
+        assertEquals(2, event.getMethodArguments().getInt(1));
+    }
+    
+    
+    
+    public void testUnparseableJSON() {
+        
+        IRequestCycle cycle = newCycle();
+        
+        trainCycleForStandardBrowserEvent(cycle);
+        
+        expect(cycle.getParameter(BrowserEvent.METHOD_ARGUMENTS))
+                .andReturn("*/utterRubbŸsh");
+        replay();
+        
+        BrowserEvent event = new BrowserEvent(cycle);
+        
+        verify();
+        
+        try {
+            event.getMethodArguments();
+            unreachable();
+        } catch( ApplicationRuntimeException e) {
+            //success.
+        }
+    }
+
+    /**
+     * @param cycle
+     */
+    private void trainCycleForStandardBrowserEvent(IRequestCycle cycle)
+    {
+        expect(cycle.getParameter(BrowserEvent.NAME)).andReturn("onClick").anyTimes();
+        
+        expect(cycle.getParameter(BrowserEvent.TYPE)).andReturn("click");
+        expect(cycle.getParameters(BrowserEvent.KEYS)).andReturn(null);
+        expect(cycle.getParameter(BrowserEvent.CHAR_CODE)).andReturn(null);
+        expect(cycle.getParameter(BrowserEvent.PAGE_X)).andReturn("123");
+        expect(cycle.getParameter(BrowserEvent.PAGE_Y)).andReturn("1243");
+        expect(cycle.getParameter(BrowserEvent.LAYER_X)).andReturn(null);
+        expect(cycle.getParameter(BrowserEvent.LAYER_Y)).andReturn(null);
+        
+        expect(cycle.getParameter(BrowserEvent.TARGET + "." + BrowserEvent.TARGET_ATTR_ID))
+        .andReturn("element1");
+    }
+    
+    
+
+}