Return-Path: Delivered-To: apmail-cocoon-cvs-archive@www.apache.org Received: (qmail 38192 invoked from network); 3 Nov 2005 14:57:02 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 3 Nov 2005 14:57:02 -0000 Received: (qmail 28718 invoked by uid 500); 3 Nov 2005 14:37:46 -0000 Delivered-To: apmail-cocoon-cvs-archive@cocoon.apache.org Received: (qmail 26867 invoked by uid 500); 3 Nov 2005 14:36:22 -0000 Mailing-List: contact cvs-help@cocoon.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@cocoon.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@cocoon.apache.org Received: (qmail 26096 invoked by uid 99); 3 Nov 2005 14:35:10 -0000 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Thu, 03 Nov 2005 06:34:27 -0800 Received: (qmail 11613 invoked by uid 65534); 3 Nov 2005 14:34:04 -0000 Message-ID: <20051103143404.11605.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r330548 [16/132] - in /cocoon/whiteboard/maven2/cocoon-flat-layout: ./ cocoon-ajax-block/ cocoon-ajax-block/api/ cocoon-ajax-block/api/src/ cocoon-ajax-block/api/src/main/ cocoon-ajax-block/api/src/main/java/ cocoon-ajax-block/api/src/main/... Date: Thu, 03 Nov 2005 14:00:48 -0000 To: cvs@cocoon.apache.org From: jheymans@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_Cocoon.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptFlowHelper.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptFlowHelper.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptFlowHelper.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptFlowHelper.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,160 @@ +/* + * 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.cocoon.components.flow.javascript.fom; + +import org.apache.cocoon.components.flow.FlowHelper; + +import org.mozilla.javascript.Scriptable; + +import java.util.Map; + +/** + * Provides the interface between the JavaScript flow controller layer and the + * view layer. A view can obtain the JavaScript "live connect" objects (that + * allow access to Java constructors) through this interface, as well as + * the FOM objects. + * + * @version CVS $Id: FOM_JavaScriptFlowHelper.java 36239 2004-08-11 18:28:06Z vgritsenko $ + */ +public class FOM_JavaScriptFlowHelper extends FlowHelper { + + // Constants defining keys in the object model used to store the various objects. + // These constants are private so that access to these objects only go through the + // accessors provided below. + // + // These objects are stored in the object model rather than as request attributes, + // as object model is cloned for subrequests (see EnvironmentWrapper), whereas + // request attributes are shared between the "real" request and all of its + // child requests. + private static final String PACKAGES_OBJECT = + "cocoon.flow.js.packages"; + private static final String JAVA_PACKAGE_OBJECT = + "cocoon.flow.js.packages.java"; + private static final String FOM_REQUEST = + "cocoon.flow.js.fom.FOM_Request"; + private static final String FOM_RESPONSE = + "cocoon.flow.js.fom.FOM_Response"; + private static final String FOM_SESSION = + "cocoon.flow.js.fom.FOM_Session"; + private static final String FOM_CONTEXT = + "cocoon.flow.js.fom.FOM_Context"; + private static final String FOM_WEB_CONTINUATION = + "cocoon.flow.js.fom.FOM_WebContinuation"; + /** + * The parent scope to be used by nested scripts (e.g. Woody event handlers) + */ + private static final String FOM_SCOPE = + "cocoon.flow.js.fom.FOM_Scope"; + + /** + * Return the JS "Packages" property (that gives access to Java + * packages) for use by the view layer + * @param objectModel The Cocoon Environment's object model + * @return The Packages property + */ + public static Scriptable getPackages(Map objectModel) { + return (Scriptable)objectModel.get(PACKAGES_OBJECT); + } + + /** + * Set the JS "Packages" property in the current request + * @param objectModel The Cocoon Environment's object model + */ + public static void setPackages(Map objectModel, Scriptable pkgs) { + objectModel.put(PACKAGES_OBJECT, pkgs); + } + + /** + * Return the JS "java" property (that gives access to the "java" + * package) for use by the view layer + * @param objectModel The Cocoon Environment's object model + * @return The java package property + */ + public static Scriptable getJavaPackage(Map objectModel) { + return (Scriptable)objectModel.get(JAVA_PACKAGE_OBJECT); + } + + /** + * Set the JS "java" property in the current request + * @param objectModel The Cocoon Environment's object model + */ + public static void setJavaPackage(Map objectModel, Scriptable javaPkg) { + objectModel.put(JAVA_PACKAGE_OBJECT, javaPkg); + } + + public static Scriptable getFOM_Request(Map objectModel) { + return (Scriptable)objectModel.get(FOM_REQUEST); + } + + public static void setFOM_Request(Map objectModel, Scriptable fom_request) { + objectModel.put(FOM_REQUEST, fom_request); + } + + public static Scriptable getFOM_Response(Map objectModel) { + return (Scriptable)objectModel.get(FOM_RESPONSE); + } + + public static void setFOM_Response(Map objectModel, Scriptable fom_response) { + objectModel.put(FOM_RESPONSE, fom_response); + } + + public static Scriptable getFOM_Session(Map objectModel) { + return (Scriptable)objectModel.get(FOM_SESSION); + } + + public static void setFOM_Session(Map objectModel, Scriptable fom_session) { + objectModel.put(FOM_SESSION, fom_session); + } + + public static Scriptable getFOM_Context(Map objectModel) { + return (Scriptable)objectModel.get(FOM_CONTEXT); + } + + public static void setFOM_Context(Map objectModel, Scriptable fom_context) { + objectModel.put(FOM_CONTEXT, fom_context); + } + + public static Scriptable getFOM_WebContinuation(Map objectModel) { + return (Scriptable)objectModel.get(FOM_WEB_CONTINUATION); + } + + public static void setFOM_WebContinuation(Map objectModel, + Scriptable fom_webContinuation) { + objectModel.put(FOM_WEB_CONTINUATION, fom_webContinuation); + } + + /** + * Get the flowscript scope, usable by JS snippets part of the control layer, such + * as forms event listeners. + * + * @param objectModel the object model where the scope is stored + * @return the flowscript scope + */ + public static Scriptable getFOM_FlowScope(Map objectModel) { + return (Scriptable)objectModel.get(FOM_SCOPE); + } + + /** + * Set the flowscript scope usable by JS snippets. + * + * @see #getFOM_FlowScope(Map) + * @param objectModel + * @param fom_scope + */ + public static void setFOM_FlowScope(Map objectModel, Scriptable fom_scope) { + objectModel.put(FOM_SCOPE, fom_scope); + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptFlowHelper.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptInterpreter.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptInterpreter.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptInterpreter.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptInterpreter.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,756 @@ +/* + * 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.cocoon.components.flow.javascript.fom; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PushbackInputStream; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.avalon.framework.activity.Initializable; +import org.apache.avalon.framework.configuration.Configurable; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.cocoon.ResourceNotFoundException; +import org.apache.cocoon.components.ContextHelper; +import org.apache.cocoon.components.flow.CompilingInterpreter; +import org.apache.cocoon.components.flow.Interpreter; +import org.apache.cocoon.components.flow.InvalidContinuationException; +import org.apache.cocoon.components.flow.WebContinuation; +import org.apache.cocoon.components.flow.javascript.JSErrorReporter; +import org.apache.cocoon.components.flow.javascript.LocationTrackingDebugger; +import org.apache.cocoon.components.flow.javascript.ScriptablePointerFactory; +import org.apache.cocoon.components.flow.javascript.ScriptablePropertyHandler; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.Request; +import org.apache.cocoon.environment.Session; +import org.apache.commons.jxpath.JXPathIntrospector; +import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl; +import org.apache.excalibur.source.Source; +import org.apache.regexp.RE; +import org.apache.regexp.RECompiler; +import org.apache.regexp.REProgram; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.EcmaError; +import org.mozilla.javascript.Function; +import org.mozilla.javascript.JavaScriptException; +import org.mozilla.javascript.NativeJavaClass; +import org.mozilla.javascript.NativeJavaPackage; +import org.mozilla.javascript.PropertyException; +import org.mozilla.javascript.Script; +import org.mozilla.javascript.ScriptRuntime; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; +import org.mozilla.javascript.WrappedException; +import org.mozilla.javascript.Wrapper; +import org.mozilla.javascript.continuations.Continuation; +import org.mozilla.javascript.tools.debugger.Main; +import org.mozilla.javascript.tools.shell.Global; + + +/** + * Interface with the JavaScript interpreter. + * + * @author Ovidiu Predescu + * @author Marcus Crafter + * @since March 25, 2002 + * @version CVS $Id: FOM_JavaScriptInterpreter.java 307410 2005-10-09 12:17:33Z reinhard $ + */ +public class FOM_JavaScriptInterpreter extends CompilingInterpreter + implements Configurable, Initializable { + + /** + * A long value is stored under this key in each top level JavaScript + * thread scope object. When you enter a context any scripts whose + * modification time is later than this value will be recompiled and reexecuted, + * and this value will be updated to the current time. + */ + private final static String LAST_EXEC_TIME = "__PRIVATE_LAST_EXEC_TIME__"; + + /** + * Prefix for session/request attribute storing JavaScript global scope object. + */ + private static final String USER_GLOBAL_SCOPE = "FOM JavaScript GLOBAL SCOPE/"; + + /** + * This is the only optimization level that supports continuations + * in the Christoper Oliver's Rhino JavaScript implementation + */ + private static final int OPTIMIZATION_LEVEL = -2; + + /** + * When was the last time we checked for script modifications. Used + * only if {@link #reloadScripts} is true. + */ + private long lastTimeCheck; + + /** + * Shared global scope for scripts and other immutable objects + */ + private Global scope; + + /** + * List of String objects that represent files to be + * read in by the JavaScript interpreter. + */ + private List topLevelScripts = new ArrayList(); + + private boolean enableDebugger; + + /** + * Needed to get things working with JDK 1.3. Can be removed once we + * don't support that platform any more. + */ + protected ServiceManager getServiceManager() { + return manager; + } + + /** + * JavaScript debugger: there's only one of these: it can debug multiple + * threads executing JS code. + */ + private static Main debugger; + + static synchronized Main getDebugger() { + if (debugger == null) { + final Main db = new Main("Cocoon Flow Debugger"); + db.pack(); + Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); + size.width *= 0.75; + size.height *= 0.75; + db.setSize(size); + db.setExitAction(new Runnable() { + public void run() { + db.setVisible(false); + } + }); + db.setOptimizationLevel(OPTIMIZATION_LEVEL); + db.setVisible(true); + debugger = db; + Context.addContextListener(debugger); + } + return debugger; + } + + public void configure(Configuration config) throws ConfigurationException { + super.configure(config); + + String loadOnStartup = config.getChild("load-on-startup").getValue(null); + if (loadOnStartup != null) { + register(loadOnStartup); + } + + String debugger = config.getChild("debugger").getValue(null); + enableDebugger = "enabled".equalsIgnoreCase(debugger); + } + + public void initialize() throws Exception { + if (enableDebugger) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Flow debugger enabled, creating"); + } + getDebugger().doBreak(); + } + Context context = Context.enter(); + context.setOptimizationLevel(OPTIMIZATION_LEVEL); + context.setCompileFunctionsWithDynamicScope(true); + context.setGeneratingDebug(true); + // add support for Rhino objects to JXPath + JXPathIntrospector.registerDynamicClass(Scriptable.class, + ScriptablePropertyHandler.class); + JXPathContextReferenceImpl.addNodePointerFactory(new ScriptablePointerFactory()); + + try { + scope = new Global(context); + // Access to Cocoon internal objects + FOM_Cocoon.init(scope); + } catch (Exception e) { + Context.exit(); + e.printStackTrace(); + throw e; + } + } + + + /** + * Returns the JavaScript scope, a Scriptable object, from the user + * session instance. Each interpreter instance can have a scope + * associated with it. + * + * @return a ThreadScope value + */ + private ThreadScope getSessionScope() throws Exception { + final String scopeID = USER_GLOBAL_SCOPE + getInterpreterID(); + final Request request = ContextHelper.getRequest(this.avalonContext); + + ThreadScope scope = null; + + // Get/create the scope attached to the current context + Session session = request.getSession(false); + if (session != null) { + scope = (ThreadScope) session.getAttribute(scopeID); + } else { + scope = (ThreadScope) request.getAttribute(scopeID); + } + + if (scope == null) { + scope = createThreadScope(); + // Save scope in the request early to allow recursive Flow calls + request.setAttribute(scopeID, scope); + } + + return scope; + } + + /** + * Associates a JavaScript scope, a Scriptable object, with + * {@link #getInterpreterID() identifier} of this {@link Interpreter} + * instance. + * + * @param scope a ThreadScope value + */ + private void setSessionScope(ThreadScope scope) throws Exception { + if (scope.useSession) { + final String scopeID = USER_GLOBAL_SCOPE + getInterpreterID(); + final Request request = ContextHelper.getRequest(this.avalonContext); + + // FIXME: Where "session scope" should go when session is invalidated? + // Attach the scope to the current context + try { + Session session = request.getSession(true); + session.setAttribute(scopeID, scope); + } catch (IllegalStateException e) { + // Session might be invalidated already. + if (getLogger().isDebugEnabled()) { + getLogger().debug("Got '" + e + "' while trying to set session scope.", e); + } + } + } + } + + public static class ThreadScope extends ScriptableObject { + private static final String[] BUILTIN_PACKAGES = {"javax", "org", "com"}; + + private ClassLoader classLoader; + + /* true if this scope has assigned any global vars */ + boolean useSession; + + boolean locked = false; + + /** + * Initializes new top-level scope. + */ + public ThreadScope(Global scope) throws Exception { + final Context context = Context.getCurrentContext(); + + final String[] names = { "importClass" }; + try { + defineFunctionProperties(names, + ThreadScope.class, + ScriptableObject.DONTENUM); + } catch (PropertyException e) { + throw new Error(); // should never happen + } + + setPrototype(scope); + + // We want this to be a new top-level scope, so set its + // parent scope to null. This means that any variables created + // by assignments will be properties of this. + setParentScope(null); + + // Put in the thread scope the Cocoon object, which gives access + // to the interpreter object, and some Cocoon objects. See + // FOM_Cocoon for more details. + final Object[] args = {}; + FOM_Cocoon cocoon = (FOM_Cocoon) context.newObject(this, + "FOM_Cocoon", + args); + cocoon.setParentScope(this); + super.put("cocoon", this, cocoon); + + defineProperty(LAST_EXEC_TIME, + new Long(0), + ScriptableObject.DONTENUM | ScriptableObject.PERMANENT); + } + + public String getClassName() { + return "ThreadScope"; + } + + public void setLock(boolean lock) { + this.locked = lock; + } + + public void put(String name, Scriptable start, Object value) { + //Allow setting values to existing variables, or if this is a + //java class (used by importClass & importPackage) + if (this.locked && !has(name, start) && !(value instanceof NativeJavaClass)) { + // Need to wrap into a runtime exception as Scriptable.put has no throws clause... + throw new WrappedException (new JavaScriptException("Implicit declaration of global variable '" + name + + "' forbidden. Please ensure all variables are explicitely declared with the 'var' keyword")); + } + this.useSession = true; + super.put(name, start, value); + } + + public void put(int index, Scriptable start, Object value) { + // FIXME(SW): do indexed properties have a meaning on the global scope? + if (this.locked && !has(index, start)) { + throw new WrappedException(new JavaScriptException("Global scope locked. Cannot set value for index " + index)); + } + this.useSession = true; + super.put(index, start, value); + } + + // Invoked after script execution + void onExec() { + this.useSession = false; + super.put(LAST_EXEC_TIME, this, new Long(System.currentTimeMillis())); + } + + /** Override importClass to allow reloading of classes */ + public static void importClass(Context ctx, + Scriptable thisObj, + Object[] args, + Function funObj) { + for (int i = 0; i < args.length; i++) { + Object clazz = args[i]; + if (!(clazz instanceof NativeJavaClass)) { + throw Context.reportRuntimeError("Not a Java class: " + + Context.toString(clazz)); + } + String s = ((NativeJavaClass) clazz).getClassObject().getName(); + String n = s.substring(s.lastIndexOf('.') + 1); + thisObj.put(n, thisObj, clazz); + } + } + + public void setupPackages(ClassLoader cl) throws Exception { + final String JAVA_PACKAGE = "JavaPackage"; + if (classLoader != cl) { + classLoader = cl; + Scriptable newPackages = new NativeJavaPackage("", cl); + newPackages.setParentScope(this); + newPackages.setPrototype(ScriptableObject.getClassPrototype(this, JAVA_PACKAGE)); + super.put("Packages", this, newPackages); + for (int i = 0; i < BUILTIN_PACKAGES.length; i++) { + String pkgName = BUILTIN_PACKAGES[i]; + Scriptable pkg = new NativeJavaPackage(pkgName, cl); + pkg.setParentScope(this); + pkg.setPrototype(ScriptableObject.getClassPrototype(this, JAVA_PACKAGE)); + super.put(pkgName, this, pkg); + } + } + } + + public ClassLoader getClassLoader() { + return classLoader; + } + } + + private ThreadScope createThreadScope() throws Exception { + return new ThreadScope(scope); + } + + /** + * Returns a new Scriptable object to be used as the global scope + * when running the JavaScript scripts in the context of a request. + * + *

If you want to maintain the state of global variables across + * multiple invocations of <map:call + * function="...">, you need to instanciate the session + * object which is a property of the cocoon object + * var session = cocoon.session. This will place the + * newly create Scriptable object in the user's session, where it + * will be retrieved from at the next invocation of {@link #callFunction}.

+ * + * @exception Exception if an error occurs + */ + private void setupContext(Redirector redirector, Context context, + ThreadScope thrScope) + throws Exception { + // Try to retrieve the scope object from the session instance. If + // no scope is found, we create a new one, but don't place it in + // the session. + // + // When a user script "creates" a session using + // cocoon.createSession() in JavaScript, the thrScope is placed in + // the session object, where it's later retrieved from here. This + // behaviour allows multiple JavaScript functions to share the + // same global scope. + + FOM_Cocoon cocoon = (FOM_Cocoon) thrScope.get("cocoon", thrScope); + long lastExecTime = ((Long) thrScope.get(LAST_EXEC_TIME, + thrScope)).longValue(); + boolean needsRefresh = false; + if (reloadScripts) { + long now = System.currentTimeMillis(); + if (now >= lastTimeCheck + checkTime) { + needsRefresh = true; + } + lastTimeCheck = now; + } + + // We need to setup the FOM_Cocoon object according to the current + // request. Everything else remains the same. + ClassLoader contextClassloader = Thread.currentThread().getContextClassLoader(); + thrScope.setupPackages(contextClassloader); + cocoon.pushCallContext(this, redirector, manager, + avalonContext, getLogger(), null); + + // Check if we need to compile and/or execute scripts + synchronized (compiledScripts) { + List execList = new ArrayList(); + // If we've never executed scripts in this scope or + // if reload-scripts is true and the check interval has expired + // or if new scripts have been specified in the sitemap, + // then create a list of scripts to compile/execute + if (lastExecTime == 0 || needsRefresh || needResolve.size() > 0) { + topLevelScripts.addAll(needResolve); + if (lastExecTime != 0 && !needsRefresh) { + execList.addAll(needResolve); + } else { + execList.addAll(topLevelScripts); + } + needResolve.clear(); + } + // Compile all the scripts first. That way you can set breakpoints + // in the debugger before they execute. + for (int i = 0, size = execList.size(); i < size; i++) { + String sourceURI = (String)execList.get(i); + ScriptSourceEntry entry = + (ScriptSourceEntry)compiledScripts.get(sourceURI); + if (entry == null) { + Source src = this.sourceresolver.resolveURI(sourceURI); + entry = new ScriptSourceEntry(src); + compiledScripts.put(sourceURI, entry); + } + // Compile the script if necessary + entry.getScript(context, this.scope, needsRefresh, this); + } + // Execute the scripts if necessary + for (int i = 0, size = execList.size(); i < size; i++) { + String sourceURI = (String) execList.get(i); + ScriptSourceEntry entry = + (ScriptSourceEntry) compiledScripts.get(sourceURI); + long lastMod = entry.getSource().getLastModified(); + Script script = entry.getScript(context, this.scope, false, this); + if (lastExecTime == 0 || lastMod > lastExecTime) { + script.exec(context, thrScope); + thrScope.onExec(); + } + } + } + } + + /** + * Compile filename as JavaScript code + * + * @param cx Rhino context + * @param fileName resource uri + * @return compiled script + */ + Script compileScript(Context cx, String fileName) throws Exception { + Source src = this.sourceresolver.resolveURI(fileName); + if (src != null) { + synchronized (compiledScripts) { + ScriptSourceEntry entry = + (ScriptSourceEntry)compiledScripts.get(src.getURI()); + Script compiledScript = null; + if (entry == null) { + compiledScripts.put(src.getURI(), + entry = new ScriptSourceEntry(src)); + } else { + this.sourceresolver.release(src); + } + compiledScript = entry.getScript(cx, this.scope, false, this); + return compiledScript; + } + } + throw new ResourceNotFoundException(fileName + ": not found"); + + } + + protected Script compileScript(Context cx, Scriptable scope, Source src) + throws Exception { + PushbackInputStream is = new PushbackInputStream(src.getInputStream(), ENCODING_BUF_SIZE); + try { + String encoding = findEncoding(is); + Reader reader = encoding == null ? new InputStreamReader(is) : new InputStreamReader(is, encoding); + reader = new BufferedReader(reader); + Script compiledScript = cx.compileReader(scope, reader, + src.getURI(), 1, null); + return compiledScript; + } finally { + is.close(); + } + } + + // A charset name can be up to 40 characters taken from the printable characters of US-ASCII + // (see http://www.iana.org/assignments/character-sets). So reading 100 bytes should be more than enough. + private final static int ENCODING_BUF_SIZE = 100; + // Match 'encoding = xxxx' on the first line + REProgram encodingRE = new RECompiler().compile("^.*encoding\\s*=\\s*([^\\s]*)"); + + /** + * Find the encoding of the stream, or null if not specified + */ + String findEncoding(PushbackInputStream is) throws IOException { + // Read some bytes + byte[] buffer = new byte[ENCODING_BUF_SIZE]; + int len = is.read(buffer, 0, buffer.length); + // and push them back + is.unread(buffer, 0, len); + + // Interpret them as an ASCII string + String str = new String(buffer, 0, len, "ASCII"); + RE re = new RE(encodingRE); + if (re.match(str)) { + return re.getParen(1); + } + return null; + } + + /** + * Calls a JavaScript function, passing params as its + * arguments. In addition to this, it makes available the parameters + * through the cocoon.parameters JavaScript array + * (indexed by the parameter names). + * + * @param funName a String value + * @param params a List value + * @param redirector + * @exception Exception if an error occurs + */ + public void callFunction(String funName, List params, Redirector redirector) + throws Exception { + Context context = Context.enter(); + context.setOptimizationLevel(OPTIMIZATION_LEVEL); + context.setGeneratingDebug(true); + context.setCompileFunctionsWithDynamicScope(true); + context.setErrorReporter(new JSErrorReporter(getLogger())); + + LocationTrackingDebugger locationTracker = new LocationTrackingDebugger(); + if (!enableDebugger) { + //FIXME: add a "tee" debugger that allows both to be used simultaneously + context.setDebugger(locationTracker, null); + } + + ThreadScope thrScope = getSessionScope(); + synchronized (thrScope) { + ClassLoader savedClassLoader = + Thread.currentThread().getContextClassLoader(); + FOM_Cocoon cocoon = null; + try { + try { + setupContext(redirector, context, thrScope); + cocoon = (FOM_Cocoon) thrScope.get("cocoon", thrScope); + + // Register the current scope for scripts indirectly called from this function + FOM_JavaScriptFlowHelper.setFOM_FlowScope(cocoon.getObjectModel(), thrScope); + + if (enableDebugger) { + if (!getDebugger().isVisible()) { + // only raise the debugger window if it isn't already visible + getDebugger().setVisible(true); + } + } + + int size = (params != null ? params.size() : 0); + Scriptable parameters = context.newObject(thrScope); + for (int i = 0; i < size; i++) { + Interpreter.Argument arg = (Interpreter.Argument)params.get(i); + if (arg.name == null) { + arg.name = ""; + } + parameters.put(arg.name, parameters, arg.value); + } + cocoon.setParameters(parameters); + + Object fun = ScriptableObject.getProperty(thrScope, funName); + if (fun == Scriptable.NOT_FOUND) { + throw new ResourceNotFoundException("Function \"javascript:" + funName + "()\" not found"); + } + + thrScope.setLock(true); + ScriptRuntime.call(context, fun, thrScope, new Object[0], thrScope); + } catch (JavaScriptException ex) { + throw locationTracker.getException("Error calling flowscript function " + funName, ex); + } catch (EcmaError ee) { + throw locationTracker.getException("Error calling function " + funName, ee); + } catch (WrappedException ee) { + throw locationTracker.getException("Error calling function " + funName, ee); + } + } finally { + thrScope.setLock(false); + setSessionScope(thrScope); + if (cocoon != null) { + cocoon.popCallContext(); + } + Context.exit(); + Thread.currentThread().setContextClassLoader(savedClassLoader); + } + } + } + + public void handleContinuation(String id, List params, + Redirector redirector) throws Exception + { + WebContinuation wk = continuationsMgr.lookupWebContinuation(id, getInterpreterID()); + + if (wk == null) { + /* + * Throw an InvalidContinuationException to be handled inside the + * sitemap element. + */ + throw new InvalidContinuationException("The continuation ID " + id + " is invalid."); + } + + Context context = Context.enter(); + context.setOptimizationLevel(OPTIMIZATION_LEVEL); + context.setGeneratingDebug(true); + context.setCompileFunctionsWithDynamicScope(true); + LocationTrackingDebugger locationTracker = new LocationTrackingDebugger(); + if (!enableDebugger) { + //FIXME: add a "tee" debugger that allows both to be used simultaneously + context.setDebugger(locationTracker, null); + } + + // Obtain the continuation object from it, and setup the + // FOM_Cocoon object associated in the dynamic scope of the saved + // continuation with the environment and context objects. + Continuation k = (Continuation)wk.getContinuation(); + ThreadScope kScope = (ThreadScope)k.getParentScope(); + synchronized (kScope) { + ClassLoader savedClassLoader = + Thread.currentThread().getContextClassLoader(); + FOM_Cocoon cocoon = null; + try { + Thread.currentThread().setContextClassLoader(kScope.getClassLoader()); + cocoon = (FOM_Cocoon)kScope.get("cocoon", kScope); + kScope.setLock(true); + cocoon.pushCallContext(this, redirector, manager, + avalonContext, + getLogger(), wk); + + // Register the current scope for scripts indirectly called from this function + FOM_JavaScriptFlowHelper.setFOM_FlowScope(cocoon.getObjectModel(), kScope); + + if (enableDebugger) { + getDebugger().setVisible(true); + } + Scriptable parameters = context.newObject(kScope); + int size = params != null ? params.size() : 0; + for (int i = 0; i < size; i++) { + Interpreter.Argument arg = (Interpreter.Argument)params.get(i); + parameters.put(arg.name, parameters, arg.value); + } + cocoon.setParameters(parameters); + FOM_WebContinuation fom_wk = new FOM_WebContinuation(wk); + fom_wk.setParentScope(kScope); + fom_wk.setPrototype(ScriptableObject.getClassPrototype(kScope, + fom_wk.getClassName())); + Object[] args = new Object[] {k, fom_wk}; + try { + ScriptableObject.callMethod(cocoon, + "handleContinuation", args); + } catch (JavaScriptException ex) { + throw locationTracker.getException("Error calling continuation", ex); + + } catch (EcmaError ee) { + throw locationTracker.getException("Error calling continuation", ee); + + } + } finally { + kScope.setLock(false); + setSessionScope(kScope); + if (cocoon != null) { + cocoon.popCallContext(); + } + Context.exit(); + Thread.currentThread().setContextClassLoader(savedClassLoader); + } + } + } + + private Throwable unwrap(JavaScriptException e) { + Object value = e.getValue(); + while (value instanceof Wrapper) { + value = ((Wrapper)value).unwrap(); + } + if (value instanceof Throwable) { + return (Throwable)value; + } + return e; + } + + public void forwardTo(Scriptable scope, FOM_Cocoon cocoon, String uri, + Object bizData, FOM_WebContinuation fom_wk, + Redirector redirector) + throws Exception { + setupView(scope, cocoon, fom_wk); + super.forwardTo(uri, bizData, + fom_wk == null ? null : fom_wk.getWebContinuation(), + redirector); + } + + // package access as this is called by FOM_Cocoon + void process(Scriptable scope, FOM_Cocoon cocoon, String uri, + Object bizData, OutputStream out) + throws Exception { + setupView(scope, cocoon, null); + super.process(uri, bizData, out); + } + + private void setupView(Scriptable scope, FOM_Cocoon cocoon, FOM_WebContinuation kont) { + Map objectModel = ContextHelper.getObjectModel(this.avalonContext); + + // Make the JS live-connect objects available to the view layer + FOM_JavaScriptFlowHelper.setPackages(objectModel, + (Scriptable)ScriptableObject.getProperty(scope, "Packages")); + FOM_JavaScriptFlowHelper.setJavaPackage(objectModel, + (Scriptable)ScriptableObject.getProperty(scope, "java")); + + // Make the FOM objects available to the view layer + FOM_JavaScriptFlowHelper.setFOM_Request(objectModel, + cocoon.jsGet_request()); + FOM_JavaScriptFlowHelper.setFOM_Response(objectModel, + cocoon.jsGet_response()); + Request request = ObjectModelHelper.getRequest(objectModel); + Scriptable session = null; + if (request.getSession(false) != null) { + session = cocoon.jsGet_session(); + } + FOM_JavaScriptFlowHelper.setFOM_Session(objectModel, session); + + FOM_JavaScriptFlowHelper.setFOM_Context(objectModel, + cocoon.jsGet_context()); + if (kont != null) { + FOM_JavaScriptFlowHelper.setFOM_WebContinuation(objectModel, kont); + } + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptInterpreter.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_WebContinuation.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_WebContinuation.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_WebContinuation.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_WebContinuation.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,256 @@ +/* + * 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.cocoon.components.flow.javascript.fom; + +import java.util.Iterator; +import java.util.List; + +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.cocoon.components.flow.ContinuationsManager; +import org.apache.cocoon.components.flow.WebContinuation; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Function; +import org.mozilla.javascript.NativeArray; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; +import org.mozilla.javascript.Undefined; +import org.mozilla.javascript.Wrapper; +import org.mozilla.javascript.continuations.Continuation; + +/** + * + * @version CVS $Id: FOM_WebContinuation.java 292158 2005-09-28 10:24:51Z sylvain $ + */ +public class FOM_WebContinuation extends ScriptableObject { + + WebContinuation wk; + + + static class UserObject { + boolean isBookmark; + PageLocalScopeImpl pageLocal; + } + + static private boolean isBookmark(WebContinuation wk) { + UserObject userObj = (UserObject)wk.getUserObject(); + if (userObj == null) { + return false; + } + return userObj.isBookmark; + } + + public FOM_WebContinuation() { + this(null); + } + + + public FOM_WebContinuation(WebContinuation wk) { + this.wk = wk; + } + + // new FOM_WebContinuation([Continuation] continuation, + // [FOM_WebContinuation] parent, + // [Number] timeToLive) + public static Object jsConstructor(Context cx, Object[] args, + Function ctorObj, + boolean inNewExpr) + throws Exception { + FOM_WebContinuation result = null; + if (args.length < 1) { + // error + } + Continuation c = (Continuation)unwrap(args[0]); + FOM_WebContinuation parent = null; + if (args.length > 1) { + parent = (FOM_WebContinuation)args[1]; + } + int timeToLive = 0; + if (args.length > 2) { + timeToLive = + (int)org.mozilla.javascript.Context.toNumber(args[2]); + } + WebContinuation wk; + Scriptable scope = getTopLevelScope(c); + FOM_Cocoon cocoon = (FOM_Cocoon)getProperty(scope, "cocoon"); + ServiceManager componentManager = cocoon.getServiceManager(); + ContinuationsManager contMgr = (ContinuationsManager) + componentManager.lookup(ContinuationsManager.ROLE); + wk = contMgr.createWebContinuation(c, + (parent == null ? null : parent.getWebContinuation()), + timeToLive, + cocoon.getInterpreterId(), + null); + result = new FOM_WebContinuation(wk); + result.setParentScope(getTopLevelScope(scope)); + result.setPrototype(getClassPrototype(scope, result.getClassName())); + return result; + } + + public String getClassName() { + return "FOM_WebContinuation"; + } + + public Object jsFunction_getAttribute(String name) { + return org.mozilla.javascript.Context.javaToJS( + wk.getAttribute(name), + getParentScope()); + } + + public void jsFunction_setAttribute(String name, Object value) { + wk.setAttribute(name, unwrap(value)); + } + + public void jsFunction_removeAttribute(String name) { + wk.removeAttribute(name); + } + + public Object jsFunction_getAttributeNames() { + return org.mozilla.javascript.Context.javaToJS( + wk.getAttributeNames(), + getParentScope()); + } + + public String jsGet_id() { + return wk.getId(); + } + + + public Continuation jsGet_continuation() { + return (Continuation)wk.getContinuation(); + } + + public FOM_WebContinuation jsFunction_getParent() { + WebContinuation parent = wk.getParentContinuation(); + if (parent == null) { + return null; + } + + FOM_WebContinuation pwk = new FOM_WebContinuation(parent); + pwk.setParentScope(getParentScope()); + pwk.setPrototype(getClassPrototype(getParentScope(), + pwk.getClassName())); + return pwk; + } + + public NativeArray jsFunction_getChildren() throws Exception { + List list = wk.getChildren(); + NativeArray arr = + (NativeArray)org.mozilla.javascript.Context.getCurrentContext().newObject(getParentScope(), + "Array", + new Object[]{new Integer(list.size())}); + Iterator iter = list.iterator(); + for (int i = 0; iter.hasNext(); i++) { + WebContinuation child = (WebContinuation)iter.next(); + FOM_WebContinuation cwk = new FOM_WebContinuation(child); + cwk.setParentScope(getParentScope()); + cwk.setPrototype(getClassPrototype(getParentScope(), + cwk.getClassName())); + arr.put(i, arr, cwk); + } + return arr; + } + + public void jsFunction_invalidate() throws Exception { + ContinuationsManager contMgr = null; + FOM_Cocoon cocoon = + (FOM_Cocoon)getProperty(getTopLevelScope(this), "cocoon"); + ServiceManager componentManager = cocoon.getServiceManager(); + contMgr = (ContinuationsManager) + componentManager.lookup(ContinuationsManager.ROLE); + contMgr.invalidateWebContinuation(wk); + } + + public void jsFunction_display() { + wk.display(); + } + + public WebContinuation getWebContinuation() { + return wk; + } + + private static Object unwrap(Object obj) { + if (obj instanceof Wrapper) { + obj = ((Wrapper)obj).unwrap(); + } else if (obj == Undefined.instance) { + obj = null; + } + return obj; + } + + PageLocalScopeImpl getPageLocal() { + UserObject userObj = (UserObject)wk.getUserObject(); + if (userObj == null) return null; + return userObj.pageLocal; + } + + void setPageLocal(PageLocalScopeImpl pageLocal) { + UserObject userObj = (UserObject)wk.getUserObject(); + if (userObj == null) { + userObj = new UserObject(); + wk.setUserObject(userObj); + } + userObj.pageLocal = pageLocal; + } + + public void jsFunction_setBookmark(boolean value) { + UserObject userObj = (UserObject)wk.getUserObject(); + if (userObj == null) { + userObj = new UserObject(); + wk.setUserObject(userObj); + } + userObj.isBookmark = value; + } + + public boolean jsGet_bookmark() { + return isBookmark(wk); + } + + public boolean jsFunction_isBookmark() { + return isBookmark(wk); + } + + public FOM_WebContinuation jsGet_previousBookmark() { + WebContinuation c = wk.getParentContinuation(); + if (c == null) { + return null; + } + + // If this is a continuation of sendPageAndWait() + // and the immediate parent is a bookmark, then + // it is the bookmark for this page, so skip it. + if (!isBookmark(wk) && isBookmark(c)) { + c = c.getParentContinuation(); + } + while (c != null && !isBookmark(c)) { + c = c.getParentContinuation(); + } + if (c == null) { + return null; + } + + FOM_WebContinuation pwk = new FOM_WebContinuation(c); + pwk.setParentScope(getParentScope()); + pwk.setPrototype(getClassPrototype(getParentScope(), pwk.getClassName())); + return pwk; + } + + /** + * Return text representation of the WebContinuation. + */ + public String toString() { + return "WC" + wk.getId(); + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/FOM_WebContinuation.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocal.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocal.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocal.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocal.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,29 @@ +/* + * 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.cocoon.components.flow.javascript.fom; + +import org.mozilla.javascript.Scriptable; + +/** + * @version CVS $Id: PageLocal.java 36239 2004-08-11 18:28:06Z vgritsenko $ + */ +public interface PageLocal extends Scriptable { + + public Object getId(); + + public void setPageLocalScope(PageLocalScope scope); + +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocal.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalImpl.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalImpl.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalImpl.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalImpl.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,119 @@ +/* + * 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.cocoon.components.flow.javascript.fom; + +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; + +/** + * @version CVS $Id: PageLocalImpl.java 36239 2004-08-11 18:28:06Z vgritsenko $ + */ +public class PageLocalImpl extends ScriptableObject implements PageLocal { + + private PageLocalScope scope; // null if this is the prototype + private String id; + + public PageLocalImpl() { + this.id = String.valueOf(System.identityHashCode(this)); + } + + public void setPageLocalScope(PageLocalScope scope) { + this.scope = scope; + } + + public Object getId() { + return id; + } + + public String getClassName() { + return "PageLocal"; + } + + public boolean has(String name, Scriptable start) { + if (scope == null) { + return super.has(name, start); + } + return scope.has(this, name); + } + + public boolean has(int index, Scriptable start) { + if (scope == null) { + return super.has(index, start); + } + return scope.has(this, index); + } + + public void put(String name, Scriptable start, Object value) { + if (scope == null) { + super.put(name, start, value); + } else { + scope.put(this, name, value); + } + } + + public void put(int index, Scriptable start, Object value) { + if (scope == null) { + super.put(index, start, value); + } else { + scope.put(this, index, value); + } + } + + public Object get(String name, Scriptable start) { + if (scope == null) { + return super.get(name, start); + } + return scope.get(this, name); + } + + public Object get(int index, Scriptable start) { + if (scope == null) { + return super.get(index, start); + } + return scope.get(this, index); + } + + public void delete(int index) { + if (scope == null) { + super.delete(index); + } else { + scope.delete(this, index); + } + } + + public void delete(String name) { + if (scope == null) { + super.delete(name); + } else { + scope.delete(this, name); + } + } + + public Object[] getIds() { + if (scope == null) { + return super.getIds(); + } + return scope.getIds(this); + } + + public Object getDefaultValue(Class hint) { + if (scope == null) { + return super.getDefaultValue(hint); + } + return scope.getDefaultValue(this, hint); + } + +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalImpl.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScope.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScope.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScope.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScope.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,44 @@ +/* + * 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.cocoon.components.flow.javascript.fom; + +/** + * @version CVS $Id: PageLocalScope.java 36239 2004-08-11 18:28:06Z vgritsenko $ + */ +public interface PageLocalScope { + + public boolean has(PageLocal local, String name); + + public boolean has(PageLocal local, int index); + + public Object get(PageLocal local, String name); + + public Object get(PageLocal local, int index); + + public void put(PageLocal local, String name, Object value); + + public void put(PageLocal local, int index, Object value); + + public void delete(PageLocal local, String name); + + public void delete(PageLocal local, int index); + + public Object[] getIds(PageLocal local); + + public Object getDefaultValue(PageLocal local, Class hint); + + public PageLocal createPageLocal(); +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScope.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScopeHolder.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScopeHolder.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScopeHolder.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScopeHolder.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,89 @@ +/* + * 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.cocoon.components.flow.javascript.fom; + +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; + +/** + * @version CVS $Id: PageLocalScopeHolder.java 36239 2004-08-11 18:28:06Z vgritsenko $ + */ +public class PageLocalScopeHolder implements PageLocalScope { + + private Scriptable scope; + private PageLocalScopeImpl delegate; + + public PageLocalScopeHolder(Scriptable scope) { + this.scope = scope; + } + + public boolean has(PageLocal local, String name) { + return delegate.has(local, name); + } + + public boolean has(PageLocal local, int index) { + return delegate.has(local, index); + } + + public Object get(PageLocal local, String name) { + return delegate.get(local, name); + } + + public Object get(PageLocal local, int index) { + return delegate.get(local, index); + } + + public void put(PageLocal local, String name, Object value) { + delegate.put(local, name, value); + } + + public void put(PageLocal local, int index, Object value) { + delegate.put(local, index, value); + } + + public void delete(PageLocal local, String name) { + delegate.delete(local, name); + } + + public void delete(PageLocal local, int index) { + delegate.delete(local, index); + } + + public Object[] getIds(PageLocal local) { + return delegate.getIds(local); + } + + public Object getDefaultValue(PageLocal local, Class hint) { + return delegate.getDefaultValue(local, hint); + } + + public void setDelegate(PageLocalScopeImpl delegate) { + this.delegate = delegate; + } + + public PageLocalScopeImpl getDelegate() { + return delegate; + } + + public PageLocal createPageLocal() { + PageLocalImpl pageLocal = new PageLocalImpl(); + pageLocal.setPrototype(ScriptableObject.getClassPrototype(scope, + pageLocal.getClassName())); + pageLocal.setParentScope(scope); + pageLocal.setPageLocalScope(this); + return pageLocal; + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScopeHolder.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScopeImpl.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScopeImpl.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScopeImpl.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScopeImpl.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,136 @@ +/* + * 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.cocoon.components.flow.javascript.fom; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Scriptable; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * @version CVS $Id: PageLocalScopeImpl.java 36239 2004-08-11 18:28:06Z vgritsenko $ + */ +public class PageLocalScopeImpl implements PageLocalScope { + + private Map locals; + private Scriptable scope; + + public PageLocalScopeImpl(Scriptable scope) { + locals = new HashMap(); + this.scope = scope; + } + + private Scriptable newObject() { + try { + return Context.getCurrentContext().newObject(scope); + } catch (Exception ignored) { + // can't happen here + ignored.printStackTrace(); + throw new Error("error: " + ignored); + } + } + + private PageLocalScopeImpl(PageLocalScopeImpl toBeCloned) { + this.scope = toBeCloned.scope; + locals = new HashMap(); + Iterator iter = toBeCloned.locals.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry e = (Map.Entry)iter.next(); + Object key = e.getKey(); + Object value = e.getValue(); + // clone it + Scriptable obj = (Scriptable)value; + Scriptable newObj = newObject(); + Object[] ids = obj.getIds(); + for (int i = 0; i < ids.length; i++) { + String name = ids[i].toString(); + newObj.put(name, newObj, obj.get(name, obj)); + } + value = newObj; + locals.put(key, value); + } + } + + private Scriptable resolve(PageLocal local) { + final Object id = local.getId(); + Scriptable result = (Scriptable)locals.get(id); + if (result == null) { + locals.put(id, result = newObject()); + } + return result; + } + + public boolean has(PageLocal local, String name) { + Scriptable obj = resolve(local); + return obj.has(name, obj); + } + + public boolean has(PageLocal local, int index) { + Scriptable obj = resolve(local); + return obj.has(index, obj); + } + + public Object get(PageLocal local, String name) { + Scriptable obj = resolve(local); + return obj.get(name, obj); + } + + public Object get(PageLocal local, int index) { + Scriptable obj = resolve(local); + return obj.get(index, obj); + } + + public void put(PageLocal local, String name, Object value) { + Scriptable obj = resolve(local); + obj.put(name, obj, value); + } + + public void put(PageLocal local, int index, Object value) { + Scriptable obj = resolve(local); + obj.put(index, obj, value); + } + + public void delete(PageLocal local, String name) { + Scriptable obj = resolve(local); + obj.delete(name); + } + + public void delete(PageLocal local, int index) { + Scriptable obj = resolve(local); + obj.delete(index); + } + + public Object[] getIds(PageLocal local) { + Scriptable obj = resolve(local); + return obj.getIds(); + } + + public Object getDefaultValue(PageLocal local, Class hint) { + Scriptable obj = resolve(local); + return obj.getDefaultValue(hint); + } + + public PageLocalScopeImpl duplicate() { + return new PageLocalScopeImpl(this); + } + + public PageLocal createPageLocal() { + // not used + return null; + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/PageLocalScopeImpl.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/fom_system.js URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/fom_system.js?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/fom_system.js (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/fom_system.js Thu Nov 3 05:41:06 2005 @@ -0,0 +1,56 @@ +/* +* 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. +*/ +FOM_Cocoon.suicide = new Continuation(); + +FOM_Cocoon.prototype.sendPageAndWait = function(uri, bizData, fun, ttl) { + this.sendPage(uri, bizData, + new FOM_WebContinuation(new Continuation(), + this.continuation, ttl)); + if (fun) { + if (!(fun instanceof Function)) { + throw "Expected a function instead of: " + fun; + } + fun(); + } + FOM_Cocoon.suicide(); +} + +FOM_Cocoon.prototype.handleContinuation = function(k, wk) { + k(wk); +} + +FOM_Cocoon.prototype.createWebContinuation = function(ttl) { + var wk = this.makeWebContinuation(new Continuation(), ttl); + wk.setBookmark(true); + return wk; +} + +/** + * Exit the current flowscript invocation. + *

+ * There are some flowscript use cases where we want to stop the current + * flowscript without creating a continuation, as we don't want the user + * to go back to the script. + *

+ * An example is a "login" function where the caller function expects this + * function to exit only if login is successful, but that has to handle + * e.g. a registration process that includes a "cancel" button. + */ +FOM_Cocoon.prototype.exit = function() { + FOM_Cocoon.suicide(); +} + + Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/javascript/fom/fom_system.js ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/util/PipelineUtil.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/util/PipelineUtil.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/util/PipelineUtil.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/util/PipelineUtil.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,181 @@ +/* + * 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.cocoon.components.flow.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; + +import org.apache.avalon.excalibur.io.IOUtil; +import org.apache.avalon.framework.activity.Disposable; +import org.apache.avalon.framework.context.Context; +import org.apache.avalon.framework.context.ContextException; +import org.apache.avalon.framework.context.Contextualizable; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; +import org.apache.cocoon.ProcessingException; +import org.apache.cocoon.components.ContextHelper; +import org.apache.cocoon.components.flow.FlowHelper; +import org.apache.cocoon.components.source.SourceUtil; +import org.apache.excalibur.source.Source; +import org.apache.excalibur.source.SourceResolver; +import org.w3c.dom.Document; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +/** + * Utility class to process a pipeline to various destinations. + * This class must be setup from the flowscript before being used. This means that instances must + * be created with cocoon.createObject(Packages.org.apache.cocoon.components.flow.util.PipelineUtil); + * + * @author Sylvain Wallez + * @version CVS $Id: PipelineUtil.java 43562 2004-09-09 02:29:46Z vgritsenko $ + */ +public class PipelineUtil implements Contextualizable, Serviceable, Disposable { + + private Context context; + private ServiceManager manager; + private SourceResolver resolver; + + /* (non-Javadoc) + * @see org.apache.avalon.framework.activity.Disposable#dispose() + */ + public void dispose() { + if (this.manager != null) { + this.manager.release(this.resolver); + this.manager = null; + this.resolver = null; + } + } + + public void contextualize(Context context) throws ContextException { + this.context = context; + + } + + public void service(ServiceManager manager) throws ServiceException { + this.manager = manager; + this.resolver = (SourceResolver)manager.lookup(SourceResolver.ROLE); + } + + /** + * Check that this object has been correctly set up. + * + * @throws IllegalStateException if not already set up. + */ + private void checkSetup() { + if (this.manager == null) { + throw new IllegalStateException("Instances of " + getClass().getName() + + " must be setup using either cocoon.createObject() or cocoon.setupObject()."); + } + } + + /** + * Process a pipeline to a stream. + * + * @param uri the pipeline URI + * @param viewData the view data object + * @param output the stream where pipeline result is output. Note: this stream is not closed. + * @throws IOException + */ + public void processToStream(String uri, Object viewData, OutputStream output) + throws IOException { + checkSetup(); + + Map objectModel = ContextHelper.getObjectModel(this.context); + + // Keep the previous view data, if any (is it really necessary?), and set the new one + Object oldViewData = FlowHelper.getContextObject(objectModel); + FlowHelper.setContextObject(objectModel, FlowHelper.unwrap(viewData)); + + Source src = null; + InputStream input = null; + try { + src = this.resolver.resolveURI("cocoon:/" + uri); + input = src.getInputStream(); + IOUtil.copy(input, output); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException ignored) {} + } + + // Restore the previous view data + FlowHelper.setContextObject(objectModel, oldViewData); + + if (src != null) { + this.resolver.release(src); + } + } + } + + /** + * Process a pipeline to a SAX ContentHandler + * + * @param uri the pipeline URI + * @param viewData the view data object + * @param handler where the pipeline should be streamed to. + */ + public void processToSAX(String uri, Object viewData, ContentHandler handler) + throws SAXException, IOException, ProcessingException { + checkSetup(); + + Map objectModel = ContextHelper.getObjectModel(this.context); + Object oldViewData = FlowHelper.getContextObject(objectModel); + FlowHelper.setContextObject(objectModel, FlowHelper.unwrap(viewData)); + + Source src = null; + try { + src = this.resolver.resolveURI("cocoon:/" + uri); + SourceUtil.toSAX(src, handler); + } finally { + FlowHelper.setContextObject(objectModel, oldViewData); + if (src != null) { + this.resolver.release(src); + } + } + } + + /** + * Process a pipeline and gets is result as a DOM Document + * + * @param uri the pipeline URI + * @param viewData the view data object + * @return the document + */ + public Document processToDOM(String uri, Object viewData) throws ProcessingException, SAXException, IOException { + checkSetup(); + + Map objectModel = ContextHelper.getObjectModel(this.context); + Object oldViewData = FlowHelper.getContextObject(objectModel); + FlowHelper.setContextObject(objectModel, FlowHelper.unwrap(viewData)); + + Source src = null; + + try { + src = this.resolver.resolveURI("cocoon:/" + uri); + return SourceUtil.toDOM(src); + } finally { + FlowHelper.setContextObject(objectModel, oldViewData); + if (src != null) { + this.resolver.release(src); + } + } + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/flow/util/PipelineUtil.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/modules/input/AbstractInputModule.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/modules/input/AbstractInputModule.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/modules/input/AbstractInputModule.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/modules/input/AbstractInputModule.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,118 @@ +/* + * 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.cocoon.components.modules.input; + +import java.util.Iterator; +import java.util.Map; +import java.util.Vector; + +import org.apache.avalon.framework.activity.Disposable; +import org.apache.avalon.framework.configuration.Configurable; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.logger.AbstractLogEnabled; + +import org.apache.cocoon.util.HashMap; + +/** + * AbstractInputModule gives you the infrastructure for easily + * deploying more InputModules. In order to get at the Logger, use + * getLogger(). + * + * @author Christian Haul + * @version CVS $Id: AbstractInputModule.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public abstract class AbstractInputModule extends AbstractLogEnabled + implements InputModule, Configurable, Disposable { + + /** + * For those modules that access only one attribute, have a + * fixed collection we can return an iterator for. + */ + final static Vector returnNames; + static { + Vector tmp = new Vector(); + tmp.add("attribute"); + returnNames = tmp; + } + + + + /** + * Stores (global) configuration parameters as key / + * value pairs. + */ + protected HashMap settings = null; + + /** + * Configures the database access helper. + * + * Takes all elements nested in component declaration and stores + * them as key-value pairs in settings. Nested + * configuration option are not catered for. This way global + * configuration options can be used. + * + * For nested configurations override this function. + * */ + public void configure(Configuration conf) throws ConfigurationException { + Configuration[] parameters = conf.getChildren(); + this.settings = new HashMap(parameters.length); + for (int i = 0; i < parameters.length; i++) { + String key = parameters[i].getName(); + String val = parameters[i].getValue(""); + this.settings.put (key, val); + } + } + + /** + * dispose + */ + public void dispose() { + // Purposely empty so that we don't need to implement it in every + // class. + } + + // + // you need to implement at least one of the following two methods + // since the ones below have a cyclic dependency! + // + + /* (non-Javadoc) + * @see org.apache.cocoon.components.modules.input.InputModule#getAttribute(java.lang.String, org.apache.avalon.framework.configuration.Configuration, java.util.Map) + */ + public Object getAttribute(String name, Configuration modeConf, Map objectModel) throws ConfigurationException { + Object[] result = this.getAttributeValues(name, modeConf, objectModel); + return (result == null ? null : result[0]); + } + + /* (non-Javadoc) + * @see org.apache.cocoon.components.modules.input.InputModule#getAttributeValues(java.lang.String, org.apache.avalon.framework.configuration.Configuration, java.util.Map) + */ + public Object[] getAttributeValues(String name, Configuration modeConf, Map objectModel) + throws ConfigurationException { + Object result = this.getAttribute(name, modeConf, objectModel); + return (result == null ? null : new Object[] {result}); + } + + + /* (non-Javadoc) + * @see org.apache.cocoon.components.modules.input.InputModule#getAttributeNames(org.apache.avalon.framework.configuration.Configuration, java.util.Map) + */ + public Iterator getAttributeNames(Configuration modeConf, Map objectModel) throws ConfigurationException { + return AbstractInputModule.returnNames.iterator(); + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/modules/input/AbstractInputModule.java ------------------------------------------------------------------------------ svn:eol-style = native