struts-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mr...@apache.org
Subject svn commit: r240168 [18/30] - in /struts/sandbox/trunk/ti: ./ core/src/java/org/apache/ti/ core/src/java/org/apache/ti/config/ core/src/java/org/apache/ti/config/mapper/ core/src/java/org/apache/ti/core/ core/src/java/org/apache/ti/core/factory/ core/s...
Date Fri, 26 Aug 2005 05:46:58 GMT
Modified: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/chain-config-servlet.xml
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/chain-config-servlet.xml?rev=240168&r1=240167&r2=240168&view=diff
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/chain-config-servlet.xml (original)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/chain-config-servlet.xml Thu Aug 25 22:46:03 2005
@@ -34,11 +34,14 @@
             className= "org.apache.commons.chain.generic.LookupCommand" />
             
             
-    <!-- ========== Start of chain ========================= -->
+    <!-- ========== Start of action chain ========================= -->
 
-    <chain     name="start" >
+    <chain     name="start-action" >
+      <command name="populateActionContext"  />
       <command name="createActionMapping"  />
       <command name="processTagsInDevMode"  />
+      <command name="createPageFlowContext" className="org.apache.ti.processor.chain.pageflow.CreatePageFlowContext" />
+      <command name="setupPageFlowModule" />
       <command name="populateContextForRequest" className="org.apache.ti.processor.chain.PopulateContextForRequest"/>
       <command name="populateContextForWebWork" className="org.apache.ti.processor.chain.webwork.PopulateContextForWebWork" />
       <command name="createWebWorkActionProxy" className="org.apache.ti.processor.chain.webwork.CreateWebWorkActionProxy"/>
@@ -48,20 +51,41 @@
            optional="false"/>
     </chain>
     
-    <!-- ========== Initialization chain ========================= -->
+    <!-- ========== Start of page/view chain ========================= -->
 
-    <chain     name="init" >
+    <chain     name="start-view" >
+      <command name="populateActionContext" />
+      <command name="createPageFlowViewContext" className="org.apache.ti.processor.chain.pageflow.CreatePageFlowViewContext" />
+      <command name="populatePageFlowContext" />
+      <!-- "showView" will be split up into a sub-chain -->
+      <command name="showView" className="org.apache.ti.processor.chain.pageflow.ShowView"/>
+    </chain>
+    
+    <!-- ========== Action Initialization chain ========================= -->
+
+    <chain     name="init-action" >
       <command name="initXWork" />
       <command name="initWebWork" />
+      <command name="initPageFlow" />
     </chain>
  
     <chain     name="create-context" >
       <command name="makeContextStackAware" className="org.apache.ti.processor.chain.servlet.MakeContextStackAware" />
     </chain>
     
+    <!-- ========== View Initialization chain ========================= -->
+    
+    <chain name="init-view" >
+    </chain>
+
     <chain     name="process-action" className="org.apache.ti.processor.chain.ProcessActionChain">
       
       <command name="initControllerContext"  />
