You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by tc...@apache.org on 2005/10/06 11:06:29 UTC

svn commit: r306557 - in /cocoon: blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/ blocks/javaflow/trunk/java/org/apache/cocoon/forms/ blocks/javaflow/trunk/java/org/apache/cocoon/forms/flow/ blocks/javaflow/trunk/java/org/apache/coco...

Author: tcurdt
Date: Thu Oct  6 02:06:11 2005
New Revision: 306557

URL: http://svn.apache.org/viewcvs?rev=306557&view=rev
Log:
updated to latest javaflow and jci,
re-added the CForms integration


Added:
    cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/AbstractContinuable.java
    cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/Invoker.java
    cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/forms/
    cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/forms/flow/
    cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/forms/flow/java/
    cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/forms/flow/java/FormInstance.java
    cocoon/trunk/lib/core/commons-javaflow-r306555.jar   (with props)
    cocoon/trunk/lib/core/commons-jci-r306555.jar   (with props)
Removed:
    cocoon/trunk/lib/core/commons-javaflow-r291286.jar
    cocoon/trunk/lib/core/commons-jci-r291284.jar
Modified:
    cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java
    cocoon/trunk/lib/jars.xml

Added: cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/AbstractContinuable.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/AbstractContinuable.java?rev=306557&view=auto
==============================================================================
--- cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/AbstractContinuable.java (added)
+++ cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/AbstractContinuable.java Thu Oct  6 02:06:11 2005
@@ -0,0 +1,180 @@
+/*
+ * 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.util.Map;
+import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.logger.Logger;
+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.Request;
+import org.apache.commons.javaflow.Continuation;
+import org.apache.excalibur.source.SourceUtil;
+
+/**
+ * Abstract class to add basic methods for flow handling.
+ * 
+ * @author <a href="mailto:tcurdt@apache.org">Torsten Curdt</a>
+ * @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
+ * @version CVS $Id: AbstractContinuable.java 30932 2004-07-29 17:35:38Z vgritsenko $
+ */
+public abstract class AbstractContinuable {
+
+    protected CocoonContinuationContext getContext() {
+        Object context = Continuation.getContext();
+        
+        if (context == null) {
+            throw new IllegalStateException("No continuation is running");
+        }
+        return (CocoonContinuationContext) context;
+    }
+
+
+    public Logger getLogger() {
+        return getContext().getLogger();
+    }
+
+
+    public void sendPageAndWait( String uri ) {
+        sendPageAndWait(uri, new VarMap());
+    }
+
+
+    public void sendPageAndWait( String uri, Object bizdata ) {
+        CocoonContinuationContext context = getContext();
+        if (context.getLogger() != null)
+            context.getLogger().debug("send page and wait '" + uri + "'");
+        FlowHelper.setContextObject(ContextHelper.getObjectModel(context.getAvalonContext()),
+                bizdata);
+        if (SourceUtil.indexOfSchemeColon(uri) == -1) {
+            uri = "cocoon:/" + uri;
+            if (getContext().getRedirector().hasRedirected()) {
+                throw new IllegalStateException(
+                        "Pipeline has already been processed for this request");
+            }
+            try {
+                context.getRedirector().redirect(false, uri);
+            } catch (Exception e) {
+                throw new CascadingRuntimeException("Cannot redirect to '" + uri + "'", e);
+            }
+        } else {
+            throw new IllegalArgumentException(
+                    "uri is not allowed to contain a scheme (cocoon:/ is always automatically used)");
+        }
+        Continuation.suspend();
+    }
+
+
+    public void sendPage( String uri ) {
+        sendPage(uri, new VarMap());
+    }
+
+
+    public void sendPage( String uri, Object bizdata ) {
+        CocoonContinuationContext context = getContext();
+        
+        if (context.getLogger() != null) {
+            context.getLogger().debug("send page '" + uri + "'");
+        }
+        
+        FlowHelper.setContextObject(
+                ContextHelper.getObjectModel(context.getAvalonContext()),
+                bizdata
+                );
+
+        if (SourceUtil.indexOfSchemeColon(uri) == -1) {
+            uri = "cocoon:/" + uri;
+
+            if (getContext().getRedirector().hasRedirected()) {
+                throw new IllegalStateException(
+                        "Pipeline has already been processed for this request");
+            }
+            try {
+                context.getRedirector().redirect(false, uri);
+            } catch (Exception e) {
+                throw new CascadingRuntimeException("Cannot redirect to '" + uri + "'", e);
+            }
+        } else {
+            throw new IllegalArgumentException(
+                    "uri is not allowed to contain a scheme (cocoon:/ is always automatically used)");
+        }
+    }
+
+
+    public Request getRequest() {
+        return ContextHelper.getRequest(getContext().getAvalonContext());
+    }
+
+
+    public Map getObjectModel() {
+        return ContextHelper.getObjectModel(getContext().getAvalonContext());
+    }
+
+
+    public void processPipelineTo( String uri, Object bizdata, OutputStream out ) {
+        CocoonContinuationContext context = getContext();
+        PipelineUtil pipeUtil = new PipelineUtil();
+        try {
+            pipeUtil.contextualize(context.getAvalonContext());
+            pipeUtil.service(context.getServiceManager());
+            pipeUtil.processToStream(uri, bizdata, out);
+        } catch (Exception e) {
+            throw new CascadingRuntimeException("Cannot process pipeline to '" + uri + "'", e);
+        } finally {
+            pipeUtil.dispose();
+        }
+    }
+
+
+    public void redirectTo( String uri ) {
+        try {
+            getContext().getRedirector().redirect(false, uri);
+        } catch (Exception e) {
+            throw new CascadingRuntimeException("Cannot redirect to '" + uri + "'", e);
+        }
+    }
+
+
+    public void sendStatus( int sc ) {
+        getContext().getRedirector().sendStatus(sc);
+    }
+
+
+    /**
+     * Access components.
+     */
+    public Object getComponent( String id ) {
+        try {
+            return getContext().getServiceManager().lookup(id);
+        } catch (Exception e) {
+            throw new CascadingRuntimeException("Cannot lookup component '" + id + "'", e);
+        }
+    }
+
+
+    /**
+     * Release pooled components.
+     * 
+     * @param component a component
+     */
+    public void releaseComponent( Object component ) {
+        if (component != null) {
+            getContext().getServiceManager().release(component);
+        }
+    }
+}

