You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by mr...@apache.org on 2005/08/26 07:46:58 UTC

svn commit: r240168 [12/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...

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/InternalUtils.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/InternalUtils.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/InternalUtils.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/InternalUtils.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,675 @@
+/*
+ * 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.pageflow.internal;
+
+import org.apache.commons.chain.web.WebContext;
+import org.apache.commons.chain.web.servlet.ServletWebContext;
+import org.apache.ti.Globals;
+import org.apache.ti.core.ActionMessage;
+import org.apache.ti.pageflow.ActionResolver;
+import org.apache.ti.pageflow.FacesBackingBean;
+import org.apache.ti.pageflow.FlowControllerException;
+import org.apache.ti.pageflow.ModuleConfig;
+import org.apache.ti.pageflow.PageFlowConstants;
+import org.apache.ti.pageflow.PageFlowController;
+import org.apache.ti.pageflow.SessionExpiredException;
+import org.apache.ti.pageflow.handler.Handlers;
+import org.apache.ti.pageflow.handler.ModuleRegistrationHandler;
+import org.apache.ti.pageflow.handler.ReloadableClassHandler;
+import org.apache.ti.pageflow.handler.StorageHandler;
+import org.apache.ti.pageflow.xwork.PageFlowAction;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+import org.apache.ti.schema.config.PageflowConfig;
+import org.apache.ti.util.Bundle;
+import org.apache.ti.util.MessageResources;
+import org.apache.ti.util.config.ConfigUtil;
+import org.apache.ti.util.internal.InternalStringBuilder;
+import org.apache.ti.util.internal.ServletUtils;
+import org.apache.ti.util.logging.Logger;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+
+
+public class InternalUtils
+        implements PageFlowConstants, InternalConstants {
+
+    private static final Logger _log = Logger.getInstance(InternalUtils.class);
+
+    private static final String LONGLIVED_PAGEFLOWS_ATTR_PREFIX = ATTR_PREFIX + "longLivedPageFlow:";
+    private static final String ACTIONOUTPUT_MAP_ATTR = ATTR_PREFIX + "actionOutputs";
+    private static final String BINDING_UPDATE_ERRORS_ATTR = ATTR_PREFIX + "bindingUpdateErrors";
+    private static final String SHARED_FLOW_CLASSNAME_ATTR = ATTR_PREFIX + "sharedFlowClass";
+    private static final String AVOID_DIRECT_RESPONSE_OUTPUT_ATTR = ATTR_PREFIX + "_avoidDirectResponseOutput";
+    private static final String FORWARDED_FORMBEAN_ATTR = ATTR_PREFIX + "forwardedForm";
+    private static final String FORWARDING_MODULE_ATTR = ATTR_PREFIX + "forwardingModule";
+    private static final String IGNORE_INCLUDE_SERVLET_PATH_ATTR = ATTR_PREFIX + "ignoreIncludeServletPath";
+
+
+    /**
+     * If not in production mode, write an error to the response; otherwise, set a response error code.
+     */
+    public static void sendDevTimeError(String messageKey, Throwable cause, int productionTimeErrorCode,
+                                        Object[] messageArgs) {
+        // TODO: re-add this
+    }
+
+    /**
+     * Write an error to the response.
+     */
+    public static void sendError(String messageKey, Throwable cause, Object[] messageArgs) {
+        sendError(messageKey, messageArgs, cause, avoidDirectResponseOutput());
+    }
+
+    /**
+     * Write an error to the response.
+     */
+    public static void sendError(String messageKey, Object[] messageArgs, Throwable cause,
+                                 boolean avoidDirectResponseOutput) {
+        assert messageArgs.length == 0 || !(messageArgs[0] instanceof Object[])
+                : "Object[] passed to sendError; this is probably a mistaken use of varargs";
+        
+        // request may be null because of deprecated FlowController.sendError().
+        if (avoidDirectResponseOutput) {
+            String baseMessage = Bundle.getString(messageKey + "_Message", messageArgs);
+            throw new ResponseOutputException(baseMessage, cause);
+        }
+
+        String html = Bundle.getString(messageKey + "_Page", messageArgs);
+        // TODO re-add
+        //ServletUtils.writeHtml(getWebContext(), html, true);
+        System.err.println(html);
+        throw new UnsupportedOperationException("NYI -- HTML is: \n" + html); // TODO: NYI        
+    }
+
+    /**
+     * Get a Method in a Class.
+     *
+     * @param parentClass the Class in which to find the Method.
+     * @param methodName  the name of the Method.
+     * @param signature   the argument types for the Method.
+     * @return the Method with the given name and signature, or <code>null</code> if the method does not exist.
+     */
+    public static Method lookupMethod(Class parentClass, String methodName, Class[] signature) {
+        try {
+            return parentClass.getDeclaredMethod(methodName, signature);
+        } catch (NoSuchMethodException e) {
+            Class superClass = parentClass.getSuperclass();
+            return superClass != null ? lookupMethod(superClass, methodName, signature) : null;
+        }
+    }
+
+    public static String getLongLivedFlowAttr(String namespace) {
+        return LONGLIVED_PAGEFLOWS_ATTR_PREFIX + namespace;
+    }
+
+    public static void setCurrentPageFlow(PageFlowController jpf) {
+        setCurrentActionResolver(jpf);
+    }
+
+    public static void removeCurrentPageFlow() {
+        StorageHandler sh = Handlers.get().getStorageHandler();
+        String currentJpfAttrName = getScopedAttrName(CURRENT_JPF_ATTR);
+        String currentLongLivedAttrName = getScopedAttrName(CURRENT_LONGLIVED_ATTR);
+        sh.removeAttribute(currentJpfAttrName);
+        sh.removeAttribute(currentLongLivedAttrName);
+    }
+
+    public static void removeCurrentFacesBackingBean() {
+        StorageHandler sh = Handlers.get().getStorageHandler();
+        String attrName = getScopedAttrName(FACES_BACKING_ATTR);
+        sh.removeAttribute(attrName);
+    }
+
+    public static void addActionOutputs(Map toAdd, boolean overwrite) {
+        if (toAdd != null) {
+            Map map = getActionOutputMap(true);
+
+            for (Iterator i = toAdd.entrySet().iterator(); i.hasNext();) {
+                Map.Entry entry = (Map.Entry) i.next();
+                String name = (String) entry.getKey();
+                boolean alreadyExists = map.containsKey(name);
+
+                if (overwrite || !alreadyExists) {
+                    if (alreadyExists) {
+                        if (_log.isWarnEnabled()) {
+                            _log.warn("Overwriting action output \"" + name + "\".");
+                        }
+                    }
+
+                    map.put(name, entry.getValue());
+                }
+            }
+        }
+    }
+
+    public static void addActionError(String propertyName, ActionMessage error) {
+        /* TODO: re-add error/message support
+        ActionErrors errors = ( ActionErrors ) request.getAttribute( Globals.ERROR_KEY );
+        if ( errors == null ) request.setAttribute( Globals.ERROR_KEY, errors = new ActionErrors() );
+        errors.add( propertyName, error );
+        */
+    }
+
+    public static Object newReloadableInstance(String className)
+            throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+        return getReloadableClass(className).newInstance();
+    }
+
+    public static Class getReloadableClass(String className)
+            throws ClassNotFoundException {
+        ReloadableClassHandler handler = Handlers.get().getReloadableClassHandler();
+        return handler.loadClass(className);
+    }
+
+    public static Map getActionOutputMap(boolean createIfNotExist) {
+        Map requestScope = PageFlowActionContext.get().getRequestScope();
+        Map map = (Map) requestScope.get(ACTIONOUTPUT_MAP_ATTR);
+
+        if (map == null && createIfNotExist) {
+            map = new HashMap();
+            requestScope.put(ACTIONOUTPUT_MAP_ATTR, map);
+        }
+
+        return map;
+    }
+
+    public static Map getPageInputMap() {
+        Map actionOutputsFromPageFlow = getActionOutputMap(false);
+        if (actionOutputsFromPageFlow != null) return actionOutputsFromPageFlow;
+        FacesBackingBean fbb = getFacesBackingBean();
+        return fbb != null ? fbb.getPageInputMap() : null;
+    }
+
+    /**
+     * Add a BindingUpdateError to the request.
+     *
+     * @param expression the expression associated with this error.
+     * @param message    the error message.
+     * @param cause      the Throwable that caused the error.
+     */
+    public static void addBindingUpdateError(String expression, String message, Throwable cause) {
+        Map errors = (Map) getWebContext().getRequestScope().get(BINDING_UPDATE_ERRORS_ATTR);
+
+        if (errors == null) {
+            errors = new LinkedHashMap();
+            getWebContext().getRequestScope().put(BINDING_UPDATE_ERRORS_ATTR, errors);
+        }
+
+        errors.put(expression, new BindingUpdateError(expression, message, cause));
+    }
+
+    /**
+     * Get a map of BindingUpdateErrors stored in the request.
+     *
+     * @return a Map of expression (String) -> BindingUpdateError.
+     */
+    public static Map getBindingUpdateErrors() {
+        return (Map) getWebContext().getRequestScope().get(BINDING_UPDATE_ERRORS_ATTR);
+    }
+
+    public static WebContext getWebContext() {
+        return PageFlowActionContext.get().getWebContext();
+    }
+
+    /**
+     * Set the given form in either the request or session, as appropriate, so Struts/NetUI
+     * tags will have access to it.
+     */
+    public static void setFormInScope(String formAttribute, Object formBean, boolean overwrite) {
+        if (formBean != null) {
+            //String formName = PageFlowActionContext.getContext().getAction().getFormBeanAttribute();
+            assert formAttribute != null;
+
+            if (overwrite || getWebContext().getRequestScope().get(formAttribute) == null) {
+                getWebContext().getRequestScope().put(formAttribute, formBean);
+            }
+        }
+    }
+
+    public static Object getFormBean(PageFlowAction action) {
+        String attrName = action.getFormBeanAttribute();
+
+        if (attrName != null) {
+            return getWebContext().getRequestScope().get(attrName);
+        }
+
+        return null;
+    }
+
+    /**
+     * Set the current ActionResolver ({@link PageFlowController}) in the user session.
+     *
+     * @param resolver the ActionResolver to set as the current one in the user session.
+     */
+    public static void setCurrentActionResolver(ActionResolver resolver) {
+        StorageHandler sh = Handlers.get().getStorageHandler();
+        String currentJpfAttrName = getScopedAttrName(CURRENT_JPF_ATTR);
+        String currentLongLivedJpfAttrName = getScopedAttrName(CURRENT_LONGLIVED_ATTR);
+
+        if (resolver == null) {
+            sh.removeAttribute(currentJpfAttrName);
+            sh.removeAttribute(currentLongLivedJpfAttrName);
+            return;
+        }
+        
+        //
+        // If this is a long-lived page flow, also store the instance in an attribute that never goes away.
+        //
+        if (resolver.getModuleConfig().isLongLivedFlow()) {
+            String longLivedAttrName = getLongLivedFlowAttr(resolver.getNamespace());
+            longLivedAttrName = getScopedAttrName(longLivedAttrName);
+            
+            // Only set this attribute if it's not already there.  We want to avoid our onDestroy() callback that's
+            // invoked when the page flow's session attribute is unbound.
+            if (sh.getAttribute(longLivedAttrName) != resolver) {
+                sh.setAttribute(longLivedAttrName, resolver);
+            }
+
+            sh.setAttribute(currentLongLivedJpfAttrName, resolver.getNamespace());
+            sh.removeAttribute(currentJpfAttrName);
+        } else {
+            sh.setAttribute(currentJpfAttrName, resolver);
+            sh.removeAttribute(currentLongLivedJpfAttrName);
+        }
+    }
+
+    public static String getFlowControllerClassName(String namespace) {
+        assert namespace != null;
+        ModuleRegistrationHandler mrh = Handlers.get().getModuleRegistrationHandler();
+        ModuleConfig moduleConfig = mrh.getModuleConfig(namespace);
+        return moduleConfig != null ? moduleConfig.getControllerClassName() : null;
+    }
+
+    public static FacesBackingBean getFacesBackingBean() {
+        StorageHandler sh = Handlers.get().getStorageHandler();
+        String attrName = getScopedAttrName(FACES_BACKING_ATTR);
+        return (FacesBackingBean) sh.getAttribute(attrName);
+    }
+
+    public static String inferNamespaceFromClassName(String className) {
+        int lastDot = className.lastIndexOf('.');
+
+        if (lastDot != -1) {
+            className = className.substring(0, lastDot);
+            return '/' + className.replace('.', '/');
+        } else {
+            return "/";
+        }
+    }
+
+    public static PageflowConfig.MultipartHandler.Enum getMultipartHandlerType() {
+        PageflowConfig pfConfig = ConfigUtil.getConfig().getPageflowConfig();
+        return pfConfig != null ? pfConfig.getMultipartHandler() : null;
+    }
+
+    /**
+     * Simply adds the context path and parent directory, based on the current request URI.
+     */
+    public static String createActionURL(String qualifiedAction) {
+        PageFlowActionContext actionContext = PageFlowActionContext.get();
+        String pageURI = actionContext.getRequestURI();
+        int lastSlash = pageURI.lastIndexOf('/');
+
+        if (lastSlash != -1) {
+            InternalStringBuilder value = new InternalStringBuilder(qualifiedAction.length() + lastSlash);
+            value.append(pageURI.substring(0, lastSlash));
+            value.append(qualifiedAction);
+            return value.toString();
+        }
+
+        return qualifiedAction;
+    }
+
+    public static String createActionPath(String qualifiedAction) {
+        ModuleConfig moduleConfig = PageFlowActionContext.get().getModuleConfig();
+
+
+        if (moduleConfig != null) {
+            InternalStringBuilder value = new InternalStringBuilder(qualifiedAction.length() + 16);
+            value.append(moduleConfig.getNamespace());
+            value.append(qualifiedAction);
+            return value.toString();
+        }
+
+        return qualifiedAction;
+    }
+
+    public static String qualifyAction(String action) {
+        assert action != null;
+        InternalStringBuilder sb = null;
+
+        String queryString = null;
+        int question = action.indexOf('?');
+        if (question >= 0) queryString = action.substring(question);
+
+        String actionMapping = getActionMappingName(action);
+        sb = new InternalStringBuilder(action.length() + ACTION_EXTENSION_LEN + 1);
+        sb.append(actionMapping);
+        sb.append(ACTION_EXTENSION);
+        if (queryString != null) sb.append(queryString);
+
+        return sb.toString();
+    }
+
+    /**
+     * Return the form action converted into an action mapping path.  The
+     * value of the <code>action</code> property is manipulated as follows in
+     * computing the name of the requested mapping:
+     * <ul>
+     * <li>Any filename extension is removed (on the theory that extension
+     * mapping is being used to select the controller servlet).</li>
+     * <li>If the resulting value does not start with a slash, then a
+     * slash is prepended.</li>
+     * </ul>
+     *
+     * @param action the action name to be converted.
+     * @return an action path, suitable for lookup in the Struts configuration file.
+     */
+    public static String getActionMappingName(String action) {
+        return getCleanActionName(action, true);
+    }
+
+    public static String getCleanActionName(String action, boolean prependSlash) {
+        int question = action.indexOf('?');
+        if (question >= 0) {
+            action = action.substring(0, question);
+        }
+
+        if (action.endsWith(ACTION_EXTENSION)) {
+            action = action.substring(0, action.length() - ACTION_EXTENSION_LEN);
+        }
+
+        if (action.charAt(0) == '/') {
+            if (!prependSlash) action = action.substring(1);
+        } else {
+            if (prependSlash) action = '/' + action;
+        }
+
+        return action;
+    }
+
+
+    /**
+     * Add a parameter to the given URL. Assumes there is no trailing
+     * anchor/fragment indicated with a '#'.
+     *
+     * @param url       the URL to which to append.
+     * @param paramName the name of the parameter to add.
+     * @param paramVal  the value of the parameter to add.
+     * @return the URL, with the given parameter added.
+     */
+    public static String addParam(String url, String paramName, String paramVal) {
+        return url + (url.indexOf('?') != -1 ? '&' : '?') + paramName + '=' + paramVal;
+    }
+
+    public static void throwPageFlowException(FlowControllerException effect)
+            throws FlowControllerException {
+        if (effect.causeMayBeSessionExpiration() && ServletUtils.isSessionExpired(getWebContext())) {
+            PageflowConfig pfc = ConfigUtil.getConfig().getPageflowConfig();
+            if (pfc == null || !pfc.isSetThrowSessionExpiredException() || pfc.getThrowSessionExpiredException()) {
+                throw new SessionExpiredException(effect);
+            }
+        }
+
+        throw effect;
+    }
+
+    /**
+     * Get the request URI, relative to the URI of the given PageFlowController.
+     *
+     * @param relativeTo a PageFlowController to which the returned URI should be relative, or
+     *                   <code>null</code> if the returned URI should be relative to the webapp root.
+     */
+    public static final String getRelativeURI(PageFlowController relativeTo) {
+        PageFlowActionContext actionContext = PageFlowActionContext.get();
+        if (relativeTo == null) return actionContext.getRequestPath();
+        return getRelativeURI(actionContext.getRequestURI(), relativeTo);
+    }
+
+    /**
+     * Get a URI relative to the URI of the given PageFlowController.
+     *
+     * @param uri        the URI which should be made relative.
+     * @param relativeTo a PageFlowController to which the returned URI should be relative, or
+     *                   <code>null</code> if the returned URI should be relative to the webapp root.
+     */
+    public static final String getRelativeURI(String uri, PageFlowController relativeTo) {
+        String contextPath = PageFlowActionContext.get().getRequestPath();
+        if (relativeTo != null) contextPath += relativeTo.getNamespace();
+        int overlap = uri.indexOf(contextPath + '/');
+        if (overlap == -1) return null;
+        return uri.substring(overlap + contextPath.length());
+    }
+
+    /**
+     * Set the forwarded form.  This overrides the auto-generated form created by processActionForm
+     * and populated by processPopulate (in PageFlowRequestProcessor).
+     */
+    public static void setForwardedFormBean(Object formBean) {
+        if (formBean == null) {
+            getWebContext().getRequestScope().remove(FORWARDED_FORMBEAN_ATTR);
+        } else {
+            getWebContext().getRequestScope().put(FORWARDED_FORMBEAN_ATTR, formBean);
+        }
+    }
+
+    public static Object getForwardedFormBean(boolean removeFromRequest) {
+        Map requestScope = getWebContext().getRequestScope();
+        Object form = requestScope.get(FORWARDED_FORMBEAN_ATTR);
+        if (removeFromRequest) requestScope.remove(FORWARDED_FORMBEAN_ATTR);
+        return form;
+    }
+
+    /**
+     * Tell whether a special request attribute was set, indicating that we should avoid writing to the response (or
+     * setting response error codes).
+     */
+    public static boolean avoidDirectResponseOutput() {
+        Boolean avoid = (Boolean) getWebContext().getRequestScope().get(AVOID_DIRECT_RESPONSE_OUTPUT_ATTR);
+        return avoid != null && avoid.booleanValue();
+    }
+
+    /**
+     * Set a special request attribute to indicate that we should avoid writing to the response (or
+     * setting response error codes).
+     */
+    public static void setAvoidDirectResponseOutput() {
+        getWebContext().getRequestScope().put(AVOID_DIRECT_RESPONSE_OUTPUT_ATTR, Boolean.TRUE);
+    }
+
+    /**
+     * Set the module prefix for the ModuleConfig that is performing a forward in this request.
+     */
+    public static void setForwardingModule(String modulePrefix) {
+        getWebContext().getRequestScope().put(FORWARDING_MODULE_ATTR, modulePrefix);
+    }
+
+    /**
+     * Set the module prefix for the ModuleConfig that is performing a forward in this request.
+     */
+    public static String getForwardingModule() {
+        return (String) getWebContext().getRequestScope().get(FORWARDING_MODULE_ATTR);
+    }
+
+    /**
+     * Tell {@link #getRequestPath} (and all that call it) to ignore the attribute that specifies the Servlet
+     * Include path, which is set when a Servlet include is done through RequestDispatcher.  Normally,
+     * getDecodedServletPath tries the Servlet Include path before falling back to getServletPath() on the request.
+     * Note that this is basically a stack of instructions to ignore the include path, and this method expects each
+     * call with <code>ignore</code>==<code>true</code> to be balanced by a call with
+     * <code>ignore</code>==<code>false</code>.
+     */
+    /* TODO: re-add for page template support
+    public static void setIgnoreIncludeServletPath( boolean ignore )
+    {
+        Map requestScope = getWebContext().getRequestScope();
+        Integer depth = ( Integer ) requestScope.get( IGNORE_INCLUDE_SERVLET_PATH_ATTR );
+        
+        if ( ignore )
+        {
+            if ( depth == null ) depth = new Integer( 0 );
+            requestScope.put( IGNORE_INCLUDE_SERVLET_PATH_ATTR, new Integer( depth.intValue() + 1 ) );
+        }
+        else
+        {
+            assert depth != null : "call to setIgnoreIncludeServletPath() was imbalanced";
+            depth = new Integer( depth.intValue() - 1 );
+            
+            if ( depth.intValue() == 0 )
+            {
+                requestScope.remove( IGNORE_INCLUDE_SERVLET_PATH_ATTR );
+            }
+            else
+            {
+                requestScope.put( IGNORE_INCLUDE_SERVLET_PATH_ATTR, depth );
+            }
+        }
+    }
+    */
+
+    public static boolean ignoreIncludeServletPath() {
+        return getWebContext().getRequestScope().get(IGNORE_INCLUDE_SERVLET_PATH_ATTR) != null;
+    }
+
+    /**
+     * Set the given Struts module in the request, and expose its set of MessageResources as request attributes.
+     *
+     * @param namespace the namespace of the desired module.
+     * @return the selected ModuleConfig, or <code>null</code> if there is none for the given module prefix.
+     */
+    public static ModuleConfig selectModule(String namespace) {
+        ModuleRegistrationHandler mrh = Handlers.get().getModuleRegistrationHandler();
+        return selectModule(mrh.getModuleConfig(namespace));
+    }
+
+    public static ModuleConfig selectModule(ModuleConfig config) {
+        PageFlowActionContext actionContext = PageFlowActionContext.get();
+
+        if (config == null) {
+            actionContext.setModuleConfig(null);
+            return null;
+        }
+        
+        // Just return it if it's already registered.
+        if (actionContext.getModuleConfig() == config) return config;
+        actionContext.setModuleConfig(config);       
+
+        /* TODO: re-add messages support
+        MessageResourcesConfig[] mrConfig = config.findMessageResourcesConfigs();
+        Object formBean = PageFlowActionContext.getContext().getAction().getFormBean();
+        
+        for ( int i = 0; i < mrConfig.length; i++ )
+        {
+            String key = mrConfig[i].getKey();
+            MessageResources resources = ( MessageResources ) servletContext.getAttribute( key + prefix );
+            
+            if ( resources != null )
+            {
+                if ( ! ( resources instanceof ExpressionAwareMessageResources ) )
+                {
+                    resources = new ExpressionAwareMessageResources( resources, formBean, request, servletContext );
+                }
+                
+                requestScope.put( key, resources );
+            }
+            else
+            {
+                requestScope.remove( key );
+            }
+        }
+        */
+        
+        return config;
+    }
+
+    public static MessageResources getMessageResources(String bundleName) {
+        PageFlowActionContext actionContext = PageFlowActionContext.get();
+        MessageResources resources = (MessageResources) actionContext.getRequestScope().get(bundleName);
+
+        if (resources == null) {
+            String qualified = getQualifiedBundleName(bundleName);
+            resources = (MessageResources) getWebContext().getApplicationScope().get(qualified);
+        }
+        
+        // If we can't find resources with this name, try them at the root (unqualified).
+        if (resources == null) resources = (MessageResources) getWebContext().getApplicationScope().get(bundleName);
+
+        return resources;
+    }
+
+    /**
+     * Qualify the given bundle name with the current namespace to return a full bundle name.
+     *
+     * @return the qualified Bundle name
+     */
+    public static String getQualifiedBundleName(String bundleName) {
+        if (bundleName != null) {
+            if (bundleName.indexOf('/') == -1) {
+                PageFlowActionContext actionContext = PageFlowActionContext.get();
+                ModuleConfig mc = actionContext.getModuleConfig();
+
+                // Note that we don't append the namespace for the root module.
+                if (mc != null && mc.getNamespace() != null && mc.getNamespace().length() > 1) {
+                    bundleName += mc.getNamespace();
+                }
+            } else if (bundleName.endsWith("/")) {
+                // Special handling for bundles referring to the root module
+                bundleName = bundleName.substring(0, bundleName.length() - 1);
+            }
+        }
+
+        return bundleName;
+    }
+
+    public static Locale lookupLocale() {
+        WebContext webContext = getWebContext();
+        Locale locale = (Locale) webContext.getSessionScope().get(Globals.LOCALE_KEY);
+        if (locale == null && webContext instanceof ServletWebContext) {
+            locale = ((ServletWebContext) webContext).getRequest().getLocale();
+        }
+        return locale;
+    }
+
+    /**
+     * If the request is a ScopedRequest, this returns an attribute name scoped to
+     * that request's scope-ID; otherwise, it returns the given attribute name.
+     */
+    public static String getScopedAttrName(String attrName) {
+        // Now, this is simply handled by the ActionContext implementation.  If it needs to wrap session attribute
+        // names, it does.
+        
+        /*
+        String requestScopeParam = request.getParameter( SCOPE_ID_PARAM );
+        
+        if ( requestScopeParam != null )
+        {
+            return getScopedName( attrName, requestScopeParam );
+        }
+        
+        ScopedRequest scopedRequest = unwrapRequest( request );
+        return scopedRequest != null ? scopedRequest.getScopedName( attrName ) : attrName;
+        */
+        return attrName;
+    }
+
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/JavaControlUtils.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/JavaControlUtils.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/JavaControlUtils.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/JavaControlUtils.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,251 @@
+/*
+ * 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.pageflow.internal;
+
+import org.apache.ti.pageflow.ControlFieldInitializationException;
+import org.apache.ti.pageflow.PageFlowManagedObject;
+
+import java.util.Map;
+
+
+public class JavaControlUtils {
+
+    /* TODO: re-add Controls support (as a Handler)
+    
+    private static final Logger _log = Logger.getInstance( JavaControlUtils.class );
+    private static final String CONTROL_CONTEXT_CLASSNAME = ServletBeanContext.class.getName();
+    private static final String CONTROL_ANNOTATION_CLASSNAME = Control.class.getName();
+    
+    /** Map of control-container-class (e.g., PageFlowController) to Map of fields/control-properties. *
+    private static InternalConcurrentHashMap/*< String, Map< Field, PropertyMap > >* _controlFieldCache =
+            new InternalConcurrentHashMap/*< String, Map< Field, PropertyMap > >*();
+    
+            */
+    public static void initializeControlContext() {
+        /*
+        ControlBeanContext beanContext = getControlBeanContext( request, response, servletContext, true );
+
+        //
+        // Start a new execution context
+        //
+        if ( beanContext instanceof ServletBeanContext )
+        {
+            ( ( ServletBeanContext ) beanContext ).beginContext( servletContext, request, response ); 
+        }
+        */
+    }
+
+    public static void uninitializeControlContext() {
+        /*
+        ControlBeanContext beanContext = getControlBeanContext( request, response, servletContext, false );
+        
+        if ( beanContext instanceof ServletBeanContext )
+        {
+            ( ( ServletBeanContext ) beanContext ).endContext();
+        }
+        */
+    }
+
+    /*
+    public static class ControlInstantiationException
+        extends Exception
+    {
+        private String _controlBeanClassName;
+        
+        public ControlInstantiationException( String controlBeanClassName, Throwable cause_ )
+        {
+            super( cause_ );
+            _controlBeanClassName = controlBeanClassName;
+        }
+
+        public String getControlBeanClassName()
+        {
+            return _controlBeanClassName;
+        }
+    }
+    
+    private static ControlBeanContext getControlBeanContext( HttpServletRequest request, HttpServletResponse response,
+                                                             ServletContext servletContext, boolean createIfMissing )
+    {
+        //
+        // Retrieve the control bean context from the request, and if it's not there, from the session.
+        // Using the request first ensures that we don't get confused by session invalidation.
+        //
+        ControlBeanContext beanContext = ( ControlBeanContext ) request.getAttribute( CONTROL_CONTEXT_CLASSNAME );
+        if ( beanContext != null ) return beanContext;
+        
+        HttpSession session = request.getSession( false );
+        if ( session != null )
+        {
+            beanContext = ( ControlBeanContext ) session.getAttribute( CONTROL_CONTEXT_CLASSNAME );
+            
+            if ( beanContext != null )
+            {
+                request.setAttribute( CONTROL_CONTEXT_CLASSNAME, beanContext );
+                return beanContext;
+            }
+        }
+        
+        //
+        // If no context exists, then create a new one and store it in the session.
+        //
+        if ( createIfMissing )
+        {
+            beanContext = ( ControlBeanContext )
+                AdapterManager.getContainerAdapter( servletContext ).createControlBeanContext( request, response );
+            request.getSession().setAttribute( CONTROL_CONTEXT_CLASSNAME, beanContext );
+            request.setAttribute( CONTROL_CONTEXT_CLASSNAME, beanContext );
+        }
+       
+        return beanContext;
+    }
+    
+    */
+    public static void destroyControl(Object controlInstance) {
+        /*
+        assert controlInstance instanceof ControlBean : controlInstance.getClass().getName();
+        BeanContext beanContext = ( ( ControlBean ) controlInstance ).getBeanContext();
+        if ( beanContext != null ) beanContext.remove( controlInstance ); 
+        */
+    }
+
+
+    /**
+     * @return a map of Field (accessible) -> AnnotationMap
+     */
+    private static Map getAccessibleControlFieldAnnotations(Class controlContainerClass) {
+        /*
+        String className = controlContainerClass.getName();
+        
+        //
+        // Reading the annotations is expensive.  See if there's a cached copy of the map.
+        //
+        Map/*< Field, PropertyMap >* cached = ( Map ) _controlFieldCache.get( className );
+        
+        if ( cached != null )
+        {
+            return cached;
+        }
+
+        
+        HashMap/*< Field, PropertyMap >* ret = new HashMap/*< Field, PropertyMap >*();
+        boolean accessPrivateFields = true;
+        
+        // Note that the annnotation reader doesn't change per-class.  Inherited annotated elements are all read.
+        AnnotationReader annReader = AnnotationReader.getAnnotationReader( controlContainerClass, servletContext );
+        
+        //
+        // Go through this class and all superclasses, looking for control fields.  Make sure that a superclass control
+        // field never replaces a subclass control field (this is what the 'fieldNames' HashSet is for).
+        //
+        
+        HashSet fieldNames = new HashSet();
+        
+        do
+        {
+            Field[] fields = controlContainerClass.getDeclaredFields();
+            
+            for ( int i = 0; i < fields.length; i++ )
+            {
+                Field field = fields[i];
+                String fieldName = field.getName();
+                int modifiers = field.getModifiers();
+                
+                if ( ! fieldNames.contains( fieldName ) && ! Modifier.isStatic( modifiers )
+                     && annReader.getAnnotation( field.getName(), CONTROL_ANNOTATION_CLASSNAME ) != null )
+                {
+                    if ( accessPrivateFields || ! Modifier.isPrivate( modifiers ) )
+                    {
+                        if ( ! Modifier.isPublic( field.getModifiers() ) ) field.setAccessible( true );
+                        ret.put( field, new AnnotatedElementMap( field ) );
+                        fieldNames.add( fieldName );
+                    }
+                }
+            }
+    
+            accessPrivateFields = false;
+            controlContainerClass = controlContainerClass.getSuperclass();
+        } while ( controlContainerClass != null );
+        
+        _controlFieldCache.put( className, ret );
+        return ret;
+        */
+        
+        return null;
+    }
+
+    /**
+     * Initialize all null member variables that are Java Controls.
+     */
+    public static void initJavaControls(PageFlowManagedObject controlClient)
+            throws ControlFieldInitializationException {
+        /*
+        Class controlClientClass = controlClient.getClass();
+        
+        //
+        // First, just return if there are no annotated Control fields.  This saves us from having to catch a
+        // (wrapped) ClassNotFoundException for the control client initializer if we were to simply call
+        // Controls.initializeClient().
+        //
+        Map controlFields = getAccessibleControlFieldAnnotations( controlClientClass, servletContext );
+        if ( controlFields.isEmpty() ) return;
+
+        request = PageFlowUtils.unwrapMultipart( request );
+        ControlBeanContext beanContext = getControlBeanContext( request, response, servletContext, false );
+        assert beanContext != null : "ControlBeanContext was not initialized by PageFlowRequestProcessor";
+        try
+        {
+            Controls.initializeClient(null, controlClient, beanContext);
+        }
+        catch ( Exception e )
+        {
+            _log.error( "Exception occurred while initializing controls", e);
+            throw new ControlFieldInitializationException( controlClientClass.getName(), controlClient, e );
+        }
+        */
+    }
+
+    /**
+     * Clean up all member variables that are Java Controls.
+     */
+    public static void uninitJavaControls(PageFlowManagedObject controlClient) {
+        /*
+        Map controlFields = getAccessibleControlFieldAnnotations( controlClient.getClass(), servletContext );
+        
+        for ( Iterator i = controlFields.keySet().iterator(); i.hasNext(); )
+        {
+            Field controlField = ( Field ) i.next();
+
+            try
+            {
+                Object fieldValue = controlField.get( controlClient );
+                
+                if ( fieldValue != null )
+                {
+                    controlField.set( controlClient, null );
+                    destroyControl( fieldValue );
+                }
+            }
+            catch ( IllegalAccessException e )
+            {
+                _log.error( "Exception while uninitializing Java Control " + controlField.getName(), e );
+            }            
+        }
+        */
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/NavigateToException.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/NavigateToException.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/NavigateToException.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/NavigateToException.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,51 @@
+/*
+ * 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.pageflow.internal;
+
+import org.apache.ti.pageflow.FlowController;
+import org.apache.ti.pageflow.FlowControllerException;
+import org.apache.ti.pageflow.xwork.NavigateToResult;
+
+public abstract class NavigateToException extends FlowControllerException {
+
+    private String _returnToType;
+
+
+    protected NavigateToException(NavigateToResult result, FlowController fc) {
+        super(fc);
+        _returnToType = result.getNavigateToAsString();
+    }
+
+    public String getReturnToType() {
+        return _returnToType;
+    }
+
+    protected Object[] getMessageArgs() {
+        return new Object[]{_returnToType, getActionName(), getFlowControllerURI()};
+    }
+
+    protected abstract String[] getMessageParts();
+
+    /**
+     * Tell whether the root cause may be session expiration in cases where the requested session ID is different than
+     * the actual session ID.  In this case, the answer is <code>true</code>.
+     */
+    public boolean causeMayBeSessionExpiration() {
+        return true;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/NullActionForm.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/NullActionForm.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/NullActionForm.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/NullActionForm.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,78 @@
+/*
+ * 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.pageflow.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * ActionForm/Map that stores no properties and emits no errors.
+ */
+public class NullActionForm implements Map {
+
+    public int size() {
+        return 0;
+    }
+
+    public boolean isEmpty() {
+        return true;
+    }
+
+    public boolean containsKey(Object key) {
+        return false;
+    }
+
+    public boolean containsValue(Object value) {
+        return false;
+    }
+
+    public Object get(Object key) {
+        return null;
+    }
+
+    public Object put(Object o, Object o1) {
+        return null;
+    }
+
+    public Object remove(Object key) {
+        return null;
+    }
+
+    public void putAll(Map map) {
+    }
+
+    public void clear() {
+    }
+
+    public Set keySet() {
+        return Collections.EMPTY_SET;
+    }
+
+    public Collection values() {
+        return Collections.EMPTY_LIST;
+    }
+
+    public Set entrySet() {
+        return Collections.EMPTY_SET;
+    }
+}
+
+

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/PageFlowBeanContext.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/PageFlowBeanContext.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/PageFlowBeanContext.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/PageFlowBeanContext.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,49 @@
+/*
+ * 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.pageflow.internal;
+
+
+
+/**
+ * Specialization of the base ServletBeanContext that adds a Page Flow service provider to offer
+ * initialization for PageFlowController and SharedFlowControler members in a Control.
+ */
+public class PageFlowBeanContext {
+
+}
+
+/* TODO: re-add this, under a controls-support module
+        extends ServletBeanContext
+        implements PageFlowServiceProvider.HasServletRequest
+{
+    public ServletRequest getServletRequest()
+    {
+        return super.getServletRequest();
+    }
+
+    /**
+      * Called by BeanContextSupport superclass during construction and deserialization to
+      * initialize subclass transient state
+      *
+     public void initialize()
+     {
+         super.initialize();
+         addService( PageFlowController.class, PageFlowServiceProvider.getProvider() );
+     }
+}
+*/

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/PageFlowServiceProvider.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/PageFlowServiceProvider.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/PageFlowServiceProvider.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/PageFlowServiceProvider.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,71 @@
+/*
+ * 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.pageflow.internal;
+
+import org.apache.ti.pageflow.PageFlowController;
+import org.apache.ti.pageflow.PageFlowUtils;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import java.beans.beancontext.BeanContextServiceProvider;
+import java.beans.beancontext.BeanContextServices;
+import java.util.Iterator;
+
+
+/**
+ * Service provider that offers initialization for PageFlowController and SharedFlowControler members in a Control.
+ */
+public class PageFlowServiceProvider implements BeanContextServiceProvider {
+
+    private static final PageFlowServiceProvider _provider = new PageFlowServiceProvider();
+
+    public static final PageFlowServiceProvider getProvider() {
+        return _provider;
+    }
+
+    private PageFlowServiceProvider() {
+    }
+
+    public static interface HasServletRequest {
+
+        ServletRequest getServletRequest();
+    }
+
+    public Object getService(BeanContextServices bcs, Object requestor, Class serviceClass,
+                             Object serviceSelector) {
+        //
+        // These services are only available to controls running within the scope of a PageFlowBeanContext
+        //
+        if (!(bcs instanceof HasServletRequest)) return null;
+
+        if (PageFlowController.class.equals(serviceClass)) {
+            ServletRequest request = ((HasServletRequest) bcs).getServletRequest();
+            if (!(request instanceof HttpServletRequest)) return null;
+            return PageFlowUtils.getCurrentPageFlow();
+        }
+
+        return null;
+    }
+
+    public void releaseService(BeanContextServices bcs, Object requestor, Object service) {
+    }
+
+    public Iterator getCurrentServiceSelectors(BeanContextServices bcs, Class serviceClass) {
+        return null;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ProcessPopulate.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ProcessPopulate.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ProcessPopulate.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ProcessPopulate.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,326 @@
+/*
+ * 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.pageflow.internal;
+
+import org.apache.ti.pageflow.RequestParameterHandler;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+import org.apache.ti.script.Expression;
+import org.apache.ti.script.ExpressionEvaluator;
+import org.apache.ti.script.ExpressionEvaluatorFactory;
+import org.apache.ti.script.ExpressionUpdateException;
+import org.apache.ti.script.common.ImplicitObjectUtil;
+import org.apache.ti.util.Bundle;
+import org.apache.ti.util.internal.InternalStringBuilder;
+import org.apache.ti.util.logging.Logger;
+
+import javax.servlet.jsp.el.VariableResolver;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Implement the processPopulate stage of the Struts / PageFlow request
+ * processing lifecycle.  The {@link #populate(Object, boolean)} method is
+ * invoked in order to take request parameters from the request
+ * use the key / value pairs from the request to perform an update to the underlying
+ * JavaBean objects.
+ * <br/>
+ * <br/>
+ * Updates are performed on a key / value pair if the key is an expression; otherwise,
+ * the updates are delegated to the Struts processPopulate infrastructure.
+ */
+public class ProcessPopulate {
+
+    /**
+     * This defines the name of the parameter that will contain the NetUI ID map..
+     */
+    public static final String IDMAP_PARAMETER_NAME = "netuiIdMap";
+
+    private static final Logger _logger = Logger.getInstance(ProcessPopulate.class);
+
+    // these must be kept in sync with the context names specified in the scripting languages
+    private static final String PAGE_FLOW_CONTEXT = "pageFlow";
+    private static final String GLOBAL_APP_CONTEXT = "globalApp";
+
+    private static final String WLW_TAG_HANDLER_PREFIX = "wlw-";
+    private static final String WLW_TAG_HANDLER_SUFFIX = ":";
+
+    private static final Map handlerMap = new HashMap();
+
+    /**
+     * An inner class that represnts the data that will be used to
+     * perform an update.  If a key has a prefix handler, this
+     * node is constructed and passed to the prefix handler
+     * so that the prefix handler can change the expression or
+     * values that will be used to execute the expression update.
+     */
+    public final static class ExpressionUpdateNode {
+
+        public String expression = null;
+        public String[] values = null;
+
+        // can't be constructed outside of this class
+        private ExpressionUpdateNode() {
+        }
+
+        public String toString() {
+            InternalStringBuilder buf = new InternalStringBuilder();
+            buf.append("expression: " + expression + "\n");
+            if (values != null)
+                for (int i = 0; i < values.length; i++)
+                    buf.append("value[" + i + "]: " + values[i]);
+            else
+                buf.append("values are null");
+
+            return buf.toString();
+        }
+    }
+
+    /**
+     * Register a {@link org.apache.ti.pageflow.RequestParameterHandler} that is added to handle a
+     * particular prefix which be present as a prefix to a request parameter
+     * key.  For keys that match the prefix, the key / value from the request
+     * are put in an {@link ExpressionUpdateNode} struct and handed to the
+     * {@link org.apache.ti.pageflow.RequestParameterHandler} for processing.  The returned {@link ExpressionUpdateNode}
+     * is used to perform an expression update.
+     *
+     * @param prefix  the String prefix that will be appended to request paramters that
+     *                should pass through the {@link org.apache.ti.pageflow.RequestParameterHandler} before being updated.
+     * @param handler the handler that should handle all request paramters with
+     *                the given <code>prefix</code>
+     */
+    public static void registerPrefixHandler(String prefix, RequestParameterHandler handler) {
+        // should happen very infrequently
+        synchronized (handlerMap) {
+            String msg = "Register RequestParameterHandler with\n\tprefix: " + prefix + "\n\thandler: " + (handler != null ? handler.getClass().getName() : null);
+
+            if (_logger.isInfoEnabled()) _logger.info(msg);
+
+            if (handlerMap.get(prefix) == null)
+                handlerMap.put(prefix, handler);
+        }
+    }
+
+    /**
+     * Write the handler name specified onto the given expression.
+     */
+    public static String writeHandlerName(String handler, String expression) {
+        if (!ExpressionEvaluatorFactory.getInstance().isExpression(expression))
+            throw new IllegalArgumentException(Bundle.getErrorString("ProcessPopulate_handler_nonAtomicExpression", new Object[]{expression}));
+
+        if (!handlerMap.containsKey(handler))
+            throw new IllegalStateException(Bundle.getErrorString("ProcessPopulate_handler_notRegistered", new Object[]{handler}));
+
+        InternalStringBuilder buf = new InternalStringBuilder();
+        buf.append(WLW_TAG_HANDLER_PREFIX);
+        buf.append(handler);
+        buf.append(WLW_TAG_HANDLER_SUFFIX);
+        buf.append(expression);
+
+        return buf.toString();
+    }
+
+    /**
+     * Use the request parameters to populate all properties that have expression keys into
+     * the underlying JavaBeans.
+     * Creates a <code>java.util.Map</code> of objects that will be consumed by
+     * Struts processPopulate.  This includes all request attributes that
+     * were not expressions
+     *
+     * @param form if this request references an action and it has an <code>ActionForm</code>
+     *             associated with it, then the <code>form</code> parameter is non-null.
+     */
+    public static void populate(Object form, boolean requestHasPopulated) {
+        String key = null;
+        Map strutsProperties = null;
+        ExpressionEvaluator ee = ExpressionEvaluatorFactory.getInstance();
+        PageFlowActionContext actionContext = PageFlowActionContext.get();        
+
+        // a boolean so that we can avoid an instanceof below...
+        boolean isMultipart = false;
+
+        // if this returns null, it's not a mulitpart request
+        // TODO: re-add multipart request support
+        //Map params = MultipartRequestUtils.handleMultipartRequest(request, form);
+        Map params = null;
+
+        // make adjustments
+        if (params != null)
+            isMultipart = true;
+        else
+            params = actionContext.getParameters();
+
+        if (params == null) {
+            if (_logger.isWarnEnabled()) _logger.warn("An error occurred checking a request for multipart status.  No model values were updated.");
+            return;
+        }
+
+        /* explicitly build a variable resolver that is used to provide objects that may be updated to the expression engine */
+        VariableResolver variableResolver = ImplicitObjectUtil.getUpdateVariableResolver(form, true);
+
+        /* todo: are there any ordering issues with using an Iterator vs. an Enumeration here? */
+        Iterator iterator = params.keySet().iterator();
+        while (iterator.hasNext()) {
+            key = (String) iterator.next();
+            String expr = null;
+
+            // if there is an expression map, lookup the real expression from the name
+            expr = key;
+            if (_logger.isDebugEnabled())
+                _logger.debug("key: " + key + " value type: " + params.get(key).getClass().getName() + " value: " + params.get(key));
+
+            try {
+                Object paramsValue = params.get(key);
+                if (ee.containsExpression(expr)) {
+                    Object updateValue = null;
+                    if (!isMultipart || paramsValue instanceof String[]) {
+                        String[] values = (String[]) paramsValue;
+
+                        // the only "contains" case that is accepted
+                        if (expr.startsWith(WLW_TAG_HANDLER_PREFIX)) {
+                            if (_logger.isDebugEnabled()) _logger.debug("Found an expression requiring a TAG HANDLER");
+
+                            ExpressionUpdateNode node = doTagHandler(key, expr, values);
+
+                            expr = node.expression;
+                            values = node.values;
+                        }
+
+                        if (values != null && values.length == 1)
+                            updateValue = values[0];
+                        else
+                            updateValue = values;
+                    }
+                    // handle funky types that Struts returns for a file upload request handler
+                    else {
+                        updateValue = params.get(key);
+                    }
+
+                    try {
+                        // trap any bad expressions here
+                        if (ee.isExpression(expr)) {
+                            // common case, make this fast
+                            if (!requestHasPopulated)
+                                ee.update(expr, updateValue, variableResolver, true);
+                            // must check the expression to make sure pageFlow. and globalApp. don't get executed more than once
+                            else {
+                                Expression pe = ee.parseExpression(expr);
+                                String contextName = pe.getContext();
+                                if (!contextName.equals(PAGE_FLOW_CONTEXT) && !contextName.equals(GLOBAL_APP_CONTEXT))
+                                    ee.update(expr, updateValue, variableResolver, true);
+                            }
+                        }
+                    }
+                            // catch any errors, particularly expression parse failures
+                    catch (ExpressionUpdateException e) {
+                        String s = Bundle.getString("ExprUpdateError", new Object[]{expr, e});
+
+                        // this is the hairy NetUI Warning that gets printed to the console
+                        System.err.println(s);
+                        if (_logger.isErrorEnabled()) _logger.error(s);
+
+                        // add binding errors via PageFlowUtils
+                        InternalUtils.addBindingUpdateError(expr, s, e);
+                    }
+                } else {
+                    if (_logger.isDebugEnabled()) _logger.debug("HTTP request parameter key \"" + key + "\" is not an expression, handle with Struts");
+
+                    if (strutsProperties == null)
+                        strutsProperties = new HashMap();
+
+                    strutsProperties.put(key, paramsValue);
+                }
+            }
+                    // catch any unexpected exception
+            catch (Exception e) {
+                String s = Bundle.getString("ProcessPopulate_exprUpdateError", new Object[]{expr, e});
+                //e.printStackTrace();
+
+                System.err.println(s);
+
+                if (_logger.isWarnEnabled()) _logger.warn(s, e);
+
+                // add binding errors via PageFlowUtils
+                InternalUtils.addBindingUpdateError(expr, s, e);
+            }
+        }
+
+        //handleStrutsProperties(strutsProperties, form);
+    }
+
+    /**
+     * Process a single key.
+     *
+     * @param key the request key that is being processed
+     */
+    static final ExpressionUpdateNode doTagHandler(String key, String expression, String[] values) {
+        // not sure if this array will be mutable.  don't want to find out at this point.
+        String[] _values = values;
+
+        // key might be mangled here; make a copy
+        String expr = expression;
+
+        if (_logger.isDebugEnabled()) _logger.debug("Found prefixed tag; handlerName: " + key.substring(WLW_TAG_HANDLER_PREFIX.length(), key.indexOf(WLW_TAG_HANDLER_SUFFIX)));
+
+        String handlerName = expression.substring(WLW_TAG_HANDLER_PREFIX.length(), expression.indexOf(WLW_TAG_HANDLER_SUFFIX));
+        
+        // execute callback to parameter handler.  Generally, these are tags.
+        RequestParameterHandler handler = (RequestParameterHandler) handlerMap.get(handlerName);
+
+        if (handler != null) {
+            expr = expression.substring(expression.indexOf(WLW_TAG_HANDLER_SUFFIX) + 1);
+
+            if (_logger.isDebugEnabled())
+                _logger.debug("found handler for prefix \"" + handlerName + "\" type: " +
+                        (handler != null ? handler.getClass().getName() : null) + "\n\t" +
+                        "key: \"" + key + "\" expr: \"" + expr + "\"");
+
+            ExpressionUpdateNode node = new ExpressionUpdateNode();
+            node.expression = expr;
+            node.values = _values;
+            
+            // request, request key, the standalone expression (may have other stuff bracketing the expression
+            handler.process(key, expression, node);
+
+            return node;
+        } else
+            throw new IllegalStateException("Request parameter references a tag handler prefix \"" +
+                    handlerName + "\" that is not registered for expression \"" + key + "\"");
+    }
+
+    /*
+    // @struts: org.apache.struts.util.RequestUtils.populate
+    private static final void handleStrutsProperties(Map strutsProperties, ActionForm form)
+    {
+        if(strutsProperties != null)
+        {
+            if(_logger.isDebugEnabled()) _logger.debug("Handle Struts request parameters.");
+
+            // default to Struts for non-expression keys
+            try
+            {
+                BeanUtils.populate(form, strutsProperties);
+            }
+            catch(Exception e)
+            {
+                throw new RuntimeException("Exception processing bean and request parameters: ", e);
+            }
+        }
+    }
+    */
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ResponseOutputException.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ResponseOutputException.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ResponseOutputException.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ResponseOutputException.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,33 @@
+/*
+ * 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.pageflow.internal;
+
+/**
+ * Unchecked exception thrown in situations where output would normally be written to the response,
+ * but when the runtime is configured to throw an exception instead.
+ */
+public class ResponseOutputException extends RuntimeException {
+
+    public ResponseOutputException(String msg) {
+        super(msg);
+    }
+
+    public ResponseOutputException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/SimpleSessionStorageHandler.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/SimpleSessionStorageHandler.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/SimpleSessionStorageHandler.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/SimpleSessionStorageHandler.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,68 @@
+/*
+ * 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.pageflow.internal;
+
+import org.apache.ti.pageflow.handler.StorageHandler;
+import org.apache.ti.pageflow.xwork.PageFlowActionContext;
+
+import java.util.Map;
+
+/**
+ * This storage handler simply puts/gets attributes in the session.  It does not do anything to support multiple
+ * concurrent forwarded requests that are simultaneously modifying session data.
+ *
+ * @see DeferredSessionStorageHandler
+ */
+public class SimpleSessionStorageHandler
+        extends DefaultHandler
+        implements StorageHandler {
+
+    public SimpleSessionStorageHandler() {
+    }
+
+    public void setAttribute(String attributeName, Object value) {
+        Map sessionScope = PageFlowActionContext.get().getSession();
+        sessionScope.put(attributeName, value);
+    }
+
+    public void removeAttribute(String attributeName) {
+        Map sessionScope = PageFlowActionContext.get().getSession();
+        sessionScope.remove(attributeName);
+    }
+
+    public Object getAttribute(String attributeName) {
+        Map sessionScope = PageFlowActionContext.get().getSession();
+        return sessionScope.get(attributeName);
+    }
+
+    public void ensureFailover(String attributeName, Object value) {
+        AdapterManager.getContainerAdapter().ensureFailover(attributeName, value);
+    }
+
+    public boolean allowBindingEvent(Object event) {
+        return true;
+    }
+
+    public Object getStorageLocation() {
+        // TODO: create a Servlet version of this class that returns the actual session object
+        return PageFlowActionContext.get().getSession();
+    }
+
+    public void applyChanges() {
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/URIContextFactory.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/URIContextFactory.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/URIContextFactory.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/URIContextFactory.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,77 @@
+/*
+ * 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.pageflow.internal;
+
+import org.apache.ti.core.urls.MutableURI;
+import org.apache.ti.core.urls.URIContext;
+import org.apache.ti.schema.config.UrlConfig;
+import org.apache.ti.util.config.ConfigUtil;
+
+/**
+ * Factory for the {@link URIContext} with the data needed to write out
+ * a string form of a {@link MutableURI}.
+ */
+public final class URIContextFactory {
+
+    /* do not construct */
+    private URIContextFactory() {
+    }
+
+    /**
+     * Get a URIContext. The context has data used to write a MutableURI
+     * as a string. For example, it will indicate that the URI should be
+     * written using the &quot;&amp;amp;&quot; entity, rather than the
+     * character, '&amp;'. This returns the default context, but also
+     * checks for any overriding setting in the NetUI config.
+     *
+     * @return the URIContext
+     */
+    public static final URIContext getInstance() {
+        URIContext uriContext = MutableURI.getDefaultContext();
+        UrlConfig urlConfig = ConfigUtil.getConfig().getUrlConfig();
+
+        if (urlConfig != null && urlConfig.isSetHtmlAmpEntity()) {
+            uriContext.setUseAmpEntity(urlConfig.getHtmlAmpEntity());
+        }
+
+        return uriContext;
+    }
+
+    /**
+     * Get a URIContext. If it's for an XML document type, the context
+     * will indicate that the URI should be written using the
+     * &quot;&amp;amp;&quot; entity, rather than the character, '&amp;'.
+     * If it's not for an XML doc type, then use the default context,
+     * but check for any overriding setting in the NetUI config.
+     *
+     * @param forXML flag indicating that the URI is for an XML doc type
+     * @return the URIContext
+     */
+    public static final URIContext getInstance(boolean forXML) {
+        URIContext uriContext = null;
+
+        if (forXML) {
+            uriContext = new URIContext();
+            uriContext.setUseAmpEntity(true);
+        } else {
+            uriContext = getInstance();
+        }
+
+        return uriContext;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/UnhandledException.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/UnhandledException.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/UnhandledException.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/UnhandledException.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,33 @@
+/*
+ * 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.pageflow.internal;
+
+import org.apache.ti.pageflow.PageFlowException;
+
+/**
+ * ServletException derivative thrown when an exception occurred during action processing, and the exception was not
+ * handled by any exception handler.  This wrapper is used to prevent any outer try/catch blocks from re-processing
+ * the exception.
+ */
+public class UnhandledException
+        extends PageFlowException {
+
+    public UnhandledException(Throwable baseCause) {
+        super(baseCause);
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ViewRenderer.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ViewRenderer.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ViewRenderer.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/ViewRenderer.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,28 @@
+/*
+ * 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.pageflow.internal;
+
+import java.io.IOException;
+
+public interface ViewRenderer {
+
+    public void init();
+
+    public void renderView()
+            throws IOException;
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/XmlBeanActionForm.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/XmlBeanActionForm.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/XmlBeanActionForm.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/internal/XmlBeanActionForm.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,90 @@
+/*
+ * 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.pageflow.internal;
+
+import org.apache.ti.util.logging.Logger;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class XmlBeanActionForm {
+
+    private static final Logger _log = Logger.getInstance(XmlBeanActionForm.class);
+
+    private Object _bean;
+    private String _xmlBeanInterfaceClassName;
+
+
+    public XmlBeanActionForm(Object xml, String formClassName) {
+        setBean(xml);
+        _xmlBeanInterfaceClassName = formClassName;
+    }
+
+    public Object getBean() {
+        return _bean;
+    }
+
+    public void setBean(Object bean) {
+        _bean = bean;
+    }
+
+    public String getXmlString() {
+        Object xmlBean = getBean();
+
+        if (xmlBean == null) return null;
+
+        try {
+            return (String) xmlBean.getClass().getMethod("xmlText", (Class[]) null).invoke(xmlBean, (Object[]) null);
+        } catch (InvocationTargetException e) {
+            _log.error("Error while getting XML String", e.getCause());
+        } catch (Exception e) {
+            assert e instanceof NoSuchMethodException || e instanceof IllegalAccessException : e.getClass().getName();
+            _log.error("Error while getting XML String", e);
+        }
+
+        return null;
+    }
+
+    public void setXmlString(String xml) {
+        setBean(invokeFactoryMethod("parse", new Class[]{String.class}, new Object[]{xml}));
+    }
+
+    public void reset() {
+        if (getBean() == null) {
+            setBean(invokeFactoryMethod("newInstance", new Class[0], new Object[0]));
+        }
+    }
+
+    private Object invokeFactoryMethod(String methodName, Class[] argTypes, Object[] args) {
+        String factoryClassName = _xmlBeanInterfaceClassName + "$Factory";
+
+        try {
+            Class factoryClass = Class.forName(factoryClassName);
+            Method newInstanceMethod = factoryClass.getMethod(methodName, argTypes);
+            return newInstanceMethod.invoke(factoryClass, args);
+        } catch (Exception e) {
+            // Can be any exception -- not just the reflection-related exceptions...
+            // because the exception could be thrown while creating the XML bean.
+            if (_log.isErrorEnabled()) {
+                _log.error("Error while creating XML object of type " + _xmlBeanInterfaceClassName, e);
+            }
+
+            return null;
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/requeststate/INameable.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/requeststate/INameable.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/requeststate/INameable.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/requeststate/INameable.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.ti.pageflow.requeststate;
+
+/**
+ * This interface defines what it means to be a namable object.  The name
+ * service will name an INameable object which will be unique for the life
+ * time of the session.
+ */
+public interface INameable {
+
+    /**
+     * Set the ObjectName of the INameable object.  This should only
+     * be set once.  If it is called a second time an IllegalStateException
+     * should be thrown
+     *
+     * @param name the Object's name.
+     * @throws IllegalStateException if this method is called more than once for an object
+     */
+    public void setObjectName(String name);
+
+    /**
+     * Returns the ObjectName of the INameable object.
+     *
+     * @return the ObjectName.
+     */
+    public String getObjectName();
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/requeststate/NameService.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/requeststate/NameService.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/requeststate/NameService.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/pageflow/requeststate/NameService.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.ti.pageflow.requeststate;
+
+import javax.servlet.http.HttpSession;
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+
+/**
+ *
+ */
+public class NameService {
+
+    private static final String NAME_SERVICE = "netui.nameService";
+
+    private HashMap/*<String,WeakReference>*/ _nameMap;
+    private int _nextValue;
+
+    /**
+     * private constructor allowing for a factory method to access NameService objects.
+     */
+    private NameService() {
+        _nameMap = new HashMap/*<String,WeakReference>*/();
+        _nextValue = 0;
+    }
+
+    /**
+     * This will return the session specific instance of a NameService.  There
+     * will only be a single NameService per session.
+     *
+     * @param session the HttpSession that contains the NameService
+     * @return the NameService associated with the session.
+     */
+    public static NameService instance(HttpSession session) {
+        // synchronize on the session so we only create a single NameService
+        // within the session.
+        synchronized (session) {
+            NameService nameService = (NameService) session.getAttribute(NAME_SERVICE);
+            if (nameService == null) {
+                nameService = new NameService();
+                session.setAttribute(NAME_SERVICE, nameService);
+            }
+            assert(nameService != null) : "Found invalid null name service";
+            return nameService;
+        }
+    }
+
+    /**
+     * This method will create a unique name for an INameable object.  The name
+     * will be unque within the session.  This will throw an IllegalStateException
+     * if INameable.setObjectName has previously been called on object.
+     *
+     * @param namePrefix The prefix of the generated name.
+     * @param object     the INameable object.
+     * @throws IllegalStateException if this method is called more than once for an object
+     */
+    public synchronized void nameObject(String namePrefix, INameable object) {
+        String name = namePrefix + Integer.toString(_nextValue++);
+        object.setObjectName(name);
+    }
+
+    /**
+     * This is a debug method that will set the next integer value.  This is used
+     * so tests can force the name.
+     *
+     * @param val
+     */
+    public void debugSetNameIntValue(int val) {
+        _nextValue = val;
+    }
+
+    /**
+     * @param object
+     */
+    public void put(INameable object) {
+        if (object == null)
+            throw new IllegalStateException("object must not be null");
+        String name = object.getObjectName();
+        if (name == null)
+            throw new IllegalStateException("object has not been named");
+
+        _nameMap.put(name, new WeakReference(object));
+    }
+
+    /**
+     * @param name
+     * @return INameable
+     */
+    public INameable get(String name) {
+        if (name == null)
+            throw new IllegalStateException("name must not be null");
+        WeakReference wr = (WeakReference) _nameMap.get(name);
+        if (wr == null)
+            return null;
+        INameable object = (INameable) wr.get();
+        if (object == null) {
+            _nameMap.remove(name);
+        }
+        return object;
+    }
+}



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