Author: mrdon Date: Tue Feb 15 23:08:47 2005 New Revision: 154003 URL: http://svn.apache.org/viewcvs?view=rev&rev=154003 Log: Adding new Rhino extensions that better integrate collections into rhino and a test of adding Groovy-like JVM extensions that utilize closures
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableList.java (with props) struts/flow/trunk/src/java/org/apache/struts/flow/core/SugarWrapFactory.java (with props) Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableMap.java Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableList.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableList.java?view=auto&rev=154003 ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableList.java (added) +++ struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableList.java Tue Feb 15 23:08:47 2005 @@ -0,0 +1,112 @@ +/* + * Copyright 1999-2004 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.struts.flow.core; + +import org.mozilla.javascript.*; + +import java.util.*; +import java.io.Serializable; + +/** + * Wrap a java.util.List for JavaScript. + */ +public class ScriptableList extends NativeJavaObject implements Scriptable, Wrapper, Serializable { + + private List list; + + public ScriptableList() { + this.list = list; + } + + public ScriptableList(List list) { + this.list = list; + this.javaObject = javaObject; + } + + public ScriptableList(Scriptable scope, Object javaObject, Class staticType) { + super(scope, javaObject, staticType); + if (javaObject instanceof List) { + this.list = (List)javaObject; + } else { + throw new IllegalArgumentException("Passed object "+javaObject+" is not an instance of List"); + } + } + + public String getClassName() { + return staticType.toString(); + } + + public boolean has(int index, Scriptable start) { + return (list.get(index) != null); + } + + public Object get(int index, Scriptable start) { + return list.get(index); + } + + public Object get(String name, Scriptable start) { + if ("each".equals(name)) { + return new EachClosure(); + } else { + return super.get(name, start); + } + } + + public void put(int index, Scriptable start, Object value) { + list.add(index, value); + } + + public void delete(int index) { + list.remove(index); + } + + public Object[] getIds() { + + //TODO: optimize this :) + Integer[] ids = new Integer[list.size()]; + for (int x=0; x<ids.length; x++) { + ids[x] = new Integer(x); + } + return ids; + } + + public Object unwrap() { + return this.list; + } + + class EachClosure extends ScriptableObject implements Function { + + public Object call(Context cx, Scriptable scope, Scriptable thisObj, java.lang.Object[] args) { + Function func = (Function)args[0]; + Object[] param = new Object[1]; + + for (Iterator i = list.iterator(); i.hasNext(); ) { + param[0] = i.next(); + func.call(cx, scope, thisObj, param); + } + return null; + } + + public Scriptable construct(Context cx, Scriptable scope, java.lang.Object[] args) { + return null; + } + + public String getClassName() { + return "EachClosure"; + } + } + +} Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableList.java ------------------------------------------------------------------------------ svn:executable = * Modified: struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableMap.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableMap.java?view=diff&r1=154002&r2=154003 ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableMap.java (original) +++ struts/flow/trunk/src/java/org/apache/struts/flow/core/ScriptableMap.java Tue Feb 15 23:08:47 2005 @@ -1,17 +1,17 @@ /* - * Copyright 1999-2004 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. + * Copyright 1999-2004 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.struts.flow.core; @@ -20,248 +20,122 @@ import org.mozilla.javascript.Wrapper; import java.util.Map; -import java.util.Iterator; +import java.io.Serializable; /** - * Wrap a java.util.Map for JavaScript. Borrowed from Cocoon. - * - [EMAIL PROTECTED] CVS $Id: ScriptableMap.java,v 1.1.1.1 2004/05/12 00:03:45 mrdon - * Exp $ + * Wrap a java.util.Map for JavaScript. */ -public class ScriptableMap implements Scriptable, Wrapper { +public class ScriptableMap extends NativeJavaObject implements Scriptable, Wrapper, Serializable { private Map map; - private Scriptable prototype, parent; - - - /** Constructor for the ScriptableMap object */ - public ScriptableMap() { } + private String functionPrefix = null; + public ScriptableMap() { + super(); + } - /** - * Constructor for the ScriptableMap object - * - [EMAIL PROTECTED] map The map to wrap - */ public ScriptableMap(Map map) { - this(map, false); + this.map = map; } - /** - * Constructor for the ScriptableMap object - * - [EMAIL PROTECTED] map The map to wrap - [EMAIL PROTECTED] deep Whether to recursively wrap contained Maps - */ - public ScriptableMap(Map map, boolean deep) { - this.map = map; - if (deep) { - Map.Entry entry; - for (Iterator i = map.entrySet().iterator(); i.hasNext(); ) { - entry = (Map.Entry)i.next(); - if (entry.getValue() instanceof Map) { - entry.setValue(new ScriptableMap((Map)entry.getValue(), deep)); - } - } + public ScriptableMap(Scriptable scope, Object javaObject, Class staticType, String functionPrefix) { + super(scope, javaObject, staticType); + this.functionPrefix = functionPrefix; + if (javaObject instanceof Map) { + this.map = (Map)javaObject; + } else { + throw new IllegalArgumentException("Passed object "+javaObject+" is not an instance of Map"); } } - - /** - * Gets the class name - * - [EMAIL PROTECTED] The className value - */ public String getClassName() { return "Map"; } - - /** - * Whether the Map contains the key - * - [EMAIL PROTECTED] name The key - [EMAIL PROTECTED] start - [EMAIL PROTECTED] True if found - */ public boolean has(String name, Scriptable start) { - return this.map.containsKey(name); + return (this.map.containsKey(name) || super.has(name, start)); } - /** - * N/A, no numeric properties - * - [EMAIL PROTECTED] index - [EMAIL PROTECTED] start - [EMAIL PROTECTED] Always false + * no numeric properties */ public boolean has(int index, Scriptable start) { return false; } - - /** - * Gets the value from the map - * - [EMAIL PROTECTED] name The key - [EMAIL PROTECTED] start N/A - [EMAIL PROTECTED] The value or <code>NOT_FOUND</code> - */ public Object get(String name, Scriptable start) { - if (this.map.containsKey(name)) { - return this.map.get(name); + if (functionPrefix != null && name.startsWith(functionPrefix)) { + return super.get(name.substring(functionPrefix.length()), start); + } else { + if (this.map.containsKey(name)) { + return this.map.get(name); + } else { + return super.get(name, start); + } } - - return NOT_FOUND; } - - /** - * N/A - * - [EMAIL PROTECTED] index - [EMAIL PROTECTED] start - [EMAIL PROTECTED] Always <code>NOT_FOUND</code> - */ public Object get(int index, Scriptable start) { return NOT_FOUND; } - - /** - * Puts the value in the map - * - [EMAIL PROTECTED] name The key - [EMAIL PROTECTED] start - [EMAIL PROTECTED] value The value - */ public void put(String name, Scriptable start, Object value) { if (value instanceof NativeJavaObject) { - value = ((NativeJavaObject) value).unwrap(); + value = ((NativeJavaObject)value).unwrap(); } map.put(name, value); } - - /** - * N/A - * - [EMAIL PROTECTED] index - [EMAIL PROTECTED] start - [EMAIL PROTECTED] value - */ public void put(int index, Scriptable start, Object value) { } - - /** - * Removes the key from the map - * - [EMAIL PROTECTED] id The key - */ public void delete(String id) { map.remove(id); } - - /** - * N/A - * - [EMAIL PROTECTED] index - */ public void delete(int index) { } - - /** - * Gets the prototype - * - [EMAIL PROTECTED] The prototype value - */ public Scriptable getPrototype() { return prototype; } - - /** - * Sets the prototype - * - [EMAIL PROTECTED] prototype The new prototype value - */ public void setPrototype(Scriptable prototype) { this.prototype = prototype; } - - /** - * Gets the parentScope - * - [EMAIL PROTECTED] The parentScope value - */ public Scriptable getParentScope() { return parent; } - - /** - * Sets the parentScope - * - [EMAIL PROTECTED] parent The new parentScope value - */ public void setParentScope(Scriptable parent) { this.parent = parent; } - - /** - * Gets the keys - * - [EMAIL PROTECTED] The ids value - */ public Object[] getIds() { return this.map.keySet().toArray(); } - - /** - * Gets the default value - * - [EMAIL PROTECTED] typeHint - [EMAIL PROTECTED] The defaultValue value - */ public Object getDefaultValue(Class typeHint) { return this.map.toString(); } - - /** - * Whether the prototype has an instance - * - [EMAIL PROTECTED] value The instance - [EMAIL PROTECTED] True if found - */ public boolean hasInstance(Scriptable value) { Scriptable proto = value.getPrototype(); while (proto != null) { - if (proto.equals(this)) { + if (proto.equals(this)) return true; - } proto = proto.getPrototype(); } return false; } - /** - * Returns the actual Map - * - [EMAIL PROTECTED] The Map + * Return the java.util.Map that is wrapped by this class. */ public Object unwrap() { return this.map; } } - Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/SugarWrapFactory.java URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/SugarWrapFactory.java?view=auto&rev=154003 ============================================================================== --- struts/flow/trunk/src/java/org/apache/struts/flow/core/SugarWrapFactory.java (added) +++ struts/flow/trunk/src/java/org/apache/struts/flow/core/SugarWrapFactory.java Tue Feb 15 23:08:47 2005 @@ -0,0 +1,93 @@ +/* + * Copyright 1999-2004 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.struts.flow.core; + +import org.mozilla.javascript.*; +import java.io.*; +import java.util.*; + +/** + * Wrap a java.util.Collection for JavaScript. + */ +public class SugarWrapFactory extends WrapFactory { + + private String mapFuncPrefix = "fn_"; + + public void setMapFunctionPrefix(String prefix) { + this.mapFuncPrefix = prefix; + } + + /** + * Wrap Java object as Scriptable instance to allow full access to its + * methods and fields from JavaScript. + * <p> + * [EMAIL PROTECTED] #wrap(Context, Scriptable, Object, Class)} and + * [EMAIL PROTECTED] #wrapNewObject(Context, Scriptable, Object)} call this method + * when they can not convert <tt>javaObject</tt> to JavaScript primitive + * value or JavaScript array. + * @param cx the current Context for this thread + * @param scope the scope of the executing script + * @param javaObject the object to be wrapped + * @param staticType type hint. If security restrictions prevent to wrap + object based on its class, staticType will be used instead. + * @return the wrapped value which shall not be null + */ + public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, + Object javaObject, Class staticType) { + + Scriptable wrap = null; + if (javaObject instanceof Map) { + wrap = new ScriptableMap(scope, javaObject, staticType, mapFuncPrefix); + } else if (javaObject instanceof List) { + wrap = new ScriptableList(scope, javaObject, staticType); + } else { + wrap = super.wrapAsJavaObject(cx, scope, javaObject, staticType); + } + return wrap; + } + + // temporary method for testing + public static final void main(String[] args) throws Exception { + // Creates and enters a Context. The Context stores information + // about the execution environment of a script. + Context cx = Context.enter(); + try { + cx.setWrapFactory(new SugarWrapFactory()); + // Initialize the standard objects (Object, Function, etc.) + // This must be done before scripts can be executed. Returns + // a scope object that we use in later calls. + Scriptable scope = cx.initStandardObjects(); + + // Collect the arguments into a single string. + String s = ""; + for (int i=0; i < args.length; i++) { + s += args[i]; + } + + // Now evaluate the string we've colected. + FileReader reader = new FileReader(args[0]); + Object result = cx.evaluateReader(scope, reader, args[0], 1, null); + + // Convert the result to a string and print it. + System.err.println(cx.toString(result)); + + } finally { + // Exit from the context. + Context.exit(); + } + } + +} Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/SugarWrapFactory.java ------------------------------------------------------------------------------ svn:executable = * --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]