+      <command name="populatePageFlowContext"  />
+      <command name="createSharedFlows" className="org.apache.ti.processor.chain.pageflow.CreateSharedFlows" />
+      <command name="chooseFlowController" className="org.apache.ti.processor.chain.pageflow.ChooseFlowController" />
+      <command name="chooseFormBean" className="org.apache.ti.processor.chain.pageflow.ChooseFormBean" />
+      <command name="populateData" className="org.apache.ti.processor.chain.pageflow.PopulateData" />
       <lookup catalogName="struts-ti" name="createForm" optional="true" />
       <command name="selectLocale" className="org.apache.ti.processor.chain.servlet.SelectLocale" />
       <command name="createValidatorContext" className="org.apache.ti.processor.chain.CreateValidatorContext" />

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ChooseFlowController.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ChooseFlowController.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ChooseFlowController.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ChooseFlowController.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,100 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.processor.chain.pageflow;
+
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+import org.apache.ti.pageflow.ModuleConfig;
+import org.apache.ti.pageflow.FlowController;
+import org.apache.ti.pageflow.FlowControllerFactory;
+import org.apache.ti.pageflow.PageFlowController;
+import org.apache.ti.pageflow.PageFlowUtils;
+import org.apache.ti.pageflow.SharedFlowController;
+import org.apache.ti.util.logging.Logger;
+
+public class ChooseFlowController implements Command {
+
+    private static final Logger _log = Logger.getInstance(ChooseFlowController.class);
+    
+    public boolean execute(Context context) throws Exception {
+        //
+        // Get the FlowController for this request (page flow or shared flow), and cache it in the request.
+        //
+        PageFlowActionContext actionContext = PageFlowActionContext.get();        
+        ModuleConfig moduleConfig = actionContext.getModuleConfig();
+        assert moduleConfig != null;
+        
+        String flowControllerClassName = moduleConfig.getControllerClassName();
+        FlowController currentFlowController = null;
+        
+        if ( flowControllerClassName != null )
+        {
+            currentFlowController = getFlowController( flowControllerClassName );
+            actionContext.setCurrentFlowController( currentFlowController );
+        }
+        else
+        {
+            actionContext.setCurrentFlowController( null );
+        }
+        
+        return false;
+    }
+    
+    private FlowController getFlowController( String fcClassName )
+            throws ClassNotFoundException, InstantiationException, IllegalAccessException
+    {
+        FlowControllerFactory fcFactory = FlowControllerFactory.get();
+        Class fcClass = fcFactory.getFlowControllerClass( fcClassName );
+        
+        if ( PageFlowController.class.isAssignableFrom( fcClass ) )
+        {
+            PageFlowController current = PageFlowUtils.getCurrentPageFlow();
+            
+            if ( current != null && current.getClass().equals( fcClass ) )
+            {
+                if ( _log.isDebugEnabled() )
+                {
+                    _log.debug( "Using current page flow: " + current );
+                }
+                
+                //
+                // Reinitialize transient data that may have been lost on session failover.
+                //
+                current.reinitialize();
+                return current;
+            }
+            
+            return fcFactory.createPageFlow( fcClass );
+        }
+        else
+        {
+            assert SharedFlowController.class.isAssignableFrom( fcClass ) : fcClass.getName();
+            
+            SharedFlowController current = PageFlowUtils.getSharedFlow( fcClass.getName());
+            
+            if ( current != null )
+            {
+                current.reinitialize();
+                return current;
+            }
+            
+            return fcFactory.createSharedFlow( fcClass );
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ChooseFormBean.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ChooseFormBean.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ChooseFormBean.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ChooseFormBean.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,188 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.processor.chain.pageflow;
+
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.ti.pageflow.internal.InternalUtils;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+import org.apache.ti.pageflow.xwork.PageFlowAction;
+import org.apache.ti.pageflow.FlowController;
+import org.apache.ti.pageflow.handler.Handlers;
+import org.apache.ti.util.logging.Logger;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
+public class ChooseFormBean implements Command {
+    
+    private static final Logger _log = Logger.getInstance(ChooseFormBean.class);
+
+    public boolean execute(Context context) throws Exception {
+        PageFlowActionContext actionContext = PageFlowActionContext.get();        
+        Object formBean = getFormBean(actionContext.getAction());
+        actionContext.setFormBean(formBean);
+        return false;
+    }
+    
+    private Object getFormBean(PageFlowAction action) {
+        //
+        // See if we're using a pageflow-scoped form (a member variable in the current pageflow).
+        //
+        Field formMemberField = getPageFlowScopedFormMember(action);
+        
+        //
+        // First look to see whether the input form was overridden in the request.
+        // This happens when a pageflow action forwards to another pageflow,
+        // whose begin action expects a form.  In this case, the form is already
+        // constructed, and shouldn't be instantiated anew or populated from request
+        // parameters.
+        //
+        Object previousForm = InternalUtils.getForwardedFormBean( false );
+        PageFlowActionContext actionContext = PageFlowActionContext.get();        
+        
+        if ( previousForm != null )
+        {
+            //
+            // If there was a forwarded form, and if this action specifies a pageflow-scoped form member,
+            // set the member with this form.
+            //
+            if ( formMemberField != null )
+            {
+                try
+                {
+                    FlowController fc = actionContext.getFlowController();
+                    assert fc != null : "no FlowController in request " + actionContext.getRequestPath();
+                    formMemberField.set( fc, previousForm );
+                }
+                catch ( IllegalAccessException e )
+                {
+                    _log.error( "Could not access page flow member " + formMemberField.getName()
+                            + " as the form bean.", e );
+                }
+            }
+            
+            //
+            // Return the forwarded form.
+            //
+            return previousForm;
+        }
+        
+        //
+        // First see if the previous action put a pageflow-scoped form in the request.  If so, remove it;
+        // we don't want a normal request-scoped action to use this pageflow-scoped form.
+        //
+        String pageFlowScopedFormName = actionContext.getPageFlowScopedFormName();
+        Map requestScope = actionContext.getWebContext().getRequestScope();
+        if ( pageFlowScopedFormName != null )
+        {
+            requestScope.remove( pageFlowScopedFormName );
+            actionContext.setPageFlowScopedFormName( null );
+        }
+        
+        //
+        // If this action specifies a pageflow-scoped form member variable, use it.
+        //
+        if ( formMemberField != null )
+        {
+            try
+            {
+                FlowController fc = actionContext.getFlowController();
+                Object form = formMemberField.get( fc );
+                
+                if ( form == null ) // the pageflow hasn't filled the value yet
+                {
+                    form = createActionForm(action);
+                    
+                    // TODO: make an interface for reset(), and call reset.
+                    // form.reset( mapping, request );
+                    formMemberField.set( fc, form );
+                }
+                
+                //
+                // Store the form in the right place in the request, so Struts can see it.
+                // But, mark a flag so we know to remove this on the next action request -- we don't
+                // want this form used by another action unless that action uses the pageflow-scoped
+                // form.
+                //
+                String formAttrName = action.getFormBeanAttribute();
+                requestScope.put( formAttrName, form );
+                actionContext.setPageFlowScopedFormName( formAttrName );
+                return form;
+            }
+            catch ( IllegalAccessException e )
+            {
+                _log.error( "Could not access page flow member " + formMemberField.getName() + " as the form bean.", e );
+            }
+        }
+        
+        Object bean = createActionForm(action);
+        return bean;
+    }
+    
+    private static Object createActionForm(PageFlowAction action)
+    {
+        String formBeanType = action.getFormBeanType();
+        if (formBeanType != null) {
+            try {
+                if ( _log.isDebugEnabled() )
+                {
+                    _log.debug( "Creating new ActionForm instance of type " + formBeanType );
+                }
+               
+                return Handlers.get().getReloadableClassHandler().newInstance(formBeanType);
+            }
+            catch ( Exception e )
+            {
+                // Can be any exception -- not just the reflection-related exceptions...
+                // because the exception could be thrown from the bean's constructor.
+                if ( _log.isErrorEnabled() )
+                {
+                    _log.error( "Error while creating form-bean object of type " + formBeanType, e );
+                }
+            }
+        }
+        
+        return null;
+    }
+        
+    private Field getPageFlowScopedFormMember(PageFlowAction action)
+    {
+        String formMember = action.getFormMember();
+        
+        try
+        {
+            if ( formMember != null )
+            {
+                FlowController fc = PageFlowActionContext.get().getFlowController();
+                Field field = fc.getClass().getDeclaredField( formMember );
+                if ( ! Modifier.isPublic( field.getModifiers() ) ) field.setAccessible( true );
+                return field;
+            }
+        }
+        catch ( Exception e )
+        {
+            _log.error( "Could not use page flow member " + formMember + " as the form bean.", e );
+        }
+        
+        return null;
+    }
+    
+     
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreatePageFlowContext.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreatePageFlowContext.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreatePageFlowContext.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreatePageFlowContext.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,34 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.processor.chain.pageflow;
+
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.commons.chain.web.WebContext;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+import com.opensymphony.xwork.ActionContext;
+
+public class CreatePageFlowContext implements Command {
+
+    public boolean execute(Context context) throws Exception {
+        ActionContext actionContext = ActionContext.getContext();
+        WebContext webContext = (WebContext) context;
+        ActionContext.setContext(new PageFlowActionContext(actionContext.getContextMap(), webContext));
+        return false;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreatePageFlowViewContext.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreatePageFlowViewContext.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreatePageFlowViewContext.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreatePageFlowViewContext.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,30 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.processor.chain.pageflow;
+
+import org.apache.commons.chain.Context;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+import com.opensymphony.xwork.ActionContext;
+
+public class CreatePageFlowViewContext extends CreatePageFlowContext {
+
+    public boolean execute(Context context) throws Exception {
+        ActionContext.getContext().getContextMap().remove("actionMapping");
+        return super.execute(context);
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreateSharedFlows.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreateSharedFlows.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreateSharedFlows.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/CreateSharedFlows.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,44 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.processor.chain.pageflow;
+
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+import org.apache.ti.pageflow.FlowControllerFactory;
+import org.apache.ti.script.common.ImplicitObjectUtil;
+import org.apache.ti.util.logging.Logger;
+
+import java.util.Map;
+
+public class CreateSharedFlows implements Command {
+    
+    private static final Logger _log = Logger.getInstance(CreateSharedFlows.class);        
+
+    public boolean execute(Context context) throws Exception {
+        if ( _log.isDebugEnabled() )
+        {
+            String requestPath = PageFlowActionContext.get().getRequestPath();
+            _log.debug( "Attempting to instantiate SharedFlowControllers for request " + requestPath );
+        }
+        
+        Map/*< String, SharedFlowController >*/ sharedFlows = FlowControllerFactory.get().getSharedFlowsForRequest();
+        ImplicitObjectUtil.loadSharedFlow( sharedFlows );
+        return false;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/InitPageFlow.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/InitPageFlow.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/InitPageFlow.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/InitPageFlow.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,177 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.processor.chain.pageflow;
+
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.commons.chain.web.WebContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ti.core.urls.TemplatedURLFormatter;
+import org.apache.ti.core.urltemplates.URLTemplatesFactory;
+import org.apache.ti.pageflow.ContainerAdapter;
+import org.apache.ti.pageflow.FacesBackingBeanFactory;
+import org.apache.ti.pageflow.FlowControllerFactory;
+import org.apache.ti.pageflow.RequestParameterHandler;
+import org.apache.ti.pageflow.handler.Handlers;
+import org.apache.ti.pageflow.interceptor.action.ActionInterceptorContext;
+import org.apache.ti.pageflow.interceptor.request.RequestInterceptorContext;
+import org.apache.ti.pageflow.internal.AdapterManager;
+import org.apache.ti.pageflow.internal.DefaultTemplatedURLFormatter;
+import org.apache.ti.pageflow.internal.DefaultURLTemplatesFactory;
+import org.apache.ti.pageflow.internal.InternalConstants;
+import org.apache.ti.pageflow.internal.ProcessPopulate;
+import org.apache.ti.processor.chain.InitXWork;
+import org.apache.ti.schema.config.PrefixHandlers;
+import org.apache.ti.util.SourceResolver;
+import org.apache.ti.util.config.ConfigInitializationException;
+import org.apache.ti.util.config.ConfigUtil;
+
+import java.io.Serializable;
+import java.net.URL;
+import java.util.Map;
+
+public class InitPageFlow implements Command {
+
+    private static final Log log = LogFactory.getLog(InitXWork.class);
+    private static final String ALREADY_INIT_ATTR = InternalConstants.ATTR_PREFIX + "contextInit";
+
+    private SourceResolver _sourceResolver;
+    private Handlers _handlers;
+
+
+    private static class TransientFlag implements Serializable {
+
+        private static final long serialVersionUID = 1;
+        private transient boolean _flag;
+
+        public TransientFlag() {
+            _flag = true;
+        }
+
+        public boolean isSet() {
+            return _flag;
+        }
+    }
+
+    public boolean execute(Context context) throws Exception {
+        // TODO: turn this whole thing into a chain
+
+        log.debug("Initializing Page Flow");
+        WebContext webContext = (WebContext) context;
+        Map appScope = webContext.getApplicationScope();
+
+        // If the flag is present, but was serialized, then the webapp was redeployed.  At this point, we want
+        // to go through the init logic again.
+        TransientFlag flag = (TransientFlag) appScope.get(ALREADY_INIT_ATTR);
+        if (flag != null && flag.isSet()) return false;
+        appScope.put(ALREADY_INIT_ATTR, new TransientFlag());
+
+        //
+        // Initialize the config file, unless it's already initialized.  This can happen because the scope for the 
+        // config (static) isn't the same as the scope for PageFlowActionServlet, which may get created and destroyed
+        // within a classloader (which is the case during StrutsTestCase tests).
+        //
+        if (! ConfigUtil.isInit()) {
+            try {
+                URL configInput = _sourceResolver.resolve(InternalConstants.NETUI_CONFIG_PATH, webContext);
+                ConfigUtil.init(configInput);
+            }
+            catch (ConfigInitializationException e) {
+                log.fatal("Could not initialize from " + InternalConstants.NETUI_CONFIG_PATH, e);
+                IllegalStateException ie =
+                        new IllegalStateException("Could not initialize from " + InternalConstants.NETUI_CONFIG_PATH);
+                ie.initCause(e);
+                throw ie;
+            }
+        }
+
+        ContainerAdapter containerAdapter = AdapterManager.init(webContext);
+        _handlers.initApplication(appScope);
+        FlowControllerFactory.init(appScope);
+        FacesBackingBeanFactory.init(appScope);
+        initPrefixHandlers(appScope);
+
+        // Create a URLTemplatesFactory (may be container specific from the ContainerAdapter) and the the default
+        // TemplatedURLFormatter (registered in the netui config). These classes are used by the URLRewriterService.
+        TemplatedURLFormatter formatter =
+                TemplatedURLFormatter.initApplication(appScope, new DefaultTemplatedURLFormatter());
+        URLTemplatesFactory.initApplication(webContext, new DefaultURLTemplatesFactory(), formatter, containerAdapter,
+                _sourceResolver);
+
+        //
+        // Initialize the request interceptors and action interceptors.
+        //
+        ActionInterceptorContext.init(appScope);
+        RequestInterceptorContext.init(appScope);
+
+        return false;
+    }
+
+    /**
+     * This method will initialize all of the PrefixHandlers registered in the netui config.
+     * The prefix handlers are registered with ProcessPopulate and are typically implemented as
+     * public inner classes in the tags that require prefix handlers.
+     */
+    private static void initPrefixHandlers(Map appScope) {
+        PrefixHandlers ph = ConfigUtil.getConfig().getPrefixHandlers();
+        if (ph == null) {
+            return;
+        }
+        PrefixHandlers.PrefixHandler[] prefixHandlers = ph.getPrefixHandlerArray();
+        if (prefixHandlers != null) {
+            for (int i = 0; i < prefixHandlers.length; i++) {
+                try {
+                    Class prefixClass = Class.forName(prefixHandlers[i].getHandlerClass());
+                    String name = prefixHandlers[i].getName();
+                    if (name == null || name.equals("")) {
+                        log.warn("The name for the prefix handler '" + prefixHandlers[i].getHandlerClass()
+                                + "' must not be null");
+                        continue;
+                    }
+                    Object o = prefixClass.newInstance();
+                    if (!(o instanceof RequestParameterHandler)) {
+                        log.warn("The class '" + prefixHandlers[i].getHandlerClass()
+                                + "' must be an instance of RequestParameterHandler");
+                        continue;
+                    }
+                    ProcessPopulate.registerPrefixHandler(name, (RequestParameterHandler) o);
+                }
+                catch (ClassNotFoundException e) {
+                    log.warn("Class '" + prefixHandlers[i].getHandlerClass() + "' not found", e);
+                }
+                catch (IllegalAccessException e) {
+                    log.warn("Illegal access on Class '" + prefixHandlers[i].getHandlerClass() + '\'', e);
+
+                }
+                catch (InstantiationException e) {
+                    log.warn("InstantiationException on Class '" + prefixHandlers[i].getHandlerClass() + '\'',
+                            e.getCause());
+                }
+            }
+        }
+    }
+
+    public void setHandlers(Handlers handlers) {
+        _handlers = handlers;
+    }
+
+    public void setSourceResolver(SourceResolver sourceResolver) {
+        _sourceResolver = sourceResolver;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/PopulateData.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/PopulateData.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/PopulateData.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/PopulateData.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,86 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.processor.chain.pageflow;
+
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.ti.pageflow.internal.ProcessPopulate;
+import org.apache.ti.pageflow.internal.InternalUtils;
+import org.apache.ti.pageflow.internal.NullActionForm;
+import org.apache.ti.pageflow.internal.InternalConstants;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+import org.apache.ti.util.logging.Logger;
+
+import java.util.Map;
+
+public class PopulateData implements Command {
+
+    private static final Logger _log = Logger.getInstance(PopulateData.class);
+    private static final NullActionForm NULL_ACTION_FORM = new NullActionForm();
+    
+    public boolean execute(Context context) throws Exception {
+        //
+        // If a previous action forwarded us a form, use that -- don't populate it from request parameters.
+        //
+        Object previousForm = InternalUtils.getForwardedFormBean( true );
+
+        if ( previousForm != null ) {
+            return false;
+        }
+
+        if ( _log.isDebugEnabled() )
+        {
+            _log.debug( "Populating bean properties from this request" );
+        }
+
+        /* TODO: re-add multipart support
+        if ( mapping.getMultipartClass() != null )
+        {
+            request.setAttribute( Globals.MULTIPART_KEY, mapping.getMultipartClass() );
+        }
+        */
+
+        PageFlowActionContext actionContext = PageFlowActionContext.get();        
+        boolean alreadyCalledInRequest = actionContext.isProcessPopulateAlreadyCalled();
+        if ( ! alreadyCalledInRequest ) actionContext.setProcessPopulateAlreadyCalled( true );
+        
+        //
+        // If this is a forwarded request and the form-bean is null, don't call to ProcessPopulate.
+        // We don't want to expose errors due to parameters from the original request, which won't
+        // apply to a forwarded action that doesn't take a form.
+        //
+        Object formBean = actionContext.getFormBean();
+        if ( ! alreadyCalledInRequest || formBean != null )
+        {
+            //
+            // If this request was forwarded by a button-override of the main form action, then ensure that there are
+            // no databinding errors when the override action does not use a form bean.
+            //
+            if (formBean == null) {
+                Map mappingParams = actionContext.getActionMapping().getParams();
+                if (mappingParams != null && mappingParams.get(InternalConstants.ORIGINAL_ACTION_KEY) != null) {
+                    formBean = NULL_ACTION_FORM;
+                }
+            }
+            
+            ProcessPopulate.populate( formBean, alreadyCalledInRequest );
+        }    
+        
+        return false;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/SetupPageFlowModule.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/SetupPageFlowModule.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/SetupPageFlowModule.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/SetupPageFlowModule.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,41 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.processor.chain.pageflow;
+
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.ti.pageflow.handler.Handlers;
+import org.apache.ti.pageflow.ModuleConfig;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+import org.apache.ti.config.mapper.ActionMapping;
+
+/**
+ * Set up the Page Flow ModuleConfig.  This step needs to happen early because it also adds a configuration provider
+ * to XWork, which needs to have this configuration available when it is creating the ActionProxy.
+ */
+public class SetupPageFlowModule implements Command {
+
+    public boolean execute(Context context) throws Exception {
+
+        ActionMapping mapping = (ActionMapping) context.get("actionMapping");
+        String namespace = mapping.getNamespace();
+        ModuleConfig config = Handlers.get().getModuleRegistrationHandler().getModuleConfig(namespace);
+        PageFlowActionContext.get().setModuleConfig(config);
+        return false;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ShowView.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ShowView.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ShowView.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/processor/chain/pageflow/ShowView.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,255 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.processor.chain.pageflow;
+
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.ti.core.urls.URLRewriterService;
+import org.apache.ti.pageflow.ContainerAdapter;
+import org.apache.ti.pageflow.FlowController;
+import org.apache.ti.pageflow.FlowControllerFactory;
+import org.apache.ti.pageflow.PageFlowController;
+import org.apache.ti.pageflow.PageFlowEventReporter;
+import org.apache.ti.pageflow.PageFlowException;
+import org.apache.ti.pageflow.PageFlowUtils;
+import org.apache.ti.pageflow.handler.Handlers;
+import org.apache.ti.pageflow.internal.AdapterManager;
+import org.apache.ti.pageflow.internal.DefaultURLRewriter;
+import org.apache.ti.pageflow.internal.InternalUtils;
+import org.apache.ti.pageflow.internal.JavaControlUtils;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+import org.apache.ti.script.common.ImplicitObjectUtil;
+import org.apache.ti.util.logging.Logger;
+
+import java.util.Map;
+
+import com.opensymphony.xwork.ActionContext;
+
+public class ShowView implements Command {
+
+    private static final Logger _log = Logger.getInstance(ShowView.class);
+
+    public boolean execute(Context context) throws Exception {
+        // Callback to the container adapter.
+        ContainerAdapter containerAdapter = AdapterManager.getContainerAdapter();
+        PageFlowEventReporter er = containerAdapter.getEventReporter();
+        containerAdapter.beginRequest();
+        er.beginPageRequest();
+        long startTime = System.currentTimeMillis();
+        
+        //
+        // Initialize the ControlBeanContext in the session.
+        //
+        JavaControlUtils.initializeControlContext();
+
+        //
+        // Register the default URLRewriter
+        //
+        URLRewriterService.registerURLRewriter( 0, new DefaultURLRewriter() );
+
+        PageFlowActionContext actionContext = PageFlowActionContext.get();        
+        boolean isForwardedRequest = actionContext.isNestedRequest();
+        
+        try
+        {
+            if ( ! actionContext.isStayInCurrentModule() ) {
+                // Ensure that the right module is selected, for use by the tags.
+                InternalUtils.selectModule( actionContext.getModuleConfig());
+            }
+            
+            try
+            {
+                //
+                // Initialize shared flows for the current request.
+                //
+                FlowControllerFactory flowControllerFactory = FlowControllerFactory.get();
+                Map/*< String, SharedFlowController >*/ sharedFlows = flowControllerFactory.getSharedFlowsForRequest();
+                ImplicitObjectUtil.loadSharedFlow( sharedFlows );
+                
+                //
+                // Make sure that the current PageFlowController is set up for this request.
+                //
+                PageFlowController curJpf;
+                if ( actionContext.isStayInCurrentModule() )
+                {
+                    actionContext.setStayInCurrentModule( false );
+                    curJpf = PageFlowUtils.getCurrentPageFlow();
+                }
+                else
+                {
+                    curJpf = flowControllerFactory.getPageFlowForRequest();
+                }
+                
+                if ( _log.isDebugEnabled() )
+                {
+                    _log.debug( "Current PageFlowController is: " + curJpf );
+                    _log.debug( "Continuing with filter chain..." );
+                }
+                
+                runPage( curJpf);
+            }
+            catch ( ClassNotFoundException e )
+            {
+                throw new PageFlowException( e );
+            }
+            catch ( InstantiationException e )
+            {
+                throw new PageFlowException( e );
+            }
+            catch ( IllegalAccessException e )
+            {
+                throw new PageFlowException( e );
+            }
+            catch ( PageFlowException e )
+            {
+                throw new PageFlowException( e );
+            }
+        }
+        finally
+        {
+            //
+            // Clean up the ControlBeanContext in the session.
+            //
+            JavaControlUtils.uninitializeControlContext();
+            
+            //
+            // Callback to the server adapter.
+            //
+            containerAdapter.endRequest();
+            long timeTaken = System.currentTimeMillis() - startTime;
+            er.endPageRequest(timeTaken );
+            
+            //
+            // If this is not a forwarded request, then commit any session-scoped changes that were stored in the
+            // request.
+            //
+            if ( ! isForwardedRequest )
+            {
+                Handlers.get().getStorageHandler().applyChanges();
+            }
+        }
+        
+        return false;
+    }
+    
+    private void runPage( PageFlowController curJpf)
+        throws PageFlowException, PageFlowException
+    {
+        //
+        // Make sure that the pageflow's getRequest() and getResponse() will work while the page
+        // is being rendered, since methods on the pageflow may be called (through databinding
+        // or tags, or through direct reference).
+        //
+        if ( curJpf != null )
+        {
+            //
+            // We're going to bail out if there are too many concurrent requests for the same JPF.
+            // This prevents an attack that takes advantage of the fact that we synchronize requests
+            // to the same pageflow.
+            //
+            if ( curJpf.incrementRequestCount() )
+            {
+                try
+                {
+                    //
+                    // Any databinding calls, indirect calls to getRequest(), etc. must be protected
+                    // against conflicts from running action methods at the same time as rendering 
+                    // the page here.  Synchronize on the JPF.
+                    //
+                    synchronized ( curJpf )
+                    {
+                        ImplicitObjectUtil.loadImplicitObjects( curJpf );
+                                
+                        //
+                        // Tell the page flow that we're about to display a page so it can manage settings,
+                        // such as previous page information, if needed in advance.
+                        //
+                        curJpf.beforePage();
+                                
+                        try
+                        {
+                            showView();
+                        }
+                        catch ( PageFlowException ex )
+                        {
+                            //
+                            // If a PageFlowException escapes out of the page, let the current FlowController handle it.
+                            //
+                            if ( ! handleException( ex, curJpf) ) throw ex;
+                        }
+                        catch ( Throwable th )
+                        {
+                            //
+                            // If a Throwable escapes out of the page, let the current FlowController handle it.
+                            //
+                            if ( ! handleException( th, curJpf) )
+                            {
+                                if ( th instanceof Error ) throw ( Error ) th;
+                                throw new PageFlowException( th );
+                            }
+                        }
+                    }
+                }
+                finally
+                {
+                    curJpf.decrementRequestCount();
+                }
+            }
+        }
+        else
+        {
+            ImplicitObjectUtil.loadImplicitObjects(null );
+            showView();
+        }
+    }
+    
+    public static abstract class ViewRunner {
+        
+        public abstract void runView() throws PageFlowException;
+        
+        public void activate() {
+            ActionContext actionContext = ActionContext.getContext();
+            actionContext.put("viewRunner", this);
+        }
+    }
+    
+    protected void showView() throws PageFlowException {
+        ActionContext actionContext = ActionContext.getContext();
+        ViewRunner viewRunner = (ViewRunner) actionContext.get("viewRunner");
+        assert viewRunner != null : "ViewRunner not in action context under key \"viewRunner\"";
+        viewRunner.runView();
+    }
+    
+    private boolean handleException( Throwable th, FlowController fc) {
+        try
+        {
+            fc.handleException( th );
+            return true;
+        }
+        catch ( PageFlowException t )
+        {
+            _log.error( "Exception while handling exception " + th.getClass().getName()
+                        + ".  The original exception will be thrown.", th );
+            return false;
+        }
+    } 
+    
+    public void destroy()
+    {
+    }    
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/Expression.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/Expression.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/Expression.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/Expression.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,56 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.script;
+
+// java imports
+
+import java.util.List;
+
+// internal imports
+
+// external imports
+
+/**
+ * This class implements an abstraction atop an Expression object.
+ * It provides access to metadata about the parsed expression
+ * including the data binding context and tokens that constitute
+ * the expression.
+ */
+public abstract class Expression {
+
+    /**
+     * Get the expression's data binding context.
+     */
+    public abstract String getContext();
+
+    /**
+     * Get the expression's token list.  For an expression that looks like
+     * "actionForm.customer.name", this will include the tokens "actionForm",
+     * "customer", and "name".
+     */
+    public abstract List getTokens();
+
+    /**
+     * Return an expression that is created starting with the
+     * token at the given index.
+     *
+     * @throws {@link java.lang.IllegalStateException} if the provided start token is out of bounds
+     *                given the number of tokens in the expression
+     */
+    public abstract String getExpression(int start);
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEngineFactory.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEngineFactory.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEngineFactory.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEngineFactory.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,27 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.script;
+
+/**
+ *
+ */
+public abstract class ExpressionEngineFactory {
+
+    public abstract ExpressionEvaluator getInstance();
+}
+

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluationException.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluationException.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluationException.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluationException.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,117 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.script;
+
+// java imports
+
+// internal imports
+
+// external imports
+
+/**
+ * The most general exception thrown when an error occurs in evaluating
+ * an expression.
+ */
+public class ExpressionEvaluationException
+        extends Exception {
+
+    private String expression = null;
+    private String[] contexts = null;
+    private String localizedMessage = null;
+
+    /**
+     * Construct an ExpressionEvaluationException.
+     */
+    public ExpressionEvaluationException() {
+        super();
+    }
+
+    /**
+     * Construct an ExpressionEvaluationException with the given message and
+     * the failed expression.
+     *
+     * @param message    a String containing the text of the exception message
+     * @param expression the expression whose evaluation failed
+     */
+    public ExpressionEvaluationException(String message, String expression) {
+        super(message);
+        this.expression = expression;
+    }
+
+    /**
+     * Construct an ExpressionEvaluationException with the given message,
+     * the failed expression, and cause.
+     *
+     * @param message    a String containing the text of the exception message
+     * @param expression the expression whose evaluation failed
+     * @param cause      a <code>Throwable</code> that is wrapped by this exception
+     */
+    public ExpressionEvaluationException(String message, String expression, Throwable cause) {
+        super(message, cause);
+        this.expression = expression;
+    }
+
+    /**
+     * Construct a ExpressionEvaluationException with the given <code>message</code> and <code>cause</code>.
+     *
+     * @param expression a String containing the text of the exception message
+     * @param cause      a <code>Throwable</code> that is wrapped by this exception
+     */
+    public ExpressionEvaluationException(String expression, Throwable cause) {
+        super(cause);
+        this.expression = expression;
+    }
+
+    /**
+     * Get the expression whose failed evaluation cause this exception to be thrown.
+     *
+     * @return the expression that caused the problem
+     */
+    public String getExpression() {
+        return expression;
+    }
+
+    /**
+     * Set the set of top-level contexts that were available at the time
+     * that the expression failed.
+     *
+     * @param contexts the list of available contexts.
+     */
+    public void setAvailableContexts(String[] contexts) {
+        this.contexts = contexts;
+    }
+
+    /**
+     * Get the top-level contexts that were available at the time that the
+     * expression failed.
+     *
+     * @return the contexts that were available at the time the expression was evaluated or <code>null</code>
+     *         if the contexts were not set.
+     */
+    public String[] getAvailableContexts() {
+        return contexts;
+    }
+
+    public void setLocalizedMessage(String localizedMessage) {
+        this.localizedMessage = localizedMessage;
+    }
+
+    public String getLocalizedMessage() {
+        return localizedMessage;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluator.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluator.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluator.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluator.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,109 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.script;
+
+import javax.servlet.jsp.el.VariableResolver;
+
+/**
+ * An interface for evaluating expressions in NetUI.  Different languages may implement
+ * this to expose the language for use in the NetUI JSP tags.
+ */
+public interface ExpressionEvaluator {
+
+    /**
+     * Evaluate an expression and return the result.
+     *
+     * @param expression       the expression to evaluate
+     * @param variableResolver the set of contexts that may be used in expression evaluation.  This set
+     *                         is not necessarily complete as some objects that can be used as top-level expression contexts
+     *                         may be contained within an object available in this JavaBean.
+     * @throws ExpressionEvaluationException when an error occurs
+     */
+    public Object evaluateStrict(String expression, VariableResolver variableResolver)
+            throws ExpressionEvaluationException;
+
+    /**
+     * Update an expression with the given value.  This will apply the parameter <code>value</code>
+     * to the object referenced by the expression <code>expression</code>.  The <code>requestParameter</code>
+     * flag is used by a caller to restrict the set of contexts into which an update can occur on
+     * the request.
+     *
+     * @param expression       the expression whose value to update
+     * @param value            the new value for the update
+     * @param variableResolver the set of contexts that may be used in expression evaluation.  This set
+     *                         is not necessarily complete as some objects that can be used as top-level expression contexts
+     *                         may be contained within an object available in this JavaBean.
+     * @param requestParameter a boolean that marks this update as occurring from data in the request, if
+     *                         <code>true</code> or simply as a regular update.
+     */
+    public void update(String expression, Object value, VariableResolver variableResolver, boolean requestParameter)
+            throws ExpressionUpdateException;
+
+    /**
+     * Change the evaluation context of an expression.  This is used to rewrite some expressions
+     * that need to be qualified into a different context for evaluation.  The context
+     * of an expression is its first identifier, up to the first delimiter.
+     *
+     * @param expression  the expression whose context to change
+     * @param oldContext  the old context to replace, if present
+     * @param newContext  the new context to replace if the expression starts with the <code>oldContext</code>
+     * @param lookupIndex an index used to qualify an expression into an array look-up.
+     * @exclude
+     */
+    public String changeContext(String expression, String oldContext, String newContext, int lookupIndex)
+            throws ExpressionEvaluationException;
+
+    /**
+     * Qualify the expression into the given context.  This will take the <code>expression</code>
+     * and simply qualify it into the new context <code>contextName</code>.
+     *
+     * @param contextName the new context
+     * @param expression  the expression to qualify
+     * @exclude
+     */
+    public String qualify(String contextName, String expression)
+            throws ExpressionEvaluationException;
+
+    /**
+     * Checks to see if a particular String is exactly an expression.
+     *
+     * @param expression the expression to check
+     * @return <code>true</code> if the expression is exactly an expression; <code>false</code> otherwise.
+     * @throws IllegalExpressionException if the given expression <code>expression</code> is not legal.
+     */
+    public boolean isExpression(String expression);
+
+    /**
+     * Checks to see if a particular expression contains an expression.  This method will return
+     * <code>true</code> if there is an expression surrounded by whitespace, other expressions,
+     * or literal text.
+     *
+     * @param expression the expression to check
+     * @return <code>true</code> if the expression contains an expression; <code>false</code> otherwise.
+     */
+    public boolean containsExpression(String expression);
+
+    /**
+     * Parse an atomic expression into a common parsed expression
+     * representation.
+     *
+     * @param expression the String expression to parse
+     * @return the parsed expression
+     */
+    public Expression parseExpression(String expression);
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluatorFactory.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluatorFactory.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluatorFactory.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionEvaluatorFactory.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,148 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.script;
+
+import org.apache.ti.schema.config.ExpressionLanguages;
+import org.apache.ti.schema.config.ExpressionLanguages.ExpressionLanguage;
+import org.apache.ti.schema.config.NetuiConfigDocument.NetuiConfig;
+import org.apache.ti.util.config.ConfigUtil;
+import org.apache.ti.util.logging.Logger;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Get an expression evaluator.
+ */
+public class ExpressionEvaluatorFactory {
+
+    private static final Logger _logger = Logger.getInstance(ExpressionEvaluatorFactory.class);
+
+    private static final HashMap FACTORY_MAP = new HashMap();
+    private static ExpressionEngineFactory DEFAULT_FACTORY;
+
+    static {
+        try {
+            DEFAULT_FACTORY = initialize(FACTORY_MAP);
+        } catch (Exception e) {
+            DEFAULT_FACTORY = null;
+
+            if (_logger.isErrorEnabled())
+                _logger.error("An exception occurred loading the expression evaluator configuration.  Cause: " + e, e);
+        }
+    }
+
+    /**
+     * Get the default instance of an expression evaluator.
+     *
+     * @return an {@link ExpressionEvaluator}
+     */
+    public final static ExpressionEvaluator getInstance() {
+        return getInstance(null);
+    }
+
+    /**
+     * Get an {@link ExpressionEvaluator} named <code>name</code>.
+     *
+     * @return an ExpressionEvaluator matching the given name.
+     * @throws IllegalArgumentException if an ExpressionEvaluator matching the name is not found
+     */
+    public final static ExpressionEvaluator getInstance(String name) {
+        assert DEFAULT_FACTORY != null;
+        assert FACTORY_MAP != null;
+
+        if (name == null)
+            return DEFAULT_FACTORY.getInstance();
+        else if (FACTORY_MAP.containsKey(name))
+            return ((ExpressionEngineFactory) FACTORY_MAP.get(name)).getInstance();
+
+        String msg = "An ExpressionEvaluator named \"" + name + "\" is not available.";
+        if (_logger.isErrorEnabled())
+            _logger.error(msg);
+
+        throw new IllegalArgumentException(msg);
+    }
+
+    private static final ExpressionEngineFactory initialize(Map factoryMap) {
+        assert factoryMap != null;
+
+        NetuiConfig config = ConfigUtil.getConfig();
+        assert config != null;
+
+        ExpressionLanguages languages = config.getExpressionLanguages();
+        assert languages != null;
+
+        ExpressionLanguage[] array = languages.getExpressionLanguageArray();
+        assert array != null;
+
+        for (int i = 0; i < array.length; i++) {
+            String name = array[i].getName();
+            String className = array[i].getFactoryClass();
+
+            ExpressionEngineFactory factory = null;
+            try {
+                Class type = Class.forName(className);
+                factory = (ExpressionEngineFactory) type.newInstance();
+            } catch (ClassNotFoundException cnf) {
+                if (_logger.isWarnEnabled())
+                    _logger.warn("Could not create an ExpressionEngineFactory for type \"" + className +
+                            "\" because the implementation class could not be found.");
+
+                continue;
+            } catch (Exception ex) {
+                assert ex instanceof IllegalAccessException || ex instanceof InstantiationException;
+
+                if (_logger.isWarnEnabled())
+                    _logger.warn("Could not create an ExpressionEngineFactory for type \"" + className +
+                            "\" because an error occurred creating the factory.  Cause: " + ex, ex);
+                continue;
+            }
+
+            if (factoryMap.containsKey(name))
+                if (_logger.isWarnEnabled())
+                    _logger.warn("Overwriting a previously defined ExpressionEngineFactory named \"" + name +
+                            "\" with a new ExpressionEngineFactory of type \"" + className + "\"");
+                else
+                    _logger.info("Adding an ExpressionEngineFactory named \"" + name + "\" with implementation \"" + className + "\"");
+
+            factoryMap.put(name, factory);
+        }
+
+        ExpressionEngineFactory defaultEngineFactory = null;
+        String defaultLanguage = languages.getDefaultLanguage();
+        if (defaultLanguage != null) {
+            defaultEngineFactory = (ExpressionEngineFactory) factoryMap.get(defaultLanguage);
+            if (defaultEngineFactory != null) {
+                if (_logger.isInfoEnabled())
+                    _logger.info("Using a default expression evaluator of type \"" + factoryMap.get(defaultLanguage).getClass().getName() + "\"");
+            } else {
+                String msg =
+                        "The default ExpressionEvaluator named \"" + defaultLanguage + "\" was specified, but the ExpressionEngineFactory could not be found.";
+                if (_logger.isWarnEnabled()) _logger.warn(msg);
+
+                throw new RuntimeException(msg);
+            }
+        } else {
+            String msg = "There is no default expression engine specified.";
+            if (_logger.isErrorEnabled()) _logger.error(msg);
+            throw new RuntimeException(msg);
+        }
+
+        return defaultEngineFactory;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionUpdateException.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionUpdateException.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionUpdateException.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/ExpressionUpdateException.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,74 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.script;
+
+// java imports
+
+// internal imports
+
+// external imports
+
+/**
+ * An exception thrown when an error occurs during an expression update.
+ */
+public class ExpressionUpdateException
+        extends ExpressionEvaluationException {
+
+    /**
+     * Construct an ExpressionUpdateException.
+     */
+    public ExpressionUpdateException() {
+        super();
+    }
+
+    /**
+     * Construct an ExpressionUpdateException with the given message, failed expression, expected updated value,
+     * and expression that was used to perform the update.
+     *
+     * @param message    a String containing the text of the exception message
+     * @param expression the expression whose update failed
+     * @param cause      the <code>Throwable</code> that is wrapped as the cause of this exception
+     */
+    public ExpressionUpdateException(String message, String expression, Throwable cause) {
+        super(message, expression, cause);
+    }
+
+    /**
+     * Construct an ExpressionUpdateException with the given message, failed expression, expected updated value,
+     * and expression that was used to perform the update.
+     *
+     * @param message    a String containing the text of the exception message
+     * @param expression the expression whose update failed
+     */
+    public ExpressionUpdateException(String message, String expression) {
+        super(message, expression);
+    }
+
+    /**
+     * Get the value that should have been written to the object
+     * referenced by the failed update expression.  This method is deprecated
+     * and will always return null because of the security risk associated
+     * with making the value available.
+     *
+     * @return the failed update value
+     * @deprecated
+     */
+    public Object getUpdateValue() {
+        return null;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/IllegalExpressionException.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/IllegalExpressionException.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/IllegalExpressionException.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/IllegalExpressionException.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,101 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.script;
+
+// java imports
+
+// internal imports
+
+// external imports
+
+/**
+ * An exception thrown when an expression is written in an illegal syntax.
+ */
+public class IllegalExpressionException
+        extends RuntimeExpressionException {
+
+    private String expression = null;
+
+    /**
+     * Construct an IllegalExpressionException.
+     */
+    public IllegalExpressionException() {
+        super();
+    }
+
+    /**
+     * Construct an IllegalExpressionException with the given message.
+     *
+     * @param message a String containing the text of the exception message
+     */
+    public IllegalExpressionException(String message) {
+        super(message);
+    }
+
+    /**
+     * Construct an IllegalExpressionException with the given cause
+     *
+     * @param cause a <code>Throwable<code> that caused this exception to be thrown
+     */
+    public IllegalExpressionException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Construct an IllegalExpressionException with the given <code>message</code> and <code>cause</code>.
+     *
+     * @param message a String containing the text of the exception message
+     * @param cause   a <code>Throwable</code> that caused this exception to be thrown
+     */
+    public IllegalExpressionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Construct an IllegalExpressionException with the given <code>message</code> and the malformed expression.
+     *
+     * @param message    a String containing the text of this exception message
+     * @param expression the expression that was malformed and caused this exception to be thrown
+     */
+    public IllegalExpressionException(String message, String expression) {
+        this(message);
+        this.expression = expression;
+    }
+
+    /**
+     * Construct an IllegalExpressionException with the given <code>message</code>, the malformed expression, and the <code>cause</code>.
+     *
+     * @param message    a String containing the text of this exception message
+     * @param expression the expression that was malformed and caused this exception to be thrown
+     * @param cause      a <code>Throwable</code> that caused this exception to be thrown
+     */
+    public IllegalExpressionException(String message, String expression, Throwable cause) {
+        this(message, cause);
+        this.expression = expression;
+    }
+
+    /**
+     * Get the malformed expression.
+     *
+     * @return the malformed expression
+     */
+    public String getExpression() {
+        return expression;
+    }
+}
+

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/RuntimeExpressionException.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/RuntimeExpressionException.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/RuntimeExpressionException.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/RuntimeExpressionException.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,57 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.script;
+
+// java imports
+
+// internal imports
+
+// external imports
+
+/**
+ *
+ */
+public abstract class RuntimeExpressionException
+        extends RuntimeException {
+
+    private String localizedMessage = null;
+
+    public RuntimeExpressionException() {
+        super();
+    }
+
+    public RuntimeExpressionException(String message) {
+        super(message);
+    }
+
+    public RuntimeExpressionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public RuntimeExpressionException(Throwable cause) {
+        super(cause);
+    }
+
+    public void setLocalizedMessage(String localizedMessage) {
+        this.localizedMessage = localizedMessage;
+    }
+
+    public String getLocalizedMessage() {
+        return (localizedMessage != null ? localizedMessage : getMessage());
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/common/AbstractScriptableMap.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/common/AbstractScriptableMap.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/common/AbstractScriptableMap.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/script/common/AbstractScriptableMap.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,130 @@
+/*
+ * Copyright 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.script.common;
+
+import org.apache.ti.util.iterator.IteratorFactory;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Base {@link java.util.Map} implementation that can be used by
+ * clients that need to expose implicit objects to an expression
+ * language through a Map.  This Map implementation is read-only.
+ */
+public abstract class AbstractScriptableMap
+        extends AbstractMap {
+
+    /**
+     * Default implementation of a {@link java.util.Set} that can be returned by the
+     * entrySet method of {@link java.util.Map}.  This implementation simply takes an
+     * array of entries and implements iterator() and size().
+     */
+    class EntrySet
+            extends AbstractSet {
+
+        private Entry[] _entries = null;
+
+        public EntrySet(Entry[] entries) {
+            _entries = entries;
+        }
+
+        public Iterator iterator() {
+            return IteratorFactory.createIterator(_entries);
+        }
+
+        public int size() {
+            return _entries != null ? _entries.length : 0;
+        }
+
+        public boolean add(Object object) {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean addAll(Collection coll) {
+            throw new UnsupportedOperationException();
+        }
+
+        public void clear() {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean remove(Object object) {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean removeAll(Collection coll) {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean retainAll(Collection coll) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    /**
+     * Default implementation of {@link java.util.Map.Entry} that handles
+     * key / value pairs in a very basic way.  This is meant as a convenience
+     * to subclasses that need to provide an entrySet() to satisfy the
+     * {@link java.util.AbstractMap} contract.
+     */
+    class Entry
+            implements Map.Entry {
+
+        private final Object _key;
+        private final Object _value;
+
+        Entry(Object key, Object value) {
+            _key = key;
+            _value = value;
+        }
+
+        public Object getKey() {
+            return _key;
+        }
+
+        public Object getValue() {
+            return _value;
+        }
+
+        public Object setValue(Object value) {
+            throw new UnsupportedOperationException();
+        }
+
+        public int hashCode() {
+            return ((_key == null ? 0 : _key.hashCode()) ^ (_value == null ? 0 : _value.hashCode()));
+        }
+
+        public boolean equals(Object obj) {
+            if (obj == null || !(obj instanceof Map.Entry))
+                return false;
+
+            Map.Entry entry = (Map.Entry) obj;
+            Object key = entry.getKey();
+            Object value = entry.getValue();
+            if ((key == null || (key != null && key.equals(_key))) &&
+                    (value == null || (value != null && value.equals(_value))))
+                return true;
+
+            return false;
+        }
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Mime
View raw message