Added: cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/Invoker.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/Invoker.java?rev=306557&view=auto
==============================================================================
--- cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/Invoker.java (added)
+++ cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/Invoker.java Thu Oct  6 02:06:11 2005
@@ -0,0 +1,22 @@
+package org.apache.cocoon.components.flow.java;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+public final class Invoker implements Runnable, Serializable {
+    private final Method method;
+
+    public Invoker(Method method) throws IllegalAccessException, InstantiationException {
+        this.method = method;
+    }
+
+    public void run() {
+        try {
+            Object o = method.getDeclaringClass().newInstance();
+            method.invoke(o, new Object[0]);
+        } catch (Throwable e) {
+            // FIXME
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file

Modified: cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java?rev=306557&r1=306556&r2=306557&view=diff
==============================================================================
--- cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java (original)
+++ cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java Thu Oct  6 02:06:11 2005
@@ -15,7 +15,6 @@
  */
 package org.apache.cocoon.components.flow.java;
 
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -61,27 +60,6 @@
     
     private Map methods = new HashMap();
 
-    private class Invoker implements Runnable {
-        private final Method method;
-        private final Object instance;
-
-        public Invoker(Method method) throws IllegalAccessException, InstantiationException {
-            this.method = method;
-            this.instance = method.getDeclaringClass().newInstance();
-        }
-
-        public void run() {
-            try {
-                method.invoke(instance, new Object[0]);
-            } catch (IllegalAccessException e) {
-                getLogger().error("", e);
-            } catch (InvocationTargetException e) {
-                getLogger().error("", e);
-            }
-        }
-    }
-
-    
     private CocoonContinuationContext createContinuationContext( final List params, final Redirector redirector ) {
         final CocoonContinuationContext context = new CocoonContinuationContext();
         
@@ -174,7 +152,9 @@
 
         final Continuation newContinuation = Continuation.startWith(new Invoker(method), context);
 
-        handler.setContinuation(newContinuation);        
+        handler.setContinuation(newContinuation);
+        
+        getLogger().debug("generated javaflow continuation " + newContinuation);
     }
 
     public void handleContinuation( final String id, final List params, final Redirector redirector ) throws Exception {
@@ -198,8 +178,12 @@
                 ContextHelper.getObjectModel(avalonContext), newWebContinuation);
 
         final Continuation oldContinuation = oldHandler.getContinuation();
+
+        getLogger().debug("resuming javaflow continuation " + oldContinuation);
+
         final Continuation newContinuation = Continuation.continueWith(oldContinuation, context);
 
         newHandler.setContinuation(newContinuation);
+        getLogger().debug("generated javaflow continuation " + newContinuation);
     }
 }

Added: cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/forms/flow/java/FormInstance.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/forms/flow/java/FormInstance.java?rev=306557&view=auto
==============================================================================
--- cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/forms/flow/java/FormInstance.java (added)
+++ cocoon/blocks/javaflow/trunk/java/org/apache/cocoon/forms/flow/java/FormInstance.java Thu Oct  6 02:06:11 2005
@@ -0,0 +1,294 @@
+/*
+ * 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.forms.flow.java;
+
+import java.util.Locale;
+import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.cocoon.components.flow.FlowHelper;
+import org.apache.cocoon.components.flow.java.AbstractContinuable;
+import org.apache.cocoon.components.flow.java.VarMap;
+import org.apache.cocoon.forms.FormContext;
+import org.apache.cocoon.forms.FormManager;
+import org.apache.cocoon.forms.binding.Binding;
+import org.apache.cocoon.forms.binding.BindingManager;
+import org.apache.cocoon.forms.formmodel.Form;
+import org.apache.cocoon.forms.formmodel.Widget;
+import org.apache.cocoon.forms.transformation.FormsPipelineConfig;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+import org.w3c.dom.Element;
+
+/**
+ * Implementation of the Cocoon Forms/Java Flow integration.
+ * 
+ * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
+ * @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
+ * @version CVS $Id: FormInstance.java 239610 2005-08-24 11:36:41Z thorsten $
+ */
+public class FormInstance extends AbstractContinuable {
+
+    private Form form;
+    private Binding binding;
+    private Locale locale;
+    private boolean isValid;
+    private Object validator; // Used?
+
+
+    /**
+     * Create a form, given the URI of its definition file
+     */
+    public FormInstance(String uri) {
+        FormManager formMgr = null;
+        SourceResolver resolver = null;
+        Source src = null;
+        try {
+            formMgr = (FormManager) getComponent(FormManager.ROLE);
+            resolver = (SourceResolver) getComponent(SourceResolver.ROLE);
+            src = resolver.resolveURI(uri);
+            this.form = formMgr.createForm(src);
+            this.binding = null;
+            // this.validator = null;
+            // TODO : do we keep this ?
+            // this.formWidget = new Widget(this.form); could not create instance
+        } catch (Exception e) {
+            throw new CascadingRuntimeException("Could not create form instance", e);
+        } finally {
+            releaseComponent(formMgr);
+            if (src != null)
+                resolver.release(src);
+            releaseComponent(resolver);
+        }
+    }
+
+
+    /**
+     * Create a form, given the URI of its definition file, the binding file.
+     */
+    public FormInstance(String definitionFile, String bindingFile) {
+        this(definitionFile);
+        createBinding(bindingFile);
+    }
+
+
+    /**
+     * Create a form of an fd:form element in the form of a org.w3c.dom.Element
+     */
+    public FormInstance(Element formDefinition) {
+        FormManager formMgr = null;
+        try {
+            formMgr = (FormManager) getComponent(FormManager.ROLE);
+            this.form = formMgr.createForm(formDefinition);
+            this.binding = null;
+        } catch (Exception e) {
+            throw new CascadingRuntimeException("Could not create form instance", e);
+        } finally {
+            releaseComponent(formMgr);
+        }
+    }
+
+
+    /*
+     * Create a form, given the URI of its definition file, the binding file and set the forms
+     * locale
+     */
+    public FormInstance(String definitionFile, String bindingFile, Locale locale) {
+        this(definitionFile);
+        this.locale = locale;
+        createBinding(bindingFile);
+    }
+
+
+    /**
+     * Create a form, given the URI of its definition file, and set the locale.
+     */
+    public FormInstance(String definitionFile, Locale locale) {
+        this(definitionFile);
+        this.locale = locale;
+    }
+
+
+    public Widget getModel() {
+        return this.form;
+    }
+
+
+    /**
+     * Get a Widget (the java object) from the form. If <code>name</code> is undefined, the form
+     * widget itself is returned. Otherwise, the form's child widget of name <code>name</code> is
+     * returned.
+     */
+    public Widget getChild( String name ) {
+        if (name == null) {
+            return this.form;
+        } else {
+            return this.form.getChild(name);
+        }
+    }
+
+
+    public String getSubmitId() {
+        Widget widget = this.form.getSubmitWidget();
+        // Can be null on "normal" submit
+        return widget == null ? null : widget.getId();
+    }
+
+
+    /**
+     * Sets the point in your script that will be returned to when the form is redisplayed. If
+     * setBookmark() is not called, this is implicitly set to the beginning of showForm().
+     */
+    /*
+     * public WebContinuation setBookmark() { return (this.local_.webContinuation =
+     * cocoon.createWebContinuation()); }
+     */
+    /**
+     * Returns the bookmark continuation associated with this form, or undefined if setBookmark()
+     * has not been called.
+     */
+    /*
+     * public WebContinuation getBookmark() { return this.local_.webContinuation; }
+     */
+    public void show( String uri ) {
+        show(uri, new VarMap());
+    }
+
+
+    /**
+     * Manages the display of a form and its validation. This uses some additionnal propertied on
+     * the form object : - "locale" : the form locale (default locale is used if not set) -
+     * "validator" : additional validation function. This function receives the form object as
+     * parameter and should return a boolean indicating if the form handling is finished (true) or
+     * if the form should be redisplayed again (false) On return, the calling code can check some
+     * properties to know the form result : - "isValid" : true if the form was sucessfully validated -
+     * "submitId" : the id of the widget that triggered the form submit (can be null)
+     * 
+     * @param uri the page uri (like in cocoon.sendPageAndWait())
+     * @param bizData some business data for the view (like in cocoon.sendPageAndWait()). The
+     *            "{FormsPipelineConfig.CFORMSKEY}" and "locale" properties are added to this
+     *            object.
+     */
+    public void show( String uri, Object bizData ) {
+        if (bizData == null)
+            bizData = new VarMap();
+        ((VarMap) bizData).add(FormsPipelineConfig.CFORMSKEY, this.form);
+        if (this.locale == null)
+            this.locale = java.util.Locale.getDefault();
+        ((VarMap) bizData).add("locale", this.locale);
+        // Keep the first continuation that will be created as the result of this function
+        // var result = null;
+        boolean finished = false;
+        this.isValid = false;
+        do {
+            sendPageAndWait(uri, bizData);
+            FormContext formContext = new FormContext(getRequest(), locale);
+            // Prematurely add the bizData as a request attribute so that event listeners can use it
+            // (the same is done by cocoon.sendPage())
+            FlowHelper.setContextObject(this.getObjectModel(), bizData);
+            finished = this.form.process(formContext);
+            // Additional flow-level validation
+            if (finished) {
+                if (this.validator == null) {
+                    this.isValid = this.form.isValid();
+                } else {
+                    this.isValid = this.form.isValid() /* & this.validator(this.form, bizData) */;
+                }
+                finished = this.isValid;
+            }
+            // FIXME: Theoretically, we should clone the form widget (this.form) to ensure it keeps
+            // its
+            // value with the continuation. We don't do it since there should me not much pratical
+            // consequences
+            // except a sudden change of repeaters whose size changed from a continuation to
+            // another.
+        } while (!finished);
+    }
+
+
+    /*
+     * /** Manages the display of a form and its validation. @param uri the page uri (like in
+     * cocoon.sendPageAndWait()) @param fun optional function which will be executed after pipeline
+     * processing. Useful for releasing resources needed during pipeline processing but which should
+     * not become part of the continuation @param ttl Time to live (in milliseconds) for the
+     * continuation created @return The web continuation associated with submitting this form public
+     * showForm(String uri, Object fun, ttl) { if (!this.getBookmark()) { this.setBookmark(); }
+     * FormContext formContext = FormsFlowHelper.getFormContext(cocoon, this.locale); // this is
+     * needed by the FormTemplateTransformer: //var javaWidget = this.formWidget_.unwrap();;
+     * //this.formWidget_["CocoonFormsInstance"] = javaWidget;
+     * getRequest().setAttribute(Packages.org.apache.cocoon.forms.transformation.CFORMSKEY,
+     * this.formWidget); WebContinuation wk = sendPageAndWait(uri, this.formWidget, fun, ttl); var
+     * formContext = new FormContext(cocoon.request, javaWidget.getLocale()); var userErrors = 0;
+     * this.formWidget_.validationErrorListener = function(widget, error) { if (error != null) {
+     * userErrors++; } } var finished = javaWidget.process(formContext); if (this.onValidate) {
+     * this.onValidate(this); } if (!finished || userErrors > 0) { cocoon.continuation =
+     * this.local_.webContinuation;
+     * this.local_.webContinuation.continuation(this.local_.webContinuation); } return wk; }
+     */
+    public void createBinding( String bindingURI ) {
+        BindingManager bindingManager = null;
+        Source source = null;
+        SourceResolver resolver = null;
+        try {
+            bindingManager = (BindingManager) getComponent(BindingManager.ROLE);
+            resolver = (SourceResolver) getComponent(SourceResolver.ROLE);
+            source = resolver.resolveURI(bindingURI);
+            this.binding = bindingManager.createBinding(source);
+        } catch (Exception e) {
+            throw new CascadingRuntimeException("Could not create binding", e);
+        } finally {
+            if (source != null)
+                resolver.release(source);
+            releaseComponent(bindingManager);
+            releaseComponent(resolver);
+        }
+    }
+
+
+    public void load( Object object ) {
+        if (this.binding == null)
+            throw new Error("Binding not configured for this form.");
+        try {
+            this.binding.loadFormFromModel(this.form, object);
+        } catch (Exception e) {
+            throw new CascadingRuntimeException("Could not load form from model", e);
+        }
+    }
+
+
+    public void save( Object object ) {
+        if (this.binding == null)
+            throw new Error("Binding not configured for this form.");
+        try {
+            this.binding.saveFormToModel(this.form, object);
+        } catch (Exception e) {
+            throw new CascadingRuntimeException("Could not save form into model", e);
+        }
+    }
+
+
+    public void setAttribute( String name, Object value ) {
+        this.form.setAttribute(name, value);
+    }
+
+
+    public Object getAttribute( String name ) {
+        return this.form.getAttribute(name);
+    }
+
+
+    public void removeAttribute( String name ) {
+        this.form.removeAttribute(name);
+    }
+}

Added: cocoon/trunk/lib/core/commons-javaflow-r306555.jar
URL: http://svn.apache.org/viewcvs/cocoon/trunk/lib/core/commons-javaflow-r306555.jar?rev=306557&view=auto
==============================================================================
Binary file - no diff available.

Propchange: cocoon/trunk/lib/core/commons-javaflow-r306555.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: cocoon/trunk/lib/core/commons-jci-r306555.jar
URL: http://svn.apache.org/viewcvs/cocoon/trunk/lib/core/commons-jci-r306555.jar?rev=306557&view=auto
==============================================================================
Binary file - no diff available.

Propchange: cocoon/trunk/lib/core/commons-jci-r306555.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: cocoon/trunk/lib/jars.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/lib/jars.xml?rev=306557&r1=306556&r2=306557&view=diff
==============================================================================
--- cocoon/trunk/lib/jars.xml (original)
+++ cocoon/trunk/lib/jars.xml Thu Oct  6 02:06:11 2005
@@ -1147,7 +1147,7 @@
       API for compiling java
     </description>
     <used-by>javaflow</used-by>
-    <lib>core/commons-jci-r291284.jar</lib>
+    <lib>core/commons-jci-r306555.jar</lib>
     <homepage></homepage>
   </file>