You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by st...@apache.org on 2004/06/24 18:48:54 UTC
cvs commit: cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/javascript JavaScriptFlowTestCase.java JavaScriptFlowTestCase.xtest
stephan 2004/06/24 09:48:54
Modified: src/blocks/javaflow/java/org/apache/cocoon/components/flow/java
AbstractContinuable.java
ContinuationClassLoader.java JavaInterpreter.java
src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/analyser
Subroutines.java
src/blocks/javaflow/test/org/apache/cocoon/components/flow/java/test
JavaFlowTestCase.java JavaFlowTestCase.xtest
SimpleFlow.java
src/blocks/javaflow/test/org/apache/cocoon/components/flow/javascript
JavaScriptFlowTestCase.java
JavaScriptFlowTestCase.xtest
Added: src/blocks/javaflow/java/org/apache/cocoon/components/flow/java
DecompilingVisitor.java
src/blocks/javaflow/java/org/apache/cocoon/components/flow/javascript
JavaScriptHelper.java JavaScriptInterpreter.java
ScriptHelper.java
Log:
Using a "ScriptHelper" to encapsulate the instrumented JavaScript interpreter.
Add a decompiler to debug the bytecode based on Torsten's work.
The current problem is the usage of "xxx.class", which were
translated to "Class.forName("..")".
Revision Changes Path
1.6 +16 -1 cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/AbstractContinuable.java
Index: AbstractContinuable.java
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/AbstractContinuable.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- AbstractContinuable.java 23 Jun 2004 09:16:31 -0000 1.5
+++ AbstractContinuable.java 24 Jun 2004 16:48:53 -0000 1.6
@@ -16,11 +16,14 @@
package org.apache.cocoon.components.flow.java;
import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceManager;
import org.apache.cocoon.components.ContextHelper;
import org.apache.cocoon.components.flow.FlowHelper;
import org.apache.cocoon.components.flow.util.PipelineUtil;
+import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Request;
import org.apache.excalibur.source.SourceUtil;
@@ -44,6 +47,18 @@
public Logger getLogger() {
return getContext().getLogger();
+ }
+
+ public Context getAvalonContext() {
+ return getContext().getAvalonContext();
+ }
+
+ public ServiceManager getServiceManager() {
+ return getContext().getServiceManager();
+ }
+
+ public Redirector getRedirector() {
+ return getContext().getRedirector();
}
public void sendPageAndWait(String uri) {
1.11 +68 -13 cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/ContinuationClassLoader.java
Index: ContinuationClassLoader.java
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/ContinuationClassLoader.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- ContinuationClassLoader.java 14 Jun 2004 15:08:35 -0000 1.10
+++ ContinuationClassLoader.java 24 Jun 2004 16:48:53 -0000 1.11
@@ -15,6 +15,7 @@
*/
package org.apache.cocoon.components.flow.java;
+import java.io.FileOutputStream;
import java.util.*;
import org.apache.bcel.*;
@@ -57,6 +58,8 @@
private static boolean currentMethodStatic;
+ private boolean debug = false;
+
private List includes = new ArrayList();
public ContinuationClassLoader(ClassLoader parent) {
@@ -64,6 +67,10 @@
Repository.setRepository(new ClassLoaderRepository(parent));
}
+ public void setDebug(boolean debug) {
+ this.debug = debug;
+ }
+
public void addIncludeClass(String pattern) {
StringBuffer buffer = new StringBuffer();
@@ -106,12 +113,16 @@
protected synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
// this finds also classes, which are already transformed, via findLoadedClass
+ if (debug)
+ System.out.println("load class "+name);
Class c = super.loadClass(name, resolve);
// transform class if class is continuable and not continuation capable
if (isContinuable(c) &&
(!ContinuationCapable.class.isAssignableFrom(c)) &&
(!c.isInterface())) {
+ if (debug)
+ System.out.println("instrument class "+name);
JavaClass clazz = Repository.lookupClass(c);
byte data[] = transform(clazz);
@@ -127,9 +138,21 @@
}
private byte[] transform(JavaClass javaclazz) throws ClassNotFoundException {
+
// make all methods of java class continuable
ClassGen clazz = new ClassGen(javaclazz);
ConstantPoolGen cp = clazz.getConstantPool();
+
+ if (debug) {
+ try {
+ FileOutputStream fos = new FileOutputStream(javaclazz.getClassName() + ".orig.j");
+ DecompilingVisitor v = new DecompilingVisitor(javaclazz, fos);
+ v.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
// vistor to build the frame information
ExecutionVisitor ev = new ExecutionVisitor();
ev.setConstantPoolGen(cp);
@@ -144,11 +167,13 @@
// information about every instruction
ControlFlowGraph cfg = new ControlFlowGraph(method);
- //System.out.println("analyse " + methods[i].getName());
+ if (debug)
+ System.out.println("analyse " + methods[i].getName());
analyse(clazz, method, cfg, ev);
// add intercepting code
- //System.out.println("rewriting " + methods[i].getName());
+ if (debug)
+ System.out.println("rewriting " + methods[i].getName());
rewrite(method, cfg);
// make last optional check for consistency
@@ -168,15 +193,25 @@
}
}
- /*byte[] changed = clazz.getJavaClass().getBytes();
- try {
- java.io.FileOutputStream out = new java.io.FileOutputStream(clazz.getClassName() + ".rewritten.class");
- out.write(changed);
- out.flush();
- out.close();
- } catch (java.io.IOException ioe) {
- ioe.printStackTrace();
- }*/
+ if (debug) {
+ byte[] changed = clazz.getJavaClass().getBytes();
+ try {
+ FileOutputStream out = new FileOutputStream(clazz.getClassName() + ".rewritten.class");
+ out.write(changed);
+ out.flush();
+ out.close();
+ } catch (java.io.IOException ioe) {
+ ioe.printStackTrace();
+ }
+
+ try {
+ FileOutputStream fos = new FileOutputStream(clazz.getClassName() + ".rewritten.j");
+ DecompilingVisitor v = new DecompilingVisitor(clazz.getJavaClass(), fos);
+ v.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
clazz.addInterface(CONTINUATIONCAPABLE_CLASS);
return clazz.getJavaClass().getBytes();
@@ -417,6 +452,8 @@
insList.insert(InstructionFactory.createLoad(STACK_TYPE, method.getMaxLocals()+1));
// test if the continuation should be restored
+ if (debug)
+ insList.insert(insFactory.createPrintln("restoring invocation "+method));
insList.insert(new IFEQ(firstIns));
insList.insert(insFactory.createInvoke(CONTINUATION_CLASS, RESTORING_METHOD, Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
insList.insert(InstructionFactory.createLoad(CONTINUATION_TYPE, method.getMaxLocals()));
@@ -541,6 +578,8 @@
boolean skipFirst = returnType.getSize() > 0;
// save stack
+ if (debug)
+ insList.append(insFactory.createPrintln("save stack"));
OperandStack os = frame.getStack();
for (int i = skipFirst ? 1 : 0; i < os.size(); i++) {
Type type = os.peek(i);
@@ -572,15 +611,24 @@
insList.append(insFactory.createInvoke(STACK_CLASS, getPushMethod(Type.OBJECT), Type.VOID, new Type[]{Type.OBJECT}, Constants.INVOKEVIRTUAL));
}
}
+
// add isCapturing test
+ if (debug)
+ insList.insert(insFactory.createPrintln("capturing invocation "+method));
insList.insert(new IFEQ(handle.getNext()));
+
// test if the continuation should be captured after the invocation
insList.insert(insFactory.createInvoke(CONTINUATION_CLASS, CAPURING_METHOD, Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
insList.insert(InstructionFactory.createLoad(CONTINUATION_TYPE, method.getMaxLocals()));
+
// test if continuation exists
insList.insert(new IFNULL(handle.getNext()));
insList.insert(InstructionFactory.createLoad(CONTINUATION_TYPE, method.getMaxLocals()));
+
// save local variables
+ if (debug)
+ insList.append(insFactory.createPrintln("save local variables"));
+
LocalVariables lvs = frame.getLocals();
for (int i = 0; i < lvs.maxLocals(); i++) {
Type type = lvs.get(i);
@@ -619,7 +667,11 @@
private InstructionList restoreFrame(MethodGen method, InstructionHandle handle,
InstructionFactory insFactory, Frame frame, ObjectType objecttype) {
InstructionList insList = new InstructionList();
+
// restore local variables
+ if (debug)
+ insList.append(insFactory.createPrintln("restore local variables"));
+
LocalVariables lvs = frame.getLocals();
for (int i = lvs.maxLocals() - 1; i >= 0; i--) {
Type type = lvs.get(i);
@@ -649,8 +701,11 @@
InvokeInstruction inv = (InvokeInstruction) handle.getInstruction();
Type returnType = getReturnType(method.getConstantPool().getConstantPool(), inv.getIndex());
boolean skipFirst = returnType.getSize() > 0;
-
+
// restore stack
+ if (debug)
+ insList.append(insFactory.createPrintln("restore stack"));
+
OperandStack os = frame.getStack();
for (int i = os.size() - 1; i >= (skipFirst ? 1 : 0); i--) {
Type type = os.peek(i);
1.10 +2 -1 cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java
Index: JavaInterpreter.java
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- JavaInterpreter.java 23 Jun 2004 09:16:32 -0000 1.9
+++ JavaInterpreter.java 24 Jun 2004 16:48:53 -0000 1.10
@@ -77,6 +77,7 @@
throw new ConfigurationException(e.getMessage());
}
continuationclassloader = new ContinuationClassLoader(javascriptclassloader);
+ continuationclassloader.setDebug(config.getAttributeAsBoolean("debug", false));
Configuration[] includes = config.getChildren("include");
for (int i = 0; i < includes.length; i++)
1.1 cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/DecompilingVisitor.java
Index: DecompilingVisitor.java
===================================================================
/*
* 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.java;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Hashtable;
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.ConstantValue;
import org.apache.bcel.classfile.Deprecated;
import org.apache.bcel.classfile.ExceptionTable;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Synthetic;
import org.apache.bcel.classfile.Utility;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.CodeExceptionGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LocalVariableGen;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.Select;
import org.apache.bcel.generic.TABLESWITCH;
public final class DecompilingVisitor extends org.apache.bcel.classfile.EmptyVisitor {
private JavaClass clazz;
private PrintWriter out;
private String clazzname;
private ConstantPoolGen cp;
public DecompilingVisitor(JavaClass clazz, OutputStream out) {
this.clazz = clazz;
this.out = new PrintWriter(out);
clazzname = clazz.getClassName();
cp = new ConstantPoolGen(clazz.getConstantPool());
}
public void start() {
new org.apache.bcel.classfile.DescendingVisitor(clazz, this).visit();
out.close();
}
public void visitJavaClass(JavaClass clazz) {
out.println("// source " + clazz.getSourceFileName());
out.println(Utility.accessToString(clazz.getAccessFlags(), true) + " "
+ Utility.classOrInterface(clazz.getAccessFlags()) + " "
+ clazz.getClassName().replace('.', '/'));
out.println(" extends " + clazz.getSuperclassName().replace('.', '/'));
String[] interfaces = clazz.getInterfaceNames();
if (interfaces.length > 0) {
out.print(" implements");
for (int i = 0; i < interfaces.length; i++)
out.print(" " + interfaces[i].replace('.', '/'));
out.println();
}
out.println();
}
public void visitField(Field field) {
out.print(" " + Utility.accessToString(field.getAccessFlags()) + " "
+ field.getName() + " " + field.getSignature());
if (field.getAttributes().length == 0)
out.print("\n");
}
public void visitConstantValue(ConstantValue cv) {
out.println(" = " + cv);
}
private Method _method;
/**
* Unfortunately Jasmin expects ".end method" after each method. Thus we've
* to check for every of the method's attributes if it's the last one and
* print ".end method" then.
*/
private final void printEndMethod(Attribute attr) {
Attribute[] attributes = _method.getAttributes();
}
public void visitDeprecated(Deprecated attribute) {
printEndMethod(attribute);
}
public void visitSynthetic(Synthetic attribute) {
if (_method != null)
printEndMethod(attribute);
}
public void visitMethod(Method method) {
this._method = method; // Remember for use in subsequent visitXXX calls
out.println("\n " + Utility.accessToString(_method.getAccessFlags())
+ " " + _method.getName() + _method.getSignature());
}
public void visitExceptionTable(ExceptionTable e) {
String[] names = e.getExceptionNames();
for (int i = 0; i < names.length; i++)
out.println(" throws " + names[i].replace('.', '/'));
printEndMethod(e);
}
private Hashtable map;
public void visitCode(Code code) {
int label_counter = 0;
MethodGen mg = new MethodGen(_method, clazzname, cp);
InstructionList il = mg.getInstructionList();
InstructionHandle[] ihs = il.getInstructionHandles();
LocalVariableGen[] lvs = mg.getLocalVariables();
CodeExceptionGen[] ehs = mg.getExceptionHandlers();
for (int i = 0; i < lvs.length; i++) {
LocalVariableGen l = lvs[i];
out.println(" // var " + l.getIndex() + " is \"" + l.getName()
+ "\" " + l.getType().getSignature() + " from "
+ l.getStart().getPosition() + " to "
+ l.getEnd().getPosition());
}
out.print("\n");
for (int i = 0; i < ihs.length; i++) {
InstructionHandle ih = ihs[i];
Instruction inst = ih.getInstruction();
out.print(" " + ih.getPosition());
if (inst instanceof BranchInstruction) {
if (inst instanceof Select) { // Special cases LOOKUPSWITCH and
// TABLESWITCH
Select s = (Select) inst;
int[] matchs = s.getMatchs();
InstructionHandle[] targets = s.getTargets();
if (s instanceof TABLESWITCH) {
out.println(" tableswitch " + matchs[0] + " "
+ matchs[matchs.length - 1]);
for (int j = 0; j < targets.length; j++)
out.println(" " + targets[j].getPosition());
} else { // LOOKUPSWITCH
out.println(" lookupswitch ");
for (int j = 0; j < targets.length; j++)
out.println(" " + matchs[j] + " : "
+ targets[j].getPosition());
}
out.println(" default: " + s.getTarget()); // Applies
// for
// both
} else {
BranchInstruction bi = (BranchInstruction) inst;
ih = bi.getTarget();
//str = get(ih);
out.println(" " + Constants.OPCODE_NAMES[bi.getOpcode()]
+ " " + ih);
}
} else
out.println(" " + inst.toString(cp.getConstantPool()));
}
out.print("\n");
for (int i = 0; i < ehs.length; i++) {
CodeExceptionGen c = ehs[i];
ObjectType caught = c.getCatchType();
String class_name = (caught == null) ? // catch any exception, used
// when compiling finally
"all" : caught.getClassName().replace('.', '/');
out.println(" catch " + class_name + " from "
+ c.getStartPC().getPosition() + " to "
+ c.getEndPC().getPosition() + " using "
+ c.getHandlerPC().getPosition());
}
printEndMethod(code);
}
}
1.2 +3 -3 cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/analyser/Subroutines.java
Index: Subroutines.java
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/analyser/Subroutines.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Subroutines.java 3 Jun 2004 12:43:27 -0000 1.1
+++ Subroutines.java 24 Jun 2004 16:48:53 -0000 1.2
@@ -449,7 +449,7 @@
// Now make sure no instruction of a Subroutine is protected by exception handling code
// as is mandated by JustIces notion of subroutines.
- for (int i=0; i<handlers.length; i++){
+ /*for (int i=0; i<handlers.length; i++){
InstructionHandle _protected = handlers[i].getStartPC();
while (_protected != handlers[i].getEndPC().getNext()){// Note the inclusive/inclusive notation of "generic API" exception handlers!
Enumeration subs = subroutines.elements();
@@ -463,7 +463,7 @@
}
_protected = _protected.getNext();
}
- }
+ }*/
// Now make sure no subroutine is calling a subroutine
// that uses the same local variable for the RET as themselves
1.1 cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/javascript/JavaScriptHelper.java
Index: JavaScriptHelper.java
===================================================================
/*
* 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;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.ResourceNotFoundException;
import org.apache.cocoon.components.flow.Interpreter;
import org.apache.cocoon.components.flow.java.AbstractContinuable;
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.excalibur.source.SourceResolver;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.EcmaError;
import org.mozilla.javascript.EvaluatorException;
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.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Wrapper;
import org.mozilla.javascript.tools.ToolErrorReporter;
import org.mozilla.javascript.tools.shell.Global;
/**
* 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: JavaScriptHelper.java,v 1.1 2004/06/24 16:48:53 stephan Exp $
*/
public class JavaScriptHelper extends AbstractContinuable
implements ScriptHelper {
/**
* List of source locations that need to be resolved.
*/
protected ArrayList needResolve = new ArrayList();
/**
* Whether reloading of scripts should be done. Specified through
* the "reload-scripts" attribute in <code>flow.xmap</code>.
*/
protected boolean reloadScripts;
/**
* Interval between two checks for modified script files. Specified
* through the "check-time" XML attribute in <code>flow.xmap</code>.
*/
protected long checkTime;
/** A source resolver */
protected SourceResolver sourceresolver;
/**
* Mapping of String objects (source uri's) to ScriptSourceEntry's
*/
//protected Map compiledScripts = new HashMap();
/**
* LAST_EXEC_TIME
* 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__";
/**
* Key for storing a JavaScript global scope object in the Cocoon session
*/
public 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
public static int OPTIMIZATION_LEVEL = -2;
/**
* When was the last time we checked for script modifications. Used
* only if {@link #reloadScripts} is true.
*/
protected long lastTimeCheck = 0;
/**
* 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 JSErrorReporter errorReporter;
private boolean enableDebugger = false;
/**
* Registers a source file with the interpreter. Using this method
* an implementation keeps track of all the script files which are
* compiled. This allows them to reload the script files which get
* modified on the file system.
*
* <p>The parsing/compilation of a script file by an interpreter
* happens in two phases. In the first phase the file's location is
* registered in the <code>needResolve</code> array.
*
* <p>The second is possible only when a Cocoon
* <code>Environment</code> is passed to the Interpreter. This
* allows the file location to be resolved using Cocoon's
* <code>SourceFactory</code> class.
*
* <p>Once a file's location can be resolved, it is removed from the
* <code>needResolve</code> array and placed in the
* <code>scripts</code> hash table. The key in this hash table is
* the file location string, and the value is a
* DelayedRefreshSourceWrapper instance which keeps track of when
* the file needs to re-read.
*
* @param source the location of the script
*
* @see org.apache.cocoon.environment.Environment
* @see org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper
*/
public void register(String source)
{
synchronized(this) {
needResolve.add(source);
}
}
public void configure(Configuration config) throws ConfigurationException {
reloadScripts = config.getChild("reload-scripts").getValueAsBoolean(false);
checkTime = config.getChild("check-time").getValueAsLong(1000L);
String loadOnStartup
= config.getChild("load-on-startup", true).getValue(null);
if (loadOnStartup != null) {
register(loadOnStartup);
}
String debugger = config.getChild("debugger").getValue(null);
if ("enabled".equalsIgnoreCase(debugger)) {
enableDebugger = true;
}
}
public void initialize() throws Exception {
if (enableDebugger) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Flow debugger enabled, creating");
}
}
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
errorReporter = new JSErrorReporter(getLogger());
} catch (Exception e) {
Context.exit();
e.printStackTrace();
throw e;
}
}
/**
* Returns the JavaScript scope, a Scriptable object, from the user
* session instance. Each sitemap can have a scope associated with it.
*
* @return a <code>Scriptable</code> value
*/
private ThreadScope getSessionScope() throws Exception {
Request request = getRequest();
ThreadScope scope = null;
Session session = request.getSession(false);
if (session != null) {
HashMap userScopes =
(HashMap)session.getAttribute(USER_GLOBAL_SCOPE);
if (userScopes != null) {
// Get the scope attached to the current context
scope = (ThreadScope)userScopes.get(getSitemapPath());
}
}
if (scope == null) {
scope = createThreadScope();
}
return scope;
}
void updateSession(Scriptable scope) throws Exception {
ThreadScope thrScope = (ThreadScope)scope;
if (thrScope.useSession) {
setSessionScope(scope);
}
}
/**
* Associates a JavaScript scope, a Scriptable object, with the
* directory path of the current sitemap, as resolved by the
* source resolver.
*
* @param scope a <code>Scriptable</code> value
*/
private Scriptable setSessionScope(Scriptable scope) throws Exception {
Request request = getRequest();
// FIXME: Where "session scope" should go when session is invalidated?
try {
Session session = request.getSession(true);
HashMap userScopes = (HashMap)session.getAttribute(USER_GLOBAL_SCOPE);
if (userScopes == null) {
userScopes = new HashMap();
session.setAttribute(USER_GLOBAL_SCOPE, userScopes);
}
// Attach the scope to the current context
userScopes.put(getSitemapPath(), scope);
} catch (IllegalStateException e) {
// Session might be invalidated already.
if (getLogger().isDebugEnabled()) {
getLogger().debug("Got '" + e + "' while trying to set session scope.", e);
}
}
return scope;
}
private String getSitemapPath() throws Exception {
Source src = this.sourceresolver.resolveURI(".");
try {
return src.getURI();
} finally {
this.sourceresolver.release(src);
}
}
public static class ThreadScope extends ScriptableObject {
static final String[] builtinPackages = {"javax", "org", "com"};
ClassLoader classLoader;
/* true if this scope has assigned any global vars */
boolean useSession = false;
public ThreadScope() {
final String[] names = { "importClass"};
try {
this.defineFunctionProperties(names, ThreadScope.class,
ScriptableObject.DONTENUM);
} catch (PropertyException e) {
throw new Error(); // should never happen
}
}
public String getClassName() {
return "ThreadScope";
}
public void put(String name, Scriptable start, Object value) {
useSession = true;
super.put(name, start, value);
}
public void put(int index, Scriptable start, Object value) {
useSession = true;
super.put(index, start, value);
}
void reset() {
useSession = false;
}
// Override importClass to allow reloading of classes
public static void importClass(Context cx, Scriptable thisObj,
Object[] args, Function funObj) {
for (int i = 0; i < args.length; i++) {
Object cl = args[i];
if (!(cl instanceof NativeJavaClass)) {
throw Context.reportRuntimeError("Not a Java class: " +
Context.toString(cl));
}
String s = ((NativeJavaClass) cl).getClassObject().getName();
String n = s.substring(s.lastIndexOf('.')+1);
thisObj.put(n, thisObj, cl);
}
}
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 < builtinPackages.length; i++) {
String pkgName = builtinPackages[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 {
Context context = Context.getCurrentContext();
ThreadScope thrScope = new ThreadScope();
thrScope.setPrototype(scope);
// We want 'thrScope' 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 "thrScope".
thrScope.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.
Object[] args = {};
thrScope.defineProperty(LAST_EXEC_TIME,
new Long(0),
ScriptableObject.DONTENUM | ScriptableObject.PERMANENT);
thrScope.reset();
return thrScope;
}
/**
* 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 cocoon object
* <code>var session = cocoon.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(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.
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.
//Thread.currentThread().setContextClassLoader(classLoader);
//thrScope.setupPackages(classLoader);
// 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.put(LAST_EXEC_TIME, thrScope,
new Long(System.currentTimeMillis()));
thrScope.reset();
}
}
}*/
}
/**
* 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;
}
} else {
throw new ResourceNotFoundException(fileName + ": not found");
}
}*/
/*protected Script compileScript(Context cx, Scriptable scope, Source src)
throws Exception {
InputStream is = src.getInputStream();
if (is != null) {
try {
Reader reader = new BufferedReader(new InputStreamReader(is));
Script compiledScript = cx.compileReader(scope, reader,
src.getURI(), 1, null);
return compiledScript;
} finally {
is.close();
}
} else {
throw new ResourceNotFoundException(src.getURI() + ": not found");
}
}*/
/**
* Calls a JavaScript function, passing <code>params</code> as its
* arguments. In addition to this, it makes available the parameters
* through the <code>cocoon.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 void callFunction(String funName, List params) throws Exception {
Context context = Context.enter();
context.setOptimizationLevel(OPTIMIZATION_LEVEL);
context.setGeneratingDebug(true);
context.setCompileFunctionsWithDynamicScope(true);
context.setErrorReporter(errorReporter);
ThreadScope thrScope = getSessionScope();
synchronized (thrScope) {
ClassLoader savedClassLoader =
Thread.currentThread().getContextClassLoader();
try {
try {
setupContext(getRedirector(), context, thrScope);
int size = (params != null ? params.size() : 0);
Object[] funArgs = new Object[size];
Scriptable parameters = context.newObject(thrScope);
for (int i = 0; i < size; i++) {
Interpreter.Argument arg = (Interpreter.Argument)params.get(i);
funArgs[i] = arg.value;
if (arg.name == null) {
arg.name = "";
}
parameters.put(arg.name, parameters, arg.value);
}
Object fun = ScriptableObject.getProperty(thrScope, funName);
if (fun == Scriptable.NOT_FOUND) {
throw new ResourceNotFoundException("Function \"javascript:" + funName + "()\" not found");
}
ScriptRuntime.call(context, fun, thrScope, funArgs, thrScope);
} catch (JavaScriptException ex) {
EvaluatorException ee = Context.reportRuntimeError(
ToolErrorReporter.getMessage("msg.uncaughtJSException",
ex.getMessage()));
Throwable unwrapped = unwrap(ex);
if (unwrapped instanceof ProcessingException) {
throw (ProcessingException)unwrapped;
}
throw new CascadingRuntimeException(ee.getMessage(),
unwrapped);
} catch (EcmaError ee) {
String msg = ToolErrorReporter.getMessage("msg.uncaughtJSException", ee.toString());
if (ee.getSourceName() != null) {
Context.reportRuntimeError(msg, ee.getSourceName(),
ee.getLineNumber(), ee.getLineSource(),
ee.getColumnNumber());
} else {
Context.reportRuntimeError(msg);
}
throw new CascadingRuntimeException(ee.getMessage(), ee);
}
} finally {
updateSession(thrScope);
Context.exit();
Thread.currentThread().setContextClassLoader(savedClassLoader);
}
}
}
/*public void handleContinuation(String id, List params,
Redirector redirector) throws Exception
{
WebContinuation wk = continuationsMgr.lookupWebContinuation(id);
if (wk == null) {
throw new InvalidContinuationException("The continuation ID " + id + " is invalid.");
}
Context context = Context.enter();
context.setOptimizationLevel(OPTIMIZATION_LEVEL);
context.setGeneratingDebug(true);
context.setCompileFunctionsWithDynamicScope(true);
// 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);
cocoon.pushCallContext(this, redirector, getServiceManager(),
getAvalonContext(),
getLogger(), wk);
// Register the current scope for scripts indirectly called from this function
FOM_JavaScriptFlowHelper.setFOM_FlowScope(cocoon.getObjectModel(), kScope);
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) {
EvaluatorException ee = Context.reportRuntimeError(
ToolErrorReporter.getMessage("msg.uncaughtJSException",
ex.getMessage()));
Throwable unwrapped = unwrap(ex);
if (unwrapped instanceof ProcessingException) {
throw (ProcessingException)unwrapped;
}
throw new CascadingRuntimeException(ee.getMessage(),
unwrapped);
} catch (EcmaError ee) {
String msg = ToolErrorReporter.getMessage("msg.uncaughtJSException", ee.toString());
if (ee.getSourceName() != null) {
Context.reportRuntimeError(msg, ee.getSourceName(),
ee.getLineNumber(), ee.getLineSource(),
ee.getColumnNumber());
} else {
Context.reportRuntimeError(msg);
}
throw new CascadingRuntimeException(ee.getMessage(), ee);
}
} finally {
updateSession(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;
}
/*private void setupView(Scriptable scope, FOM_Cocoon cocoon, FOM_WebContinuation kont) {
Map objectModel = ContextHelper.getObjectModel(getAvalonContext());
// Make the JS live-connect objects available to the view layer
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);
}
}*/
/*protected class ScriptSourceEntry {
final private Source source;
private Script script;
private long compileTime;
public ScriptSourceEntry(Source source) {
this.source = source;
}
public ScriptSourceEntry(Source source, Script script, long t) {
this.source = source;
this.script = script;
this.compileTime = t;
}
public Source getSource() {
return source;
}
public Script getScript(Context context, Scriptable scope,
boolean refresh, JavaScriptHelper interpreter)
throws Exception {
if (refresh) {
source.refresh();
}
if (script == null || compileTime < source.getLastModified()) {
script = interpreter.compileScript(context, scope, source);
compileTime = source.getLastModified();
}
return script;
}
}*/
}
1.1 cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/javascript/JavaScriptInterpreter.java
Index: JavaScriptInterpreter.java
===================================================================
/*
* 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;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
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.parameters.Parameters;
import org.apache.cocoon.components.ContextHelper;
import org.apache.cocoon.components.flow.AbstractInterpreter;
import org.apache.cocoon.components.flow.FlowHelper;
import org.apache.cocoon.components.flow.InvalidContinuationException;
import org.apache.cocoon.components.flow.WebContinuation;
import org.apache.cocoon.components.flow.java.Continuation;
import org.apache.cocoon.components.flow.java.ContinuationClassLoader;
import org.apache.cocoon.components.flow.java.ContinuationContext;
import org.apache.cocoon.components.flow.java.VarMap;
import org.apache.cocoon.components.flow.java.VarMapHandler;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Session;
import org.apache.commons.jxpath.JXPathIntrospector;
/**
* Implementation of the java flow interpreter.
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
* @version CVS $Id: JavaScriptInterpreter.java,v 1.1 2004/06/24 16:48:53 stephan Exp $
*/
public class JavaScriptInterpreter extends AbstractInterpreter implements Configurable {
private boolean initialized = false;
private int timeToLive = 600000;
/**
* Key for storing a global scope object in the Cocoon session
*/
public static final String USER_GLOBAL_SCOPE = "JAVASCRIPT GLOBAL SCOPE";
private ContinuationClassLoader continuationclassloader;
private Configuration configuration;
static {
JXPathIntrospector.registerDynamicClass(VarMap.class, VarMapHandler.class);
}
public void configure(Configuration config) throws ConfigurationException {
super.configure(config);
continuationclassloader = new ContinuationClassLoader(Thread.currentThread().getContextClassLoader());
continuationclassloader.setDebug(config.getAttributeAsBoolean("debug", false));
Configuration[] includes = config.getChildren("include");
for (int i = 0; i < includes.length; i++)
continuationclassloader.addIncludeClass(includes[i].getAttribute("class"));
this.configuration = config;
}
public ScriptHelper getScriptHelper() throws Exception {
ScriptHelper flow = (ScriptHelper)continuationclassloader
.loadClass("org.apache.cocoon.components.flow.javascript.JavaScriptHelper").newInstance();
for (Iterator scripts = needResolve.iterator(); scripts.hasNext();) {
String name = (String) scripts.next();
flow.register(name);
}
flow.configure(configuration);
flow.initialize();
return flow;
}
/**
* Calls a Java function, passing <code>params</code> as its
* arguments. In addition to this, it makes available the parameters
* through the <code>cocoon.parameters</code> Java array
* (indexed by the parameter names).
*
* @param function a <code>String</code> value
* @param params a <code>List</code> value
* @param redirector
* @exception Exception if an error occurs
*/
public void callFunction(String function, List params, Redirector redirector) throws Exception {
if (getLogger().isDebugEnabled())
getLogger().debug("calling function \"" + function + "\"");
Request request = ContextHelper.getRequest(this.avalonContext);
Session session = request.getSession(true);
ScriptHelper flow = (ScriptHelper) session.getAttribute(USER_GLOBAL_SCOPE);
ContinuationContext context = new ContinuationContext();
context.setObject(flow);
context.setAvalonContext(avalonContext);
context.setLogger(getLogger());
context.setServiceManager(manager);
context.setRedirector(redirector);
Parameters parameters = new Parameters();
for(Iterator i=params.iterator(); i.hasNext();) {
Argument argument = (Argument)i.next();
parameters.setParameter(argument.name, argument.value);
}
context.setParameters(parameters);
Continuation continuation = new Continuation(context);
WebContinuation wk = continuationsMgr.createWebContinuation(continuation, null, timeToLive, null);
FlowHelper.setWebContinuation(ContextHelper.getObjectModel(this.avalonContext), wk);
continuation.registerThread();
try {
if (flow == null) {
if (getLogger().isDebugEnabled())
getLogger().debug("create new instance of the script helper");
flow = getScriptHelper();
context.setObject(flow);
}
flow.callFunction(function, params);
} finally {
// remove last object reference, which is not needed to
// reconstruct the invocation path
if (continuation.isCapturing())
continuation.getStack().popReference();
continuation.deregisterThread();
}
session.setAttribute(USER_GLOBAL_SCOPE, flow);
}
public void handleContinuation(String id, List params, Redirector redirector) throws Exception {
WebContinuation parentwk = continuationsMgr.lookupWebContinuation(id);
if (parentwk == null) {
/*
* Throw an InvalidContinuationException to be handled inside the
* <map:handle-errors> sitemap element.
*/
throw new InvalidContinuationException("The continuation ID " + id + " is invalid."); }
Continuation parentContinuation = (Continuation) parentwk.getContinuation();
ContinuationContext parentContext = (ContinuationContext) parentContinuation.getContext();
ContinuationContext context = new ContinuationContext();
context.setObject(parentContext.getObject());
context.setAvalonContext(avalonContext);
context.setLogger(getLogger());
context.setServiceManager(manager);
context.setRedirector(redirector);
Parameters parameters = new Parameters();
for(Iterator i=params.iterator(); i.hasNext();) {
Argument argument = (Argument)i.next();
parameters.setParameter(argument.name, argument.value);
}
context.setParameters(parameters);
Continuation continuation = new Continuation(parentContinuation, context);
Request request = ContextHelper.getRequest(this.avalonContext);
Session session = request.getSession(true);
HashMap userScopes = (HashMap) session.getAttribute(USER_GLOBAL_SCOPE);
ScriptHelper flow = (ScriptHelper) context.getObject();
WebContinuation wk = continuationsMgr.createWebContinuation(continuation, parentwk, timeToLive, null);
FlowHelper.setWebContinuation(ContextHelper.getObjectModel(this.avalonContext), wk);
continuation.registerThread();
try {
flow.callFunction(null, null);
} finally {
// remove last object reference, which is not needed to reconstruct
// the invocation path
if (continuation.isCapturing())
continuation.getStack().popReference();
continuation.deregisterThread();
}
session.setAttribute(USER_GLOBAL_SCOPE, flow);
}
}
1.1 cocoon-2.1/src/blocks/javaflow/java/org/apache/cocoon/components/flow/javascript/ScriptHelper.java
Index: ScriptHelper.java
===================================================================
/*
* Created on 24.06.2004
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
package org.apache.cocoon.components.flow.javascript;
import java.util.List;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
/**
* @author stephan
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
public interface ScriptHelper extends Configurable, Initializable {
public void register(String source);
public void callFunction(String funName, List params) throws Exception;
}
1.3 +6 -1 cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/java/test/JavaFlowTestCase.java
Index: JavaFlowTestCase.java
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/java/test/JavaFlowTestCase.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- JavaFlowTestCase.java 23 Jun 2004 09:16:32 -0000 1.2
+++ JavaFlowTestCase.java 24 Jun 2004 16:48:53 -0000 1.3
@@ -160,4 +160,9 @@
String id = callFunction("java", source, "parameterTest", parameters);
}
+
+ public void testClass() throws Exception {
+ String source = "org.apache.cocoon.components.flow.java.test.SimpleFlow";
+ String id = callFunction("java", source, "forClassTest", new HashMap());
+ }
}
1.2 +1 -1 cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/java/test/JavaFlowTestCase.xtest
Index: JavaFlowTestCase.xtest
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/java/test/JavaFlowTestCase.xtest,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- JavaFlowTestCase.xtest 14 Jun 2004 14:53:56 -0000 1.1
+++ JavaFlowTestCase.xtest 24 Jun 2004 16:48:53 -0000 1.2
@@ -78,7 +78,7 @@
<source-resolver class="org.apache.excalibur.source.impl.SourceResolverImpl"/>
<flow-interpreters default="java">
- <component-instance class="org.apache.cocoon.components.flow.java.JavaInterpreter" name="java"/>
+ <component-instance class="org.apache.cocoon.components.flow.java.JavaInterpreter" name="java" debug="false"/>
</flow-interpreters>
<continuations-manager time-to-live="3600000">
1.7 +8 -0 cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/java/test/SimpleFlow.java
Index: SimpleFlow.java
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/java/test/SimpleFlow.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- SimpleFlow.java 23 Jun 2004 09:16:32 -0000 1.6
+++ SimpleFlow.java 24 Jun 2004 16:48:53 -0000 1.7
@@ -20,7 +20,10 @@
import junit.framework.Assert;
import org.apache.cocoon.components.flow.java.*;
+import org.apache.cocoon.components.flow.javascript.ScriptablePropertyHandler;
import org.apache.cocoon.forms.FormContext;
+import org.apache.commons.jxpath.JXPathIntrospector;
+import org.mozilla.javascript.Scriptable;
/*import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.*;*/
@@ -130,6 +133,11 @@
Assert.assertEquals("abc", getParameters().getParameter("p1"));
Assert.assertEquals("def", getParameters().getParameter("p2"));
Assert.assertEquals(2.3f, getParameters().getParameterAsFloat("p3"), 0.1f);
+ }
+
+ public void doClassTest() {
+ JXPathIntrospector.registerDynamicClass(Scriptable.class,
+ ScriptablePropertyHandler.class);
}
}
1.3 +5 -3 cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/javascript/JavaScriptFlowTestCase.java
Index: JavaScriptFlowTestCase.java
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/javascript/JavaScriptFlowTestCase.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- JavaScriptFlowTestCase.java 14 Jun 2004 14:53:57 -0000 1.2
+++ JavaScriptFlowTestCase.java 24 Jun 2004 16:48:53 -0000 1.3
@@ -16,6 +16,8 @@
package org.apache.cocoon.components.flow.javascript;
+import java.util.HashMap;
+
import org.apache.cocoon.SitemapComponentTestCase;
/**
@@ -31,7 +33,7 @@
}
public void testCalculator() throws Exception {
- /*String source = "resource://org/apache/cocoon/components/flow/javascript/calc.js";
- callFunction("java", source, "calculator", new ArrayList());*/
+ String source = "resource://org/apache/cocoon/components/flow/javascript/calc.js";
+ callFunction("javascript", source, "calculator", new HashMap());
}
}
1.2 +3 -2 cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/javascript/JavaScriptFlowTestCase.xtest
Index: JavaScriptFlowTestCase.xtest
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/blocks/javaflow/test/org/apache/cocoon/components/flow/javascript/JavaScriptFlowTestCase.xtest,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- JavaScriptFlowTestCase.xtest 4 Jun 2004 14:02:38 -0000 1.1
+++ JavaScriptFlowTestCase.xtest 24 Jun 2004 16:48:53 -0000 1.2
@@ -77,10 +77,11 @@
<source-resolver class="org.apache.excalibur.source.impl.SourceResolverImpl"/>
- <flow-interpreters default="java">
+ <flow-interpreters default="javascript">
<component-instance class="org.apache.cocoon.components.flow.java.JavaInterpreter" name="java"/>
+ <component-instance class="org.apache.cocoon.components.flow.javascript.JavaScriptInterpreter" name="javascript" debug="false"/>
</flow-interpreters>
-
+
<continuations-manager time-to-live="3600000">
<expirations-check type="periodic">
<offset>180000</offset>