You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by mr...@apache.org on 2005/11/27 08:10:27 UTC
svn commit: r349187 [3/6] - in /struts/flow/trunk: ./ src/examples/WEB-INF/
src/examples/WEB-INF/guess/ src/examples/WEB-INF/portlet/
src/examples/WEB-INF/remote/ src/examples/remote/ src/java/
src/java/org/apache/struts/flow/ src/java/org/apache/strut...
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/ConversionHelper.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/ConversionHelper.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/ConversionHelper.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/ConversionHelper.java Sat Nov 26 23:10:08 2005
@@ -0,0 +1,74 @@
+/*
+ * Copyright 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.struts.flow.core.javascript;
+
+import java.util.ArrayList;
+import java.util.*;
+
+import org.mozilla.javascript.Wrapper;
+import org.mozilla.javascript.Undefined;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptRuntime;
+import org.mozilla.javascript.NativeArray;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.JavaScriptException;
+
+/**
+ * Aids in converting from Javascript objects to Java objects and vice versa.
+ * @version $Id: LocationTrackingDebugger.java 280811 2005-09-14 09:53:32Z sylvain $
+ */
+public class ConversionHelper {
+
+ /**
+ * Converts a JavaScript object to a HashMap
+ *
+ *@param jsobject The object to convert
+ *@return The Map
+ */
+ public static Map jsobjectToMap(Scriptable jsobject) {
+ HashMap hash = new HashMap();
+ Object[] ids = jsobject.getIds();
+ for (int i = 0; i < ids.length; i++) {
+ String key = ScriptRuntime.toString(ids[i]);
+ Object value = jsobject.get(key, jsobject);
+ if (value == Undefined.instance) {
+ value = null;
+ } else {
+ value = jsobjectToObject(value);
+ }
+ hash.put(key, value);
+ }
+ return hash;
+ }
+
+ /**
+ * Converts a JavaScript object to a Java Object
+ *
+ *@param obj The JavaScript object
+ *@return The Java Object
+ */
+ public static Object jsobjectToObject(Object obj) {
+ // unwrap Scriptable wrappers of real Java objects
+ if (obj instanceof Wrapper) {
+ obj = ((Wrapper) obj).unwrap();
+ } else if (obj == Undefined.instance) {
+ obj = null;
+ }
+ return obj;
+ }
+}
+
Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/ConversionHelper.java
------------------------------------------------------------------------------
svn:executable = *
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/JSErrorReporter.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/JSErrorReporter.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/JSErrorReporter.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/JSErrorReporter.java Sat Nov 26 23:10:08 2005
@@ -0,0 +1,124 @@
+/*
+* 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.javascript;
+
+import org.apache.struts.flow.core.Logger;
+import org.apache.struts.flow.core.location.Location;
+import org.apache.struts.flow.core.location.LocationImpl;
+import org.mozilla.javascript.ErrorReporter;
+import org.mozilla.javascript.EvaluatorException;
+import org.mozilla.javascript.tools.ToolErrorReporter;
+
+/**
+ * Implements a Rhino JavaScript {@link
+ * org.mozilla.javascript.ErrorReporter}.
+ * Like ToolErrorReporter but logs to supplied logger instead of stdout
+ *
+ * @version CVS $Id: JSErrorReporter.java 292797 2005-09-30 16:05:46Z sylvain $
+ */
+public class JSErrorReporter implements ErrorReporter
+{
+ private Logger logger;
+ private Location location;
+ private StringBuffer message;
+
+ public JSErrorReporter(Logger logger)
+ {
+ this.logger = logger;
+ }
+
+ private void appendMessage(String text, String sourceName, int line, int column) {
+ if (location == null) {
+ location = new LocationImpl(null, sourceName, line, column);
+ message = new StringBuffer();
+ } else {
+ // Append a linefeed
+ message.append("\n");
+ }
+
+ message.append(text);
+ }
+
+ public void error(String message,
+ String sourceName, int line,
+ String lineSrc, int column)
+ {
+ String errMsg = getErrorMessage("msg.error", message,
+ sourceName, line, lineSrc, column);
+ appendMessage(errMsg, sourceName, line, column);
+ System.err.println(errMsg);
+ logger.error(errMsg);
+ }
+
+ public void warning(String message, String sourceName, int line,
+ String lineSrc, int column)
+ {
+ String errMsg = getErrorMessage("msg.warning", message,
+ sourceName, line, lineSrc, column);
+ appendMessage(errMsg, sourceName, line, column);
+ System.err.println(errMsg);
+ logger.warn(errMsg);
+ }
+
+ public EvaluatorException runtimeError(String message, String sourceName,
+ int line, String lineSrc,
+ int column)
+ {
+ String errMsg = getErrorMessage("msg.error", message,
+ sourceName, line,
+ lineSrc, column);
+ appendMessage(errMsg, sourceName, line, column);
+ System.err.println(errMsg);
+ // FIXME(SW): need to build a locatable extension to EvaluatorException
+ return new EvaluatorException(this.message.toString());
+ }
+
+ /**
+ * Formats error message
+ *
+ * @param type a <code>String</code> value, indicating the error
+ * type (error or warning)
+ * @param message a <code>String</code> value, the error or warning
+ * message
+ * @param line an <code>int</code> value, the original cummulative
+ * line number
+ * @param lineSource a <code>String</code> value, the text of the
+ * line in the file
+ * @param column an <code>int</code> value, the column in
+ * <code>lineSource</code> where the error appeared
+ * @return a <code>String</code> value, the aggregated error
+ * message, with the source file and line number adjusted to the
+ * real values
+ */
+ String getErrorMessage(String type,
+ String message,
+ String sourceName, int line,
+ String lineSource, int column)
+ {
+ if (line > 0) {
+ if (sourceName != null) {
+ Object[] errArgs = { sourceName, new Integer(line), message };
+ return ToolErrorReporter.getMessage("msg.format3", errArgs);
+ } else {
+ Object[] errArgs = { new Integer(line), message };
+ return ToolErrorReporter.getMessage("msg.format2", errArgs);
+ }
+ } else {
+ Object[] errArgs = { message };
+ return ToolErrorReporter.getMessage("msg.format1", errArgs);
+ }
+ }
+}
Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/JSErrorReporter.java
------------------------------------------------------------------------------
svn:executable = *
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/LocationTrackingDebugger.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/LocationTrackingDebugger.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/LocationTrackingDebugger.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/LocationTrackingDebugger.java Sat Nov 26 23:10:08 2005
@@ -0,0 +1,157 @@
+/*
+ * Copyright 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.struts.flow.core.javascript;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.struts.flow.core.FlowException;
+import org.apache.struts.flow.core.location.Location;
+import org.apache.struts.flow.core.location.LocationImpl;
+import org.apache.struts.flow.core.location.LocationUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.EcmaError;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.debug.DebugFrame;
+import org.mozilla.javascript.debug.DebuggableScript;
+import org.mozilla.javascript.debug.Debugger;
+
+/**
+ * A Rhino debugger that tracks location information when an exception is raised in some JavaScript code.
+ * It's purpose is to build a {@link org.apache.flow.core.FlowException} that holds the stacktrace
+ * in the JavaScript code.
+ * <p>
+ * This debugger implementation is designed to be as lightweight and fast as possible, in order to have a
+ * negligible impact on the performances of the Rhino interpreter.
+ *
+ * @since 2.1.8
+ * @version $Id: LocationTrackingDebugger.java 280811 2005-09-14 09:53:32Z sylvain $
+ */
+public class LocationTrackingDebugger implements Debugger {
+
+ // Strong reference to the location finder
+ private static final LocationUtils.LocationFinder rhinoLocFinder = new LocationUtils.LocationFinder() {
+
+ public Location getLocation(Object obj, String description) {
+ if (obj instanceof EcmaError) {
+ EcmaError ex = (EcmaError)obj;
+ if (ex.getSourceName() != null) {
+ return new LocationImpl(ex.getName(), ex.getSourceName(), ex.getLineNumber(), ex.getColumnNumber());
+ } else {
+ return Location.UNKNOWN;
+ }
+
+ } else if (obj instanceof JavaScriptException) {
+ JavaScriptException ex = (JavaScriptException)obj;
+ if (ex.sourceName() != null) {
+ return new LocationImpl(description, ex.sourceName(), ex.lineNumber(), -1);
+ } else {
+ return Location.UNKNOWN;
+ }
+ }
+
+ return null;
+ }
+ };
+
+
+ static {
+ // Register what's needed to analyze exceptions produced by Rhino
+ ExceptionUtils.addCauseMethodName("getWrappedException");
+ LocationUtils.addFinder(rhinoLocFinder);
+ }
+
+ private List locations;
+ private Throwable throwable;
+
+ public void handleCompilationDone(Context cx, DebuggableScript fnOrScript, String source) {
+ // nothing
+ }
+
+ public DebugFrame getFrame(Context cx, DebuggableScript fnOrScript) {
+ return new StackTrackingFrame(fnOrScript);
+ }
+
+ /**
+ * Get an exception that reflects the known location stack
+ *
+ * @param description a description for the exception
+ * @param originalException the original exception
+ *
+ * @return a suitable exception to throw
+ * @see ProcessingException#throwLocated(String, Throwable, Location)
+ */
+ public Exception getException(String description, Exception originalException) throws FlowException {
+ if (throwable == null || locations == null) {
+ // Cannot to better for now
+ return originalException;
+ }
+
+ // Unwrap original exception, if any, wrapped by Rhino (the wrapping
+ // class is different in Rhino+cont and Rhino 1.6)
+ Throwable cause = ExceptionUtils.getCause(throwable);
+ if (cause != null)
+ throwable = cause;
+
+ return FlowException.throwLocated(description, throwable, locations);
+ }
+
+ private class StackTrackingFrame implements DebugFrame {
+
+ DebuggableScript script;
+ int line;
+
+ public StackTrackingFrame(DebuggableScript script) {
+ this.script = script;
+ }
+
+ public void onEnter(Context cx, Scriptable activation, Scriptable thisObj, Object[] args) {
+ // nothing
+ }
+
+ public void onLineChange(Context cx, int lineNumber) {
+ line = lineNumber;
+ }
+
+ public void onExceptionThrown(Context cx, Throwable ex) {
+ throwable = ex;
+ }
+
+ public void onExit(Context cx, boolean byThrow, Object resultOrException) {
+ if (byThrow) {
+ String name = null;
+ if (script.isFunction()) {
+ name = script.getFunctionName();
+ } else {
+ name = "[script]";
+ }
+
+ if (locations == null) {
+ locations = new ArrayList(1); // start small
+ }
+
+ locations.add(new LocationImpl(name, script.getSourceName(), line, -1));
+
+ } else if (locations != null) {
+ // The exception was handled by the script: clear any recorded locations
+ locations = null;
+ }
+ }
+ }
+}
+
Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/LocationTrackingDebugger.java
------------------------------------------------------------------------------
svn:executable = *
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOMResourceNotFoundException.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOMResourceNotFoundException.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOMResourceNotFoundException.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOMResourceNotFoundException.java Sat Nov 26 23:10:08 2005
@@ -0,0 +1,33 @@
+/*
+ * Copyright 1999-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.struts.flow.core.javascript.fom;
+
+/**
+ * The exception thrown when the FOM classes can't find the necessary
+ * resource.
+ */
+public final class FOMResourceNotFoundException extends RuntimeException
+{
+ public FOMResourceNotFoundException(String message)
+ {
+ super(message);
+ }
+
+ public FOMResourceNotFoundException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+}
Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOMResourceNotFoundException.java
------------------------------------------------------------------------------
svn:executable = *
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_Flow.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_Flow.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_Flow.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_Flow.java Sat Nov 26 23:10:08 2005
@@ -0,0 +1,501 @@
+/*
+ * 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.javascript.fom;
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.struts.flow.Constants;
+
+//import org.apache.avalon.framework.context.Context;
+//import org.apache.avalon.framework.context.ContextException;
+//import org.apache.avalon.framework.logger.Logger;
+//import org.apache.avalon.framework.service.ServiceManager;
+//import org.apache.cocoon.components.ContextHelper;
+//import org.apache.cocoon.components.LifecycleHelper;
+import org.apache.struts.flow.core.ContinuationsManager;
+import org.apache.struts.flow.core.WebContinuation;
+import org.apache.struts.flow.core.javascript.ConversionHelper;
+import org.apache.struts.flow.core.Interpreter.Argument;
+//import org.apache.cocoon.environment.ObjectModelHelper;
+//import org.apache.cocoon.environment.Redirector;
+//import org.apache.cocoon.environment.Request;
+//import org.apache.cocoon.environment.Response;
+//import org.apache.cocoon.environment.Session;
+//import org.apache.cocoon.util.ClassUtils;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.NativeJavaClass;
+import org.mozilla.javascript.NativeJavaObject;
+import org.mozilla.javascript.Script;
+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;
+
+import org.apache.commons.chain.web.WebContext;
+import org.apache.struts.flow.core.Factory;
+import org.apache.struts.flow.core.Logger;
+
+/**
+ * Implementation of FOM (Flow Object Model).
+ *
+ * @since 2.1
+ * @author <a href="mailto:coliver.at.apache.org">Christopher Oliver</a>
+ * @author <a href="mailto:reinhard.at.apache.org">Reinhard P\u00F6tz</a>
+ * @version CVS $Id: FOM_Flow.java 292491 2005-09-29 17:44:16Z bloritsch $
+ */
+public class FOM_Flow extends ScriptableObject {
+
+ class CallContext {
+ CallContext caller;
+ FOM_JavaScriptInterpreter interpreter;
+ WebContext webctx;
+ Logger logger;
+ Scriptable context;
+ Scriptable parameters;
+ Scriptable log;
+ WebContinuation lastContinuation;
+ FOM_WebContinuation fwk;
+ PageLocalScopeImpl currentPageLocal;
+
+ public CallContext(CallContext caller,
+ FOM_JavaScriptInterpreter interp,
+ WebContext webctx,
+ Logger logger,
+ WebContinuation lastContinuation) {
+ this.caller = caller;
+ this.interpreter = interp;
+ this.webctx = webctx;
+ this.logger = logger;
+ this.lastContinuation = lastContinuation;
+ if (lastContinuation != null) {
+ fwk = new FOM_WebContinuation(lastContinuation);
+ Scriptable scope = FOM_Flow.this.getParentScope();
+ fwk.setParentScope(scope);
+ fwk.setPrototype(getClassPrototype(scope, fwk.getClassName()));
+ this.currentPageLocal = fwk.getPageLocal();
+ }
+ if (this.currentPageLocal != null) {
+ // "clone" the page local scope
+ this.currentPageLocal = this.currentPageLocal.duplicate();
+ } else {
+ this.currentPageLocal = new PageLocalScopeImpl(getTopLevelScope(FOM_Flow.this));
+ }
+ pageLocal.setDelegate(this.currentPageLocal);
+ }
+
+ public FOM_WebContinuation getLastContinuation() {
+ return fwk;
+ }
+
+ public void setLastContinuation(FOM_WebContinuation fwk) {
+ this.fwk = fwk;
+ if (fwk != null) {
+ pageLocal.setDelegate(fwk.getPageLocal());
+ this.lastContinuation = fwk.getWebContinuation();
+ } else {
+ this.lastContinuation = null;
+ }
+ }
+
+ public WebContext getWebContext() {
+ return webctx;
+ }
+
+ public Scriptable getContext() {
+ if (context != null) {
+ return context;
+ }
+ context = org.mozilla.javascript.Context.toObject(webctx, getParentScope());
+ return context;
+ }
+
+ public Scriptable getLog() {
+ if (log != null) {
+ return log;
+ }
+ log = org.mozilla.javascript.Context.toObject(logger, getParentScope());
+ return log;
+ }
+
+ public Scriptable getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(Scriptable parameters) {
+ this.parameters = parameters;
+ }
+ }
+
+ private CallContext currentCall;
+ protected PageLocalScopeHolder pageLocal;
+
+ public String getClassName() {
+ return "FOM_Flow";
+ }
+
+
+ // Called by FOM_JavaScriptInterpreter
+ static void init(Scriptable scope) throws Exception {
+ //FIXME(SW) what is the exact purpose of defineClass() ??
+ defineClass(scope, FOM_Flow.class);
+// defineClass(scope, FOM_Request.class);
+// defineClass(scope, FOM_Response.class);
+// defineClass(scope, FOM_Cookie.class);
+// defineClass(scope, FOM_Session.class);
+// defineClass(scope, FOM_Context.class);
+// defineClass(scope, FOM_Log.class);
+ defineClass(scope, FOM_WebContinuation.class);
+ defineClass(scope, PageLocalImpl.class);
+ }
+
+ void pushCallContext(FOM_JavaScriptInterpreter interp,
+ WebContext webctx,
+ Logger logger,
+ WebContinuation lastContinuation) {
+ if (pageLocal == null) {
+ pageLocal = new PageLocalScopeHolder(getTopLevelScope(this));
+ }
+
+ this.currentCall = new CallContext(currentCall, interp, webctx,
+ logger, lastContinuation);
+ }
+
+ void popCallContext() {
+ // Clear the scope attribute
+ //FOM_JavaScriptFlowHelper.setFOM_FlowScope(this.getObjectModel(), null);
+
+ this.currentCall = this.currentCall.caller;
+ // reset current page locals
+ if (this.currentCall != null) {
+ pageLocal.setDelegate(this.currentCall.currentPageLocal);
+ } else {
+ pageLocal.setDelegate(null);
+ }
+ }
+
+
+ public FOM_WebContinuation jsGet_continuation() {
+ // FIXME: This method can return invalid continuation! Is it OK to do so?
+ return currentCall.getLastContinuation();
+ }
+
+ public void jsSet_continuation(Object obj) {
+ FOM_WebContinuation fwk = (FOM_WebContinuation)ConversionHelper.jsobjectToObject(obj);
+ currentCall.setLastContinuation(fwk);
+ }
+
+ public FOM_WebContinuation jsFunction_forward(String uri,
+ Object obj,
+ Object wk)
+ throws Exception {
+
+ WebContext ctx = currentCall.getWebContext();
+ FOM_WebContinuation fom_wk = (FOM_WebContinuation)ConversionHelper.jsobjectToObject(wk);
+
+ if (fom_wk != null) {
+ // save page locals
+ fom_wk.setPageLocal(pageLocal.getDelegate());
+ ctx.put(Constants.CONTINUATION_ID_KEY, fom_wk.jsGet_id());
+ }
+
+ ctx.put(Constants.FORWARD_NAME_KEY, uri);
+ ctx.put(Constants.BIZ_DATA_KEY, ConversionHelper.jsobjectToObject(obj));
+ return fom_wk;
+ }
+
+ public Scriptable jsFunction_createPageLocal() {
+ return pageLocal.createPageLocal();
+ }
+
+/*
+
+ NOTE (SM): These are the hooks to the future FOM Event Model that will be
+ designed in the future. It has been postponed because we think
+ there are more important things to do at the moment, but these
+ are left here to indicate that they are planned.
+
+ public void jsFunction_addEventListener(String eventName,
+ Object function) {
+ // what is this?
+ }
+
+ public void jsFunction_removeEventListener(String eventName,
+ Object function) {
+ // what is this?
+ }
+
+*/
+
+
+ /**
+ * Load the script file specified as argument.
+ *
+ * @param filename a <code>String</code> value
+ * @return an <code>Object</code> value
+ * @exception JavaScriptException if an error occurs
+ */
+ public Object jsFunction_load( String filename )
+ throws Exception {
+ org.mozilla.javascript.Context cx =
+ org.mozilla.javascript.Context.getCurrentContext();
+ Scriptable scope = getParentScope();
+ Script script = getInterpreter().compileScript(cx, filename);
+ return script.exec( cx, scope );
+ }
+
+
+ /**
+ * Base JS wrapper for Cocoon's request/session/context objects.
+ * <p>
+ * FIXME(SW): The only thing added to the regular Java object is the fact that
+ * attributes can be accessed as properties. Do we want to keep this?
+ */
+ private static abstract class AttributeHolderJavaObject extends NativeJavaObject {
+
+ private static Map classProps = new HashMap();
+ private Set propNames;
+
+ public AttributeHolderJavaObject(Scriptable scope, Object object, Class clazz) {
+ super(scope, object, clazz);
+ this.propNames = getProperties(object.getClass());
+ }
+
+ /** Compute the names of JavaBean properties so that we can filter them our in get() */
+ private static Set getProperties(Class clazz) {
+ Set result = (Set)classProps.get(clazz);
+ if (result == null) {
+ try {
+ PropertyDescriptor[] descriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
+ result = new HashSet();
+ for (int i = 0; i < descriptors.length; i++) {
+ result.add(descriptors[i].getName());
+ }
+ } catch (IntrospectionException e) {
+ // Cannot introspect: just consider there are no properties
+ result = Collections.EMPTY_SET;
+ }
+ classProps.put(clazz, result);
+ }
+ return result;
+ }
+
+
+ protected abstract Enumeration getAttributeNames();
+ protected abstract Object getAttribute(String name);
+
+ public Object[] getIds() {
+ // Get class Ids
+ Object [] classIds = super.getIds();
+
+ // and add attribute names
+ ArrayList idList = new ArrayList(Arrays.asList(classIds));
+ Enumeration iter = getAttributeNames();
+ while(iter.hasMoreElements()) {
+ idList.add(iter.nextElement());
+ }
+ return idList.toArray();
+ }
+
+ public boolean has(String name, Scriptable start) {
+ return super.has(name, start) || getAttribute(name) != null;
+ }
+
+ public Object get(String name, Scriptable start) {
+ Object result;
+ // Filter out JavaBean properties. We only want methods of the underlying object.
+ if (this.propNames.contains(name)) {
+ result = NOT_FOUND;
+ } else {
+ result = super.get(name, start);
+ }
+ if (result == NOT_FOUND) {
+ result = getAttribute(name);
+ if (result != null) {
+ result = org.mozilla.javascript.Context.javaToJS(result, start);
+ } else {
+ result = NOT_FOUND;
+ }
+ }
+ return result;
+ }
+ }
+
+
+ public Scriptable jsGet_log() {
+ return currentCall.getLog();
+ }
+
+ public Scriptable jsGet_context() {
+ return currentCall.getContext();
+ }
+
+ /**
+ * Get Sitemap parameters
+ *
+ * @return a <code>Scriptable</code> value whose properties represent
+ * the Sitemap parameters from <map:call>
+ */
+ public Scriptable jsGet_parameters() {
+ return getParameters();
+ }
+
+ public Scriptable getParameters() {
+ return currentCall.getParameters();
+ }
+
+ void setParameters(Scriptable value) {
+ currentCall.setParameters(value);
+ }
+
+ /**
+ * Converts a JavaScript object to a HashMap
+ */
+ public Map jsFunction_jsobjectToMap(Scriptable jsobject) {
+ return ConversionHelper.jsobjectToMap(jsobject);
+ }
+
+ // Make everything available to JavaScript objects implemented in Java:
+
+ /**
+ * Get the current context
+ * @return The context
+ */
+ public WebContext getWebContext() {
+ return currentCall.webctx;
+ }
+
+ private Logger getLogger() {
+ return currentCall.logger;
+ }
+
+ private FOM_JavaScriptInterpreter getInterpreter() {
+ return currentCall.interpreter;
+ }
+
+ /**
+ * Required by FOM_WebContinuation. This way we do not make whole Interpreter public
+ * @return interpreter Id associated with this FOM.
+ */
+ public String getInterpreterId() {
+ return getInterpreter().getInterpreterID();
+ }
+
+ /**
+ * Perform the behavior of <map:call continuation="blah">
+ * This can be used in cases where the continuation id is not encoded
+ * in the request in a form convenient to access in the sitemap.
+ * Your script can extract the id from the request and then call
+ * this method to process it as normal.
+ * @param kontId The continuation id
+ * @param parameters Any parameters you want to pass to the continuation (may be null)
+ */
+ public void handleContinuation(String kontId, Scriptable parameters)
+ throws Exception {
+ List list = null;
+ if (parameters == null || parameters == Undefined.instance) {
+ parameters = getParameters();
+ }
+ Object[] ids = parameters.getIds();
+ list = new ArrayList();
+ for (int i = 0; i < ids.length; i++) {
+ String name = ids[i].toString();
+ Argument arg = new Argument(name,
+ org.mozilla.javascript.Context.toString(getProperty(parameters, name)));
+ list.add(arg);
+ }
+ getInterpreter().handleContinuation(kontId, list, this.currentCall.webctx);
+ }
+
+ /**
+ * Return this continuation if it is valid, or first valid parent
+ */
+ private FOM_WebContinuation findValidParent(FOM_WebContinuation wk) {
+ if (wk != null) {
+ WebContinuation wc = wk.getWebContinuation();
+ while (wc != null && wc.disposed()) {
+ wc = wc.getParentContinuation();
+ }
+ if (wc != null) {
+ return new FOM_WebContinuation(wc);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Create a Bookmark WebContinuation from a JS Continuation with the last
+ * continuation of sendPageAndWait as its parent.
+ * PageLocal variables will be shared with the continuation of
+ * the next call to sendPageAndWait().
+ * @param k The JS continuation
+ * @param ttl Lifetime for this continuation (zero means no limit)
+ */
+ public FOM_WebContinuation jsFunction_makeWebContinuation(Object k,
+ Object ttl)
+ throws Exception {
+ double d = org.mozilla.javascript.Context.toNumber(ttl);
+ FOM_WebContinuation result =
+ makeWebContinuation((Continuation)ConversionHelper.jsobjectToObject(k),
+ findValidParent(jsGet_continuation()),
+ (int)d);
+ result.setPageLocal(pageLocal.getDelegate());
+ currentCall.setLastContinuation(result);
+ return result;
+ }
+
+ /**
+ * Create a Web Continuation from a JS Continuation
+ * @param k The JS continuation (may be null - null will be returned in that case)
+ * @param parent The parent of this continuation (may be null)
+ * @param timeToLive Lifetime for this continuation (zero means no limit)
+ */
+ public FOM_WebContinuation makeWebContinuation(Continuation k,
+ FOM_WebContinuation parent,
+ int timeToLive)
+ throws Exception {
+ if (k == null) {
+ return null;
+ }
+ WebContinuation wk;
+ ContinuationsManager contMgr;
+ contMgr = Factory.getContinuationsManager();
+ wk = contMgr.createWebContinuation(ConversionHelper.jsobjectToObject(k),
+ (parent == null ? null : parent.getWebContinuation()),
+ timeToLive,
+ getInterpreter().getInterpreterID(),
+ null,
+ currentCall.getWebContext());
+ FOM_WebContinuation result = new FOM_WebContinuation(wk);
+ result.setParentScope(getParentScope());
+ result.setPrototype(getClassPrototype(getParentScope(),
+ result.getClassName()));
+ return result;
+ }
+}
Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_Flow.java
------------------------------------------------------------------------------
svn:executable = *
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_JavaScriptInterpreter.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_JavaScriptInterpreter.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_JavaScriptInterpreter.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_JavaScriptInterpreter.java Sat Nov 26 23:10:08 2005
@@ -0,0 +1,845 @@
+/*
+ * 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.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.*;
+import java.util.Map;
+
+import org.apache.struts.flow.core.Logger;
+import org.apache.struts.flow.core.Factory;
+
+import org.apache.commons.chain.web.WebContext;
+import java.lang.reflect.InvocationTargetException;
+//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;
+//mport org.apache.avalon.framework.service.ServiceManager;
+//mport org.apache.flow.ResourceNotFoundException;
+//mport org.apache.flow.components.ContextHelper;
+import org.apache.struts.flow.core.CompilingInterpreter;
+import org.apache.struts.flow.core.Interpreter;
+import org.apache.struts.flow.core.InvalidContinuationException;
+import org.apache.struts.flow.core.*;
+import org.apache.struts.flow.core.javascript.JSErrorReporter;
+import org.apache.struts.flow.core.javascript.LocationTrackingDebugger;
+//import org.apache.struts.flow.core.javascript.ScriptablePointerFactory;
+//import org.apache.struts.flow.core.javascript.ScriptablePropertyHandler;
+//import org.apache.flow.environment.ObjectModelHelper;
+//import org.apache.flow.environment.Redirector;
+//import org.apache.flow.environment.Request;
+//import org.apache.flow.environment.Session;
+//import org.apache.commons.jxpath.JXPathIntrospector;
+//import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
+import org.apache.struts.flow.core.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.WrapFactory;
+import org.mozilla.javascript.continuations.Continuation;
+import org.mozilla.javascript.tools.debugger.Main;
+import org.mozilla.javascript.tools.shell.Global;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+/**
+ * Interface with the JavaScript interpreter.
+ *
+ * @author <a href="mailto:ovidiu@apache.org">Ovidiu Predescu</a>
+ * @author <a href="mailto:crafterm@apache.org">Marcus Crafter</a>
+ * @since March 25, 2002
+ * @version CVS $Id: FOM_JavaScriptInterpreter.java 307410 2005-10-09 12:17:33Z reinhard $
+ */
+public class FOM_JavaScriptInterpreter extends CompilingInterpreter {
+
+ /**
+ * 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 <code>String</code> objects that represent files to be
+ * read in by the JavaScript interpreter.
+ */
+ private List topLevelScripts = new ArrayList();
+
+ private boolean enableDebugger;
+
+ private WrapFactory wrapFactory;
+ private List registrars = new ArrayList();
+
+ /**
+ * 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("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;
+ }
+
+ /**
+ * Gets the logger attribute of the JavaScriptInterpreter object
+ *
+ *@return The logger value
+ */
+ public Logger getLogger() {
+ return Factory.getLogger();
+ }
+
+ /**
+ * Sets the wrap factory to use with Rhino
+ *
+ *@param wf The WrapFactory instance
+ */
+ public void setWrapFactory(WrapFactory wf) {
+ this.wrapFactory = wf;
+ }
+
+ /**
+ * Adds a class that will register a global variable
+ *
+ * @param reg The variable registrar
+ */
+ public void addVariableRegistrar(VariableRegistrar reg) {
+ registrars.add(reg);
+ }
+
+ /**
+ * Removes a class that will register a global variable
+ *
+ * @param reg The variable registrar
+ */
+ public void removeVariableRegistrar(VariableRegistrar reg) {
+ registrars.remove(reg);
+ }
+
+
+ /**
+ * Sets the interval between when the script should be looked at to see if
+ * it needs to be reloaded
+ *
+ *@param time The interval time in milliseconds
+ */
+ public void setCheckTime(long time) {
+ checkTime = time;
+ }
+
+
+ /**
+ * Sets whether to enable the debugger
+ *
+ *@param val The new debugger value
+ */
+ public void setDebugger(boolean val) {
+ enableDebugger = val;
+ }
+
+
+ /**
+ * Sets whether to try to reload modified scripts or not
+ *
+ *@param val True to reload
+ */
+ public void setReloadScripts(boolean val) {
+ reloadScripts = val;
+ }
+
+ /**
+ * Initialize the global scope
+ *
+ *@exception FlowException If anything goes wrong
+ */
+ public void initialize() throws FlowException {
+ initialize(null);
+ }
+
+
+ /**
+ * Initialize the global scope
+ *
+ *@exception FlowException If anything goes wrong
+ */
+ public void initialize(List classes) throws FlowException {
+ 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);
+ if (wrapFactory != null) {
+ context.setWrapFactory(wrapFactory);
+ }
+
+ try {
+ scope = new Global(context);
+
+ // Register some handy classes with JavaScript, so we can make
+ // use of them from the flow layer.
+ initScope(context, scope);
+
+ // Register any custom classes
+ if (classes != null) {
+ for (Iterator i = classes.iterator(); i.hasNext(); ) {
+ ScriptableObject.defineClass(scope, (Class)i.next());
+ }
+ }
+
+ // Access to Cocoon internal objects
+ FOM_Flow.init(scope);
+ } catch (Exception e) {
+ Context.exit();
+ e.printStackTrace();
+ throw new FlowException(e);
+ }
+ }
+
+
+ /**
+ * Initialize the global scope
+ *
+ *@param context The context
+ *@param scope The scope to initialize
+ *@exception IllegalAccessException If anything goes wrong
+ *@exception InstantiationException If anything goes wrong
+ *@exception InvocationTargetException If anything goes wrong
+ *@exception JavaScriptException If anything goes wrong
+ */
+ protected void initScope(Context context, Global scope) throws IllegalAccessException,
+ InstantiationException, InvocationTargetException, JavaScriptException {
+
+ VariableRegistrar reg;
+ List lst;
+ for (Iterator i = registrars.iterator(); i.hasNext(); ) {
+ reg = (VariableRegistrar) i.next();
+ ScriptableObject.defineClass(scope, reg.getClassInstance());
+ }
+
+ // Define some global variables in JavaScript
+ Object args[] = {};
+
+ for (Iterator i = registrars.iterator(); i.hasNext(); ) {
+ reg = (VariableRegistrar) i.next();
+ if (!reg.isCallSpecific()) {
+ Scriptable var = context.newObject(scope, reg.getClassName(), args);
+ scope.put(reg.getName(), scope, reg.getInstance(scope, null));
+ }
+ }
+
+
+ }
+
+
+ /**
+ * Returns the JavaScript scope, a Scriptable object, from the user
+ * session instance. Each interpreter instance can have a scope
+ * associated with it.
+ *
+ * @return a <code>ThreadScope</code> value
+ */
+ private ThreadScope getSessionScope(WebContext ctx) throws Exception {
+ final String scopeID = USER_GLOBAL_SCOPE + getInterpreterID();
+
+ 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);
+ //}
+
+ // FIXME: This might create a unwanted session
+ scope = (ThreadScope) ctx.getSessionScope().get(scopeID);
+ if (scope == null) {
+ scope = (ThreadScope) ctx.getRequestScope().get(scopeID);
+ }
+
+
+ if (scope == null) {
+ scope = createThreadScope();
+ // Save scope in the request early to allow recursive Flow calls
+ ctx.getRequestScope().put(scopeID, scope);
+ }
+
+ return scope;
+ }
+
+ /**
+ * Associates a JavaScript scope, a Scriptable object, with
+ * {@link #getInterpreterID() identifier} of this {@link Interpreter}
+ * instance.
+ *
+ * @param scope a <code>ThreadScope</code> value
+ */
+ private void setSessionScope(ThreadScope scope, WebContext ctx) throws Exception {
+ if (scope.useSession) {
+ final String scopeID = USER_GLOBAL_SCOPE + getInterpreterID();
+
+ // FIXME: Where "session scope" should go when session is invalidated?
+ // Attach the scope to the current context
+ try {
+ ctx.getSessionScope().put(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_Flow for more details.
+ final Object[] args = {};
+ FOM_Flow flow = (FOM_Flow) context.newObject(this,
+ "FOM_Flow",
+ args);
+ flow.setParentScope(this);
+ super.put("flow", this, flow);
+
+ 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.
+ *
+ * <p>If you want to maintain the state of global variables across
+ * multiple invocations of <code><map:call
+ * function="..."></code>, you need to instanciate the session
+ * object which is a property of the flow object
+ * <code>var session = flow.session</code>. 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}.</p>
+ *
+ * @exception Exception if an error occurs
+ */
+ private void setupContext(WebContext webctx, 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
+ // flow.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_Flow flow = (FOM_Flow) thrScope.get("flow", 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_Flow object according to the current
+ // request. Everything else remains the same.
+ ClassLoader contextClassloader = Thread.currentThread().getContextClassLoader();
+ thrScope.setupPackages(contextClassloader);
+ flow.pushCallContext(this, webctx, getLogger(), null);
+
+ VariableRegistrar reg;
+ for (Iterator i = registrars.iterator(); i.hasNext(); ) {
+ reg = (VariableRegistrar) i.next();
+ if (reg.isCallSpecific()) {
+ WrapFactory factory = context.getWrapFactory();
+ Object o = reg.getInstance(thrScope, webctx);
+ if (o instanceof Scriptable) {
+ thrScope.put(reg.getName(), thrScope, (Scriptable)o);
+ } else {
+ Scriptable var = factory.wrapAsJavaObject(context, thrScope, o, reg.getClassInstance());
+ thrScope.put(reg.getName(), thrScope, var);
+ }
+ }
+ }
+
+ // 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 FlowException(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
+ Pattern encodingRE = Pattern.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");
+ Matcher re = encodingRE.matcher(str);
+ if (re.matches()) {
+ return re.group(1);
+ }
+ return null;
+ }
+
+ /**
+ * Calls a JavaScript function, passing <code>params</code> as its
+ * arguments. In addition to this, it makes available the parameters
+ * through the <code>flow.parameters</code> JavaScript array
+ * (indexed by the parameter names).
+ *
+ * @param funName a <code>String</code> value
+ * @param params a <code>List</code> value
+ * @param redirector
+ * @exception Exception if an error occurs
+ */
+ public Object callFunction(String funName, List params, WebContext webctx)
+ 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);
+ }
+ Object ret = null;
+ ThreadScope thrScope = getSessionScope(webctx);
+ synchronized (thrScope) {
+ ClassLoader savedClassLoader =
+ Thread.currentThread().getContextClassLoader();
+ FOM_Flow flow = null;
+ try {
+ try {
+ setupContext(webctx, context, thrScope);
+ flow = (FOM_Flow) thrScope.get("flow", thrScope);
+
+ // Register the current scope for scripts indirectly called from this function
+ //FOM_JavaScriptFlowHelper.setFOM_FlowScope(flow.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);
+ }
+ flow.setParameters(parameters);
+
+ Object fun = ScriptableObject.getProperty(thrScope, funName);
+ if (fun == Scriptable.NOT_FOUND) {
+ throw new FlowException("Function \"javascript:" + funName + "()\" not found");
+ }
+
+ thrScope.setLock(true);
+ ret = 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, webctx);
+ if (flow != null) {
+ flow.popCallContext();
+ }
+ Context.exit();
+ Thread.currentThread().setContextClassLoader(savedClassLoader);
+ }
+ }
+ return ret;
+ }
+
+ public void handleContinuation(String id, List params,
+ WebContext webctx) throws Exception
+ {
+ WebContinuation wk = continuationsMgr.lookupWebContinuation(id, getInterpreterID(), webctx);
+
+ if (wk == null) {
+ /*
+ * Throw an InvalidContinuationException to be handled inside the
+ * <map:handle-errors> 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_Flow 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_Flow flow = null;
+ try {
+ Thread.currentThread().setContextClassLoader(kScope.getClassLoader());
+ flow = (FOM_Flow)kScope.get("flow", kScope);
+ kScope.setLock(true);
+ flow.pushCallContext(this, webctx, getLogger(), wk);
+
+ // Register the current scope for scripts indirectly called from this function
+ //FOM_JavaScriptFlowHelper.setFOM_FlowScope(flow.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);
+ }
+ flow.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(flow,
+ "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, webctx);
+ if (flow != null) {
+ flow.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;
+ }
+}
Propchange: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_JavaScriptInterpreter.java
------------------------------------------------------------------------------
svn:executable = *
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_WebContinuation.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_WebContinuation.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_WebContinuation.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_WebContinuation.java Sat Nov 26 23:10:08 2005
@@ -0,0 +1,254 @@
+/*
+ * 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.javascript.fom;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.struts.flow.core.Factory;
+
+import org.apache.struts.flow.core.ContinuationsManager;
+import org.apache.struts.flow.core.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_Flow cocoon = (FOM_Flow)getProperty(scope, "flow");
+ ContinuationsManager contMgr = Factory.getContinuationsManager();
+ wk = contMgr.createWebContinuation(c,
+ (parent == null ? null : parent.getWebContinuation()),
+ timeToLive,
+ cocoon.getInterpreterId(),
+ null,
+ cocoon.getWebContext());
+ 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_Flow cocoon =
+ (FOM_Flow)getProperty(getTopLevelScope(this), "flow");
+ contMgr = Factory.getContinuationsManager();
+ contMgr.invalidateWebContinuation(wk, cocoon.getWebContext());
+ }
+
+ 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: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/FOM_WebContinuation.java
------------------------------------------------------------------------------
svn:executable = *
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocal.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocal.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocal.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocal.java Sat Nov 26 23:10:08 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.struts.flow.core.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: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocal.java
------------------------------------------------------------------------------
svn:executable = *
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocalImpl.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocalImpl.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocalImpl.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocalImpl.java Sat Nov 26 23:10:08 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.struts.flow.core.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: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocalImpl.java
------------------------------------------------------------------------------
svn:executable = *
Added: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocalScope.java
URL: http://svn.apache.org/viewcvs/struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocalScope.java?rev=349187&view=auto
==============================================================================
--- struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocalScope.java (added)
+++ struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocalScope.java Sat Nov 26 23:10:08 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.struts.flow.core.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: struts/flow/trunk/src/java/org/apache/struts/flow/core/javascript/fom/PageLocalScope.java
------------------------------------------------------------------------------
svn:executable = *
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org