You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by ma...@apache.org on 2009/12/27 19:01:09 UTC

svn commit: r894087 [3/46] - in /struts/xwork/trunk: ./ assembly/ assembly/src/ assembly/src/main/ assembly/src/main/assembly/ assembly/src/main/resources/ core/ core/src/ core/src/main/ core/src/main/java/ core/src/main/java/com/ core/src/main/java/co...

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+
+/**
+ * Provides a default implementation for the most common actions.
+ * See the documentation for all the interfaces this class implements for more detailed information.
+ */
+public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
+
+    protected static Logger LOG = LoggerFactory.getLogger(ActionSupport.class);
+
+    private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
+
+    private transient TextProvider textProvider;
+    private Container container;
+
+    public void setActionErrors(Collection<String> errorMessages) {
+        validationAware.setActionErrors(errorMessages);
+    }
+
+    public Collection<String> getActionErrors() {
+        return validationAware.getActionErrors();
+    }
+
+    public void setActionMessages(Collection<String> messages) {
+        validationAware.setActionMessages(messages);
+    }
+
+    public Collection<String> getActionMessages() {
+        return validationAware.getActionMessages();
+    }
+
+    /**
+     * @deprecated Use {@link #getActionErrors()}.
+     */
+    @Deprecated
+    public Collection<String> getErrorMessages() {
+        return getActionErrors();
+    }
+
+    /**
+     * @deprecated Use {@link #getFieldErrors()}.
+     */
+    @Deprecated
+    public Map<String, List<String>> getErrors() {
+        return getFieldErrors();
+    }
+
+    public void setFieldErrors(Map<String, List<String>> errorMap) {
+        validationAware.setFieldErrors(errorMap);
+    }
+
+    public Map<String, List<String>> getFieldErrors() {
+        return validationAware.getFieldErrors();
+    }
+
+    public Locale getLocale() {
+        ActionContext ctx = ActionContext.getContext();
+        if (ctx != null) {
+            return ctx.getLocale();
+        } else {
+            LOG.debug("Action context not initialized");
+            return null;
+        }
+    }
+
+    public boolean hasKey(String key) {
+        return getTextProvider().hasKey(key);
+    }
+
+    public String getText(String aTextName) {
+        return getTextProvider().getText(aTextName);
+    }
+
+    public String getText(String aTextName, String defaultValue) {
+        return getTextProvider().getText(aTextName, defaultValue);
+    }
+
+    public String getText(String aTextName, String defaultValue, String obj) {
+        return getTextProvider().getText(aTextName, defaultValue, obj);
+    }
+
+    public String getText(String aTextName, List<Object> args) {
+        return getTextProvider().getText(aTextName, args);
+    }
+
+    public String getText(String key, String[] args) {
+        return getTextProvider().getText(key, args);
+    }
+
+    public String getText(String aTextName, String defaultValue, List<Object> args) {
+        return getTextProvider().getText(aTextName, defaultValue, args);
+    }
+
+    public String getText(String key, String defaultValue, String[] args) {
+        return getTextProvider().getText(key, defaultValue, args);
+    }
+
+    public String getText(String key, String defaultValue, List<Object> args, ValueStack stack) {
+        return getTextProvider().getText(key, defaultValue, args, stack);
+    }
+
+    public String getText(String key, String defaultValue, String[] args, ValueStack stack) {
+        return getTextProvider().getText(key, defaultValue, args, stack);
+    }
+
+    public ResourceBundle getTexts() {
+        return getTextProvider().getTexts();
+    }
+
+    public ResourceBundle getTexts(String aBundleName) {
+        return getTextProvider().getTexts(aBundleName);
+    }
+
+    public void addActionError(String anErrorMessage) {
+        validationAware.addActionError(anErrorMessage);
+    }
+
+    public void addActionMessage(String aMessage) {
+        validationAware.addActionMessage(aMessage);
+    }
+
+    public void addFieldError(String fieldName, String errorMessage) {
+        validationAware.addFieldError(fieldName, errorMessage);
+    }
+
+    public String input() throws Exception {
+        return INPUT;
+    }
+
+    public String doDefault() throws Exception {
+        return SUCCESS;
+    }
+
+    /**
+     * A default implementation that does nothing an returns "success".
+     * <p/>
+     * Subclasses should override this method to provide their business logic.
+     * <p/>
+     * See also {@link com.opensymphony.xwork2.Action#execute()}.
+     *
+     * @return returns {@link #SUCCESS}
+     * @throws Exception can be thrown by subclasses.
+     */
+    public String execute() throws Exception {
+        return SUCCESS;
+    }
+
+    public boolean hasActionErrors() {
+        return validationAware.hasActionErrors();
+    }
+
+    public boolean hasActionMessages() {
+        return validationAware.hasActionMessages();
+    }
+
+    public boolean hasErrors() {
+        return validationAware.hasErrors();
+    }
+
+    public boolean hasFieldErrors() {
+        return validationAware.hasFieldErrors();
+    }
+
+    /**
+     * Clears field errors. Useful for Continuations and other situations
+     * where you might want to clear parts of the state on the same action.
+     */
+    public void clearFieldErrors() {
+        validationAware.clearFieldErrors();
+    }
+
+    /**
+     * Clears action errors. Useful for Continuations and other situations
+     * where you might want to clear parts of the state on the same action.
+     */
+    public void clearActionErrors() {
+        validationAware.clearActionErrors();
+    }
+
+    /**
+     * Clears messages. Useful for Continuations and other situations
+     * where you might want to clear parts of the state on the same action.
+     */
+    public void clearMessages() {
+        validationAware.clearMessages();
+    }
+
+    /**
+     * Clears all errors. Useful for Continuations and other situations
+     * where you might want to clear parts of the state on the same action.
+     */
+    public void clearErrors() {
+        validationAware.clearErrors();
+    }
+
+    /**
+     * Clears all errors and messages. Useful for Continuations and other situations
+     * where you might want to clear parts of the state on the same action.
+     */
+    public void clearErrorsAndMessages() {
+        validationAware.clearErrorsAndMessages();
+    }
+
+    /**
+     * A default implementation that validates nothing.
+     * Subclasses should override this method to provide validations.
+     */
+    public void validate() {
+    }
+
+    @Override
+    public Object clone() throws CloneNotSupportedException {
+        return super.clone();
+    }
+
+    /**
+     * <!-- START SNIPPET: pause-method -->
+     * Stops the action invocation immediately (by throwing a PauseException) and causes the action invocation to return
+     * the specified result, such as {@link #SUCCESS}, {@link #INPUT}, etc.
+     * <p/>
+     * <p/>
+     * The next time this action is invoked (and using the same continuation ID), the method will resume immediately
+     * after where this method was called, with the entire call stack in the execute method restored.
+     * <p/>
+     * <p/>
+     * Note: this method can <b>only</b> be called within the {@link #execute()} method.
+     * <!-- END SNIPPET: pause-method -->
+     *
+     * @param result the result to return - the same type of return value in the {@link #execute()} method.
+     */
+    public void pause(String result) {
+    }
+
+    /**
+     * If called first time it will create {@link com.opensymphony.xwork2.TextProviderFactory},
+     * inject dependency (if {@link com.opensymphony.xwork2.inject.Container} is accesible) into in,
+     * then will create new {@link com.opensymphony.xwork2.TextProvider} and store it in a field
+     * for future references and at the returns reference to that field
+     *
+     * @return reference to field with TextProvider
+     */
+    private TextProvider getTextProvider() {
+        if (textProvider == null) {
+            TextProviderFactory tpf = new TextProviderFactory();
+            if (container != null) {
+                container.inject(tpf);
+            }
+            textProvider = tpf.createInstance(getClass(), this);
+        }
+        return textProvider;
+    }
+
+    @Inject
+    public void setContainer(Container container) {
+        this.container = container;
+    }
+
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/CompositeTextProvider.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/CompositeTextProvider.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/CompositeTextProvider.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/CompositeTextProvider.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,267 @@
+package com.opensymphony.xwork2;
+
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+import java.util.*;
+
+
+/**
+ * This is a composite {@link TextProvider} that takes in an array or {@link java.util.List} of {@link TextProvider}s, it will
+ * consult each of them in order to get a composite result. To know how each method behaves, please refer to the
+ * javadoc for each methods.
+ *
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class CompositeTextProvider implements TextProvider {
+
+    private static final Logger LOG = LoggerFactory.getLogger(CompositeTextProvider.class);
+
+    private List<TextProvider> textProviders = new ArrayList<TextProvider>();
+
+    /**
+     * Instantiates a {@link CompositeTextProvider} with some predefined <code>textProviders</code>.
+     *
+     * @param textProviders
+     */
+    public CompositeTextProvider(List<TextProvider> textProviders) {
+        this.textProviders.addAll(textProviders);
+    }
+
+    /**
+     * Instantiates a {@link CompositeTextProvider} with some predefined <code>textProviders</code>.
+     *
+     * @param textProviders
+     */
+    public CompositeTextProvider(TextProvider[] textProviders) {
+        this(Arrays.asList(textProviders));
+    }
+
+    /**
+     * @param key The key to lookup in ressource bundles.
+     * @return <tt>true</tt>, if the requested key is found in one of the ressource bundles.
+     * @see {@link com.opensymphony.xwork2.TextProvider#hasKey(String)}
+     *      It will consult each individual {@link TextProvider}s and return true if either one of the
+     *      {@link TextProvider} has such a <code>key></code> else false.
+     */
+    public boolean hasKey(String key) {
+        // if there's a key in either text providers we are ok, else try the next text provider
+        for (TextProvider tp : textProviders) {
+            if (tp.hasKey(key)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>
+     *
+     * @param key The key to lookup in ressource bundles.
+     * @return The i18n text for the requested key.
+     * @see {@link com.opensymphony.xwork2.TextProvider#getText(String)}
+     */
+    public String getText(String key) {
+        return getText(key, key, Collections.emptyList());
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code> before returning <code>defaultValue</code> if every else fails.
+     *
+     * @param key
+     * @param defaultValue
+     * @return
+     * @see {@link com.opensymphony.xwork2.TextProvider#getText(String, String)}
+     */
+    public String getText(String key, String defaultValue) {
+        return getText(key, defaultValue, Collections.emptyList());
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>, before returining <code>defaultValue</code>
+     * if every else fails.
+     *
+     * @param key
+     * @param defaultValue
+     * @param obj
+     * @return
+     * @see {@link com.opensymphony.xwork2.TextProvider#getText(String, String, String)}
+     */
+    public String getText(String key, String defaultValue, final String obj) {
+        return getText(key, defaultValue, new ArrayList<Object>() {
+            {
+                add(obj);
+            }
+
+
+        });
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>.
+     *
+     * @param key
+     * @param args
+     * @return
+     * @see {@link com.opensymphony.xwork2.TextProvider#getText(String, java.util.List)}
+     */
+    public String getText(String key, List<Object> args) {
+        return getText(key, key, args);
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>.
+     *
+     * @param key
+     * @param args
+     * @return
+     * @see {@link com.opensymphony.xwork2.TextProvider#getText(String, String[])}
+     */
+    public String getText(String key, String[] args) {
+        return getText(key, key, args);
+    }
+
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>, before returining <code>defaultValue</code>
+     *
+     * @param key
+     * @param defaultValue
+     * @param args
+     * @return
+     * @see {@link com.opensymphony.xwork2.TextProvider#getText#getText(String, String, java.util.List)}
+     */
+    public String getText(String key, String defaultValue, List<Object> args) {
+        // if there's one text provider that gives us a msg not the same as defaultValue
+        // for this key, we are ok, else try the next
+        // text provider
+        for (TextProvider textProvider : textProviders) {
+            String msg = textProvider.getText(key, defaultValue, args);
+            if (msg != null && (!msg.equals(defaultValue))) {
+                return msg;
+            }
+        }
+        return defaultValue;
+    }
+
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>, before returining <code>defaultValue</code>.
+     *
+     * @param key
+     * @param defaultValue
+     * @param args
+     * @return
+     * @see {@link com.opensymphony.xwork2.TextProvider#getText(String, String, String[])}
+     */
+    public String getText(String key, String defaultValue, String[] args) {
+        // if there's one text provider that gives us a msg not the same as defaultValue
+        // for this key, we are ok, else try the next
+        // text provider
+        for (TextProvider textProvider : textProviders) {
+            String msg = textProvider.getText(key, defaultValue, args);
+            if (msg != null && (!msg.equals(defaultValue))) {
+                return msg;
+            }
+        }
+        return defaultValue;
+    }
+
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>, before returining <code>defaultValue</code>
+     *
+     * @param key
+     * @param defaultValue
+     * @param args
+     * @param stack
+     * @return
+     * @see {@link com.opensymphony.xwork2.TextProvider#getText(String, String, java.util.List, com.opensymphony.xwork2.util.OgnlValueStack)}
+     */
+    public String getText(String key, String defaultValue, List<Object> args, ValueStack stack) {
+        // if there's one text provider that gives us a msg not the same as defaultValue
+        // for this key, we are ok, else try the next
+        // text provider
+        for (TextProvider textProvider : textProviders) {
+            String msg = textProvider.getText(key, defaultValue, args, stack);
+            if (msg != null && (!msg.equals(defaultValue))) {
+                return msg;
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>, before returining <code>defaultValue</code>
+     *
+     * @param key
+     * @param defaultValue
+     * @param args
+     * @param stack
+     * @return
+     * @see {@link com.opensymphony.xwork2.TextProvider#getText(String, String, String[], com.opensymphony.xwork2.util.ValueStack)}
+     */
+    public String getText(String key, String defaultValue, String[] args, ValueStack stack) {
+        // if there's one text provider that gives us a msg not the same as defaultValue
+        // for this key, we are ok, else try the next
+        // text provider
+        for (TextProvider textProvider : textProviders) {
+            String msg = textProvider.getText(key, defaultValue, args, stack);
+            if (msg != null && (!msg.equals(defaultValue))) {
+                return msg;
+            }
+        }
+        return defaultValue;
+    }
+
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first non-null {@link ResourceBundle}.
+     *
+     * @param bundleName
+     * @return
+     * @see {@link TextProvider#getTexts(String)}
+     */
+    public ResourceBundle getTexts(String bundleName) {
+        // if there's one text provider that gives us a non-null resource bunlde for this bundleName, we are ok, else try the next
+        // text provider
+        for (TextProvider textProvider : textProviders) {
+            ResourceBundle bundle = textProvider.getTexts(bundleName);
+            if (bundle != null) {
+                return bundle;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * It will consult each {@link com.opensymphony.xwork2.TextProvider}s and return the first non-null {@link ResourceBundle}.
+     *
+     * @return
+     * @see {@link TextProvider#getTexts()}
+     */
+    public ResourceBundle getTexts() {
+        // if there's one text provider that gives us a non-null resource bundle, we are ok, else try the next
+        // text provider
+        for (TextProvider textProvider : textProviders) {
+            ResourceBundle bundle = textProvider.getTexts();
+            if (bundle != null) {
+                return bundle;
+            }
+        }
+        return null;
+    }
+}
+
+

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/CompositeTextProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/CompositeTextProvider.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.InterceptorMapping;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.PreResultListener;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * The Default ActionInvocation implementation
+ *
+ * @author Rainer Hermanns
+ * @author tmjee
+ * @version $Date$ $Id$
+ * @see com.opensymphony.xwork2.DefaultActionProxy
+ */
+public class DefaultActionInvocation implements ActionInvocation {
+
+    private static final long serialVersionUID = -585293628862447329L;
+
+    //static {
+    //    if (ObjectFactory.getContinuationPackage() != null) {
+    //        continuationHandler = new ContinuationHandler();
+    //    }
+    //}
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultActionInvocation.class);
+
+    private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
+
+    protected Object action;
+    protected ActionProxy proxy;
+    protected List<PreResultListener> preResultListeners;
+    protected Map<String, Object> extraContext;
+    protected ActionContext invocationContext;
+    protected Iterator<InterceptorMapping> interceptors;
+    protected ValueStack stack;
+    protected Result result;
+    protected Result explicitResult;
+    protected String resultCode;
+    protected boolean executed = false;
+    protected boolean pushAction = true;
+    protected ObjectFactory objectFactory;
+    protected ActionEventListener actionEventListener;
+    protected ValueStackFactory valueStackFactory;
+    protected Container container;
+    private Configuration configuration;
+    protected UnknownHandlerManager unknownHandlerManager;
+
+    public DefaultActionInvocation(final Map<String, Object> extraContext, final boolean pushAction) {
+        DefaultActionInvocation.this.extraContext = extraContext;
+        DefaultActionInvocation.this.pushAction = pushAction;
+    }
+
+    @Inject
+    public void setUnknownHandlerManager(UnknownHandlerManager unknownHandlerManager) {
+        this.unknownHandlerManager = unknownHandlerManager;
+    }
+
+    @Inject
+    public void setValueStackFactory(ValueStackFactory fac) {
+        this.valueStackFactory = fac;
+    }
+
+    @Inject
+    public void setConfiguration(Configuration configuration) {
+        this.configuration = configuration;
+    }
+
+    @Inject
+    public void setObjectFactory(ObjectFactory fac) {
+        this.objectFactory = fac;
+    }
+
+    @Inject
+    public void setContainer(Container cont) {
+        this.container = cont;
+    }
+
+    @Inject(required=false)
+    public void setActionEventListener(ActionEventListener listener) {
+        this.actionEventListener = listener;
+    }
+
+    public Object getAction() {
+        return action;
+    }
+
+    public boolean isExecuted() {
+        return executed;
+    }
+
+    public ActionContext getInvocationContext() {
+        return invocationContext;
+    }
+
+    public ActionProxy getProxy() {
+        return proxy;
+    }
+
+    /**
+     * If the DefaultActionInvocation has been executed before and the Result is an instance of ActionChainResult, this method
+     * will walk down the chain of ActionChainResults until it finds a non-chain result, which will be returned. If the
+     * DefaultActionInvocation's result has not been executed before, the Result instance will be created and populated with
+     * the result params.
+     *
+     * @return a Result instance
+     * @throws Exception
+     */
+    public Result getResult() throws Exception {
+        Result returnResult = result;
+
+        // If we've chained to other Actions, we need to find the last result
+        while (returnResult instanceof ActionChainResult) {
+            ActionProxy aProxy = ((ActionChainResult) returnResult).getProxy();
+
+            if (aProxy != null) {
+                Result proxyResult = aProxy.getInvocation().getResult();
+
+                if ((proxyResult != null) && (aProxy.getExecuteResult())) {
+                    returnResult = proxyResult;
+                } else {
+                    break;
+                }
+            } else {
+                break;
+            }
+        }
+
+        return returnResult;
+    }
+
+    public String getResultCode() {
+        return resultCode;
+    }
+
+    public void setResultCode(String resultCode) {
+        if (isExecuted())
+            throw new IllegalStateException("Result has already been executed.");
+
+        this.resultCode = resultCode;
+    }
+
+
+    public ValueStack getStack() {
+        return stack;
+    }
+
+    /**
+     * Register a com.opensymphony.xwork2.interceptor.PreResultListener to be notified after the Action is executed and before the
+     * Result is executed. The ActionInvocation implementation must guarantee that listeners will be called in the order
+     * in which they are registered. Listener registration and execution does not need to be thread-safe.
+     *
+     * @param listener
+     */
+    public void addPreResultListener(PreResultListener listener) {
+        if (preResultListeners == null) {
+            preResultListeners = new ArrayList<PreResultListener>(1);
+        }
+
+        preResultListeners.add(listener);
+    }
+
+    public Result createResult() throws Exception {
+
+        if (explicitResult != null) {
+            Result ret = explicitResult;
+            explicitResult = null;
+
+            return ret;
+        }
+        ActionConfig config = proxy.getConfig();
+        Map<String, ResultConfig> results = config.getResults();
+
+        ResultConfig resultConfig = null;
+
+        try {
+            resultConfig = results.get(resultCode);
+        } catch (NullPointerException e) {
+            // swallow
+        }
+        
+        if (resultConfig == null) {
+            // If no result is found for the given resultCode, try to get a wildcard '*' match.
+            resultConfig = results.get("*");
+        }
+
+        if (resultConfig != null) {
+            try {
+                return objectFactory.buildResult(resultConfig, invocationContext.getContextMap());
+            } catch (Exception e) {
+                LOG.error("There was an exception while instantiating the result of type " + resultConfig.getClassName(), e);
+                throw new XWorkException(e, resultConfig);
+            }
+        } else if (resultCode != null && !Action.NONE.equals(resultCode) && unknownHandlerManager.hasUnknownHandlers()) {
+            return unknownHandlerManager.handleUnknownResult(invocationContext, proxy.getActionName(), proxy.getConfig(), resultCode);
+        }
+        return null;
+    }
+
+    /**
+     * @throws ConfigurationException If no result can be found with the returned code
+     */
+    public String invoke() throws Exception {
+        String profileKey = "invoke: ";
+        try {
+            UtilTimerStack.push(profileKey);
+
+            if (executed) {
+                throw new IllegalStateException("Action has already executed");
+            }
+
+            if (interceptors.hasNext()) {
+                final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
+                String interceptorMsg = "interceptor: " + interceptor.getName();
+                UtilTimerStack.push(interceptorMsg);
+                try {
+                                resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
+                            }
+                finally {
+                    UtilTimerStack.pop(interceptorMsg);
+                }
+            } else {
+                resultCode = invokeActionOnly();
+            }
+
+            // this is needed because the result will be executed, then control will return to the Interceptor, which will
+            // return above and flow through again
+            if (!executed) {
+                if (preResultListeners != null) {
+                    for (Object preResultListener : preResultListeners) {
+                        PreResultListener listener = (PreResultListener) preResultListener;
+
+                        String _profileKey = "preResultListener: ";
+                        try {
+                            UtilTimerStack.push(_profileKey);
+                            listener.beforeResult(this, resultCode);
+                        }
+                        finally {
+                            UtilTimerStack.pop(_profileKey);
+                        }
+                    }
+                }
+
+                // now execute the result, if we're supposed to
+                if (proxy.getExecuteResult()) {
+                    executeResult();
+                }
+
+                executed = true;
+            }
+
+            return resultCode;
+        }
+        finally {
+            UtilTimerStack.pop(profileKey);
+        }
+    }
+
+    public String invokeActionOnly() throws Exception {
+        return invokeAction(getAction(), proxy.getConfig());
+    }
+
+    protected void createAction(Map<String, Object> contextMap) {
+        // load action
+        String timerKey = "actionCreate: " + proxy.getActionName();
+        try {
+            UtilTimerStack.push(timerKey);
+            action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);
+        } catch (InstantiationException e) {
+            throw new XWorkException("Unable to intantiate Action!", e, proxy.getConfig());
+        } catch (IllegalAccessException e) {
+            throw new XWorkException("Illegal access to constructor, is it public?", e, proxy.getConfig());
+        } catch (Exception e) {
+            String gripe = "";
+
+            if (proxy == null) {
+                gripe = "Whoa!  No ActionProxy instance found in current ActionInvocation.  This is bad ... very bad";
+            } else if (proxy.getConfig() == null) {
+                gripe = "Sheesh.  Where'd that ActionProxy get to?  I can't find it in the current ActionInvocation!?";
+            } else if (proxy.getConfig().getClassName() == null) {
+                gripe = "No Action defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'";
+            } else {
+                gripe = "Unable to instantiate Action, " + proxy.getConfig().getClassName() + ",  defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'";
+            }
+
+            gripe += (((" -- " + e.getMessage()) != null) ? e.getMessage() : " [no message in exception]");
+            throw new XWorkException(gripe, e, proxy.getConfig());
+        } finally {
+            UtilTimerStack.pop(timerKey);
+        }
+
+        if (actionEventListener != null) {
+            action = actionEventListener.prepare(action, stack);
+        }
+    }
+
+    protected Map<String, Object> createContextMap() {
+        Map<String, Object> contextMap;
+
+        if ((extraContext != null) && (extraContext.containsKey(ActionContext.VALUE_STACK))) {
+            // In case the ValueStack was passed in
+            stack = (ValueStack) extraContext.get(ActionContext.VALUE_STACK);
+
+            if (stack == null) {
+                throw new IllegalStateException("There was a null Stack set into the extra params.");
+            }
+
+            contextMap = stack.getContext();
+        } else {
+            // create the value stack
+            // this also adds the ValueStack to its context
+            stack = valueStackFactory.createValueStack();
+
+            // create the action context
+            contextMap = stack.getContext();
+        }
+
+        // put extraContext in
+        if (extraContext != null) {
+            contextMap.putAll(extraContext);
+        }
+
+        //put this DefaultActionInvocation into the context map
+        contextMap.put(ActionContext.ACTION_INVOCATION, this);
+        contextMap.put(ActionContext.CONTAINER, container);
+
+        return contextMap;
+    }
+
+    /**
+     * Uses getResult to get the final Result and executes it
+     *
+     * @throws ConfigurationException If not result can be found with the returned code
+     */
+    private void executeResult() throws Exception {
+        result = createResult();
+
+        String timerKey = "executeResult: " + getResultCode();
+        try {
+            UtilTimerStack.push(timerKey);
+            if (result != null) {
+                result.execute(this);
+            } else if (resultCode != null && !Action.NONE.equals(resultCode)) {
+                throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()
+                        + " and result " + getResultCode(), proxy.getConfig());
+            } else {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("No result returned for action " + getAction().getClass().getName() + " at " + proxy.getConfig().getLocation());
+                }
+            }
+        } finally {
+            UtilTimerStack.pop(timerKey);
+        }
+    }
+
+    public void init(ActionProxy proxy) {
+        this.proxy = proxy;
+        Map<String, Object> contextMap = createContextMap();
+
+        // Setting this so that other classes, like object factories, can use the ActionProxy and other
+        // contextual information to operate
+        ActionContext actionContext = ActionContext.getContext();
+
+        if (actionContext != null) {
+            actionContext.setActionInvocation(this);
+        }
+
+        createAction(contextMap);
+
+        if (pushAction) {
+            stack.push(action);
+            contextMap.put("action", action);
+        }
+
+        invocationContext = new ActionContext(contextMap);
+        invocationContext.setName(proxy.getActionName());
+
+        // get a new List so we don't get problems with the iterator if someone changes the list
+        List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());
+        interceptors = interceptorList.iterator();
+    }
+
+    protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
+        String methodName = proxy.getMethod();
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Executing action method = " + actionConfig.getMethodName());
+        }
+
+        String timerKey = "invokeAction: " + proxy.getActionName();
+        try {
+            UtilTimerStack.push(timerKey);
+
+            boolean methodCalled = false;
+            Object methodResult = null;
+            Method method = null;
+            try {
+                method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY);
+            } catch (NoSuchMethodException e) {
+                // hmm -- OK, try doXxx instead
+                try {
+                    String altMethodName = "do" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
+                    method = getAction().getClass().getMethod(altMethodName, EMPTY_CLASS_ARRAY);
+                } catch (NoSuchMethodException e1) {
+                    // well, give the unknown handler a shot
+                    if (unknownHandlerManager.hasUnknownHandlers()) {
+                        try {
+                            methodResult = unknownHandlerManager.handleUnknownMethod(action, methodName);
+                            methodCalled = true;
+                        } catch (NoSuchMethodException e2) {
+                            // throw the original one
+                            throw e;
+                        }
+                    } else {
+                        throw e;
+                    }
+                }
+            }
+
+            if (!methodCalled) {
+                methodResult = method.invoke(action, new Object[0]);
+            }
+
+            if (methodResult instanceof Result) {
+                this.explicitResult = (Result) methodResult;
+
+                // Wire the result automatically
+                container.inject(explicitResult);
+                return null;
+            } else {
+                return (String) methodResult;
+            }
+        } catch (NoSuchMethodException e) {
+            throw new IllegalArgumentException("The " + methodName + "() is not defined in action " + getAction().getClass() + "");
+        } catch (InvocationTargetException e) {
+            // We try to return the source exception.
+            Throwable t = e.getTargetException();
+
+            if (actionEventListener != null) {
+                String result = actionEventListener.handleException(t, getStack());
+                if (result != null) {
+                    return result;
+                }
+            }
+            if (t instanceof Exception) {
+                throw (Exception) t;
+            } else {
+                throw e;
+            }
+        } finally {
+            UtilTimerStack.pop(timerKey);
+        }
+    }
+
+
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.LocalizedTextUtil;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
+
+import java.io.Serializable;
+import java.util.Locale;
+
+import org.apache.commons.lang.StringUtils;
+
+
+/**
+ * The Default ActionProxy implementation
+ *
+ * @author Rainer Hermanns
+ * @author Revised by <a href="mailto:hu_pengfei@yahoo.com.cn">Henry Hu</a>
+ * @author tmjee
+ * 
+ * @version $Date$ $Id$
+ * @since 2005-8-6
+ */
+public class DefaultActionProxy implements ActionProxy, Serializable {
+	
+	private static final long serialVersionUID = 3293074152487468527L;
+
+	private static final Logger LOG = LoggerFactory.getLogger(DefaultActionProxy.class);
+
+    protected Configuration configuration;
+    protected ActionConfig config;
+    protected ActionInvocation invocation;
+    protected UnknownHandlerManager unknownHandlerManager;
+    protected String actionName;
+    protected String namespace;
+    protected String method;
+    protected boolean executeResult;
+    protected boolean cleanupContext;
+
+    protected ObjectFactory objectFactory;
+
+    protected ActionEventListener actionEventListener;
+
+    /**
+     * This constructor is private so the builder methods (create*) should be used to create an DefaultActionProxy.
+     * <p/>
+     * The reason for the builder methods is so that you can use a subclass to create your own DefaultActionProxy instance
+     * (like a RMIActionProxy).
+     */
+    protected DefaultActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
+        
+        this.invocation = inv;
+		this.cleanupContext = cleanupContext;
+		if (LOG.isDebugEnabled()) {
+			LOG.debug("Creating an DefaultActionProxy for namespace " + namespace + " and action name " + actionName);
+		}
+
+		this.actionName = actionName;
+		this.namespace = namespace;
+		this.executeResult = executeResult;
+        this.method = methodName;
+    }
+    
+    @Inject
+    public void setObjectFactory(ObjectFactory factory) {
+        this.objectFactory = factory;
+    }
+    
+    @Inject
+    public void setConfiguration(Configuration config) {
+        this.configuration = config;
+    }
+    
+    @Inject
+    public void setUnknownHandler(UnknownHandlerManager unknownHandlerManager) {
+        this.unknownHandlerManager = unknownHandlerManager;
+    }
+    
+    @Inject(required=false) 
+    public void setActionEventListener(ActionEventListener listener) {
+        this.actionEventListener = listener;
+    }
+
+    public Object getAction() {
+        return invocation.getAction();
+    }
+
+    public String getActionName() {
+        return actionName;
+    }
+
+    public ActionConfig getConfig() {
+        return config;
+    }
+    
+    public void setExecuteResult(boolean executeResult) {
+        this.executeResult = executeResult;
+    }
+
+    public boolean getExecuteResult() {
+        return executeResult;
+    }
+
+    public ActionInvocation getInvocation() {
+        return invocation;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public String execute() throws Exception {
+        ActionContext nestedContext = ActionContext.getContext();
+        ActionContext.setContext(invocation.getInvocationContext());
+
+        String retCode = null;
+
+        String profileKey = "execute: ";
+        try {
+        	UtilTimerStack.push(profileKey);
+        	
+            retCode = invocation.invoke();
+        } finally {
+            if (cleanupContext) {
+                ActionContext.setContext(nestedContext);
+            }
+            UtilTimerStack.pop(profileKey);
+        }
+
+        return retCode;
+    }
+
+
+    public String getMethod() {
+        return method;
+    }
+
+    private void resolveMethod() {
+        // if the method is set to null, use the one from the configuration
+        // if the one from the configuration is also null, use "execute"
+        if (StringUtils.isEmpty(this.method)) {
+            this.method = config.getMethodName();
+            if (StringUtils.isEmpty(this.method)) {
+                this.method = "execute";
+            }
+        }
+    }
+
+    protected void prepare()  {
+        String profileKey = "create DefaultActionProxy: ";
+        try {
+            UtilTimerStack.push(profileKey);
+            config = configuration.getRuntimeConfiguration().getActionConfig(namespace, actionName);
+    
+            if (config == null && unknownHandlerManager.hasUnknownHandlers()) {
+                config = unknownHandlerManager.handleUnknownAction(namespace, actionName);
+            }
+            if (config == null) {
+                String message;
+    
+                if ((namespace != null) && (namespace.trim().length() > 0)) {
+                    message = LocalizedTextUtil.findDefaultText(XWorkMessages.MISSING_PACKAGE_ACTION_EXCEPTION, Locale.getDefault(), new String[]{
+                        namespace, actionName
+                    });
+                } else {
+                    message = LocalizedTextUtil.findDefaultText(XWorkMessages.MISSING_ACTION_EXCEPTION, Locale.getDefault(), new String[]{
+                        actionName
+                    });
+                }
+                throw new ConfigurationException(message);
+            }
+
+            resolveMethod();
+            
+            if (!config.isAllowedMethod(method)) {
+                throw new ConfigurationException("Invalid method: "+method+" for action "+actionName);
+            }
+
+            invocation.init(this);
+
+        } finally {
+            UtilTimerStack.pop(profileKey);
+        }
+    }
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxyFactory.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxyFactory.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxyFactory.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxyFactory.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+
+import java.util.Map;
+
+
+/**
+ * Default factory for {@link com.opensymphony.xwork2.ActionProxyFactory}.
+ *
+ * @author Jason Carreira
+ */
+public class DefaultActionProxyFactory implements ActionProxyFactory {
+
+    protected Container container;
+    
+    public DefaultActionProxyFactory() {
+        super();
+    }
+    
+    @Inject
+    public void setContainer(Container container) {
+        this.container = container;
+    }
+    
+    public ActionProxy createActionProxy(String namespace, String actionName, Map<String, Object> extraContext) {
+        return createActionProxy(namespace, actionName, null, extraContext, true, true);
+    }
+
+    public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext) {
+        return createActionProxy(namespace, actionName, methodName, extraContext, true, true);
+    }
+
+    public ActionProxy createActionProxy(String namespace, String actionName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext) {
+        return createActionProxy(namespace, actionName, null, extraContext, executeResult, cleanupContext);
+    }
+
+    public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext) {
+        
+        ActionInvocation inv = new DefaultActionInvocation(extraContext, true);
+        container.inject(inv);
+        return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
+    }
+    
+    public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, boolean executeResult, boolean cleanupContext) {
+        
+        return createActionProxy(inv, namespace, actionName, null, executeResult, cleanupContext);
+    }
+
+    public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
+
+        DefaultActionProxy proxy = new DefaultActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
+        container.inject(proxy);
+        proxy.prepare();
+        return proxy;
+    }
+
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxyFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxyFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultTextProvider.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultTextProvider.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultTextProvider.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultTextProvider.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import com.opensymphony.xwork2.util.LocalizedTextUtil;
+import com.opensymphony.xwork2.util.ValueStack;
+
+import java.io.Serializable;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ResourceBundle;
+
+/**
+ * DefaultTextProvider gets texts from only the default resource bundles associated with the
+ * LocalizedTextUtil.
+ *
+ * @author Jason Carreira <jc...@gmail.com>
+ * @author Rainer Hermanns
+ * @see LocalizedTextUtil#addDefaultResourceBundle(String)
+ */
+public class DefaultTextProvider implements TextProvider, Serializable, Unchainable {
+
+    private static final Object[] EMPTY_ARGS = new Object[0];
+
+    public DefaultTextProvider() {
+    }
+
+    public boolean hasKey(String key) {
+        return getText(key) != null;
+    }
+
+    public String getText(String key) {
+        return LocalizedTextUtil.findDefaultText(key, ActionContext.getContext().getLocale());
+    }
+
+    public String getText(String key, String defaultValue) {
+        String text = getText(key);
+        if (text == null) {
+            return defaultValue;
+        }
+        return text;
+    }
+
+    public String getText(String key, List<Object> args) {
+        Object[] params;
+        if (args != null) {
+            params = args.toArray();
+        } else {
+            params = EMPTY_ARGS;
+        }
+
+        return LocalizedTextUtil.findDefaultText(key, ActionContext.getContext().getLocale(), params);
+    }
+
+    public String getText(String key, String[] args) {
+        Object[] params;
+        if (args != null) {
+            params = args;
+        } else {
+            params = EMPTY_ARGS;
+        }
+
+        return LocalizedTextUtil.findDefaultText(key, ActionContext.getContext().getLocale(), params);
+    }
+
+    public String getText(String key, String defaultValue, List<Object> args) {
+        String text = getText(key, args);
+        if(text == null && defaultValue == null) {
+            defaultValue = key;
+        }
+        if (text == null && defaultValue != null) {
+
+            MessageFormat format = new MessageFormat(defaultValue);
+            format.setLocale(ActionContext.getContext().getLocale());
+            format.applyPattern(defaultValue);
+
+            Object[] params;
+            if (args != null) {
+                params = args.toArray();
+            } else {
+                params = EMPTY_ARGS;
+            }
+
+            return format.format(params);
+        }
+        return text;        
+    }
+
+    public String getText(String key, String defaultValue, String[] args) {
+        String text = getText(key, args);
+        if (text == null) {
+            MessageFormat format = new MessageFormat(defaultValue);
+            format.setLocale(ActionContext.getContext().getLocale());
+            format.applyPattern(defaultValue);
+
+            if (args == null) {
+                return format.format(EMPTY_ARGS);
+            }
+
+            return format.format(args);
+        }
+        return text;
+    }
+
+
+    public String getText(String key, String defaultValue, String obj) {
+        List<Object> args = new ArrayList<Object>(1);
+        args.add(obj);
+        return getText(key, defaultValue, args);
+    }
+
+    public String getText(String key, String defaultValue, List<Object> args, ValueStack stack) {
+        //we're not using the value stack here
+        return getText(key, defaultValue, args);
+    }
+
+    public String getText(String key, String defaultValue, String[] args, ValueStack stack) {
+        //we're not using the value stack here
+        List<Object> values = new ArrayList<Object>(Arrays.asList(args));
+        return getText(key, defaultValue, values);
+    }
+
+    public ResourceBundle getTexts(String bundleName) {
+        return LocalizedTextUtil.findResourceBundle(bundleName, ActionContext.getContext().getLocale());
+    }
+
+    public ResourceBundle getTexts() {
+        return null;
+    }
+
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultTextProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultTextProvider.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultUnknownHandlerManager.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultUnknownHandlerManager.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultUnknownHandlerManager.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultUnknownHandlerManager.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.Result;
+import com.opensymphony.xwork2.UnknownHandler;
+import com.opensymphony.xwork2.UnknownHandlerManager;
+import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.UnknownHandlerConfig;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+
+/**
+ * Default implementation of UnknownHandlerManager
+ *
+ * @see com.opensymphony.xwork2.UnknownHandlerManager
+ */
+public class DefaultUnknownHandlerManager implements UnknownHandlerManager {
+    protected ArrayList<UnknownHandler> unknownHandlers;
+    private Configuration configuration;
+    private Container container;
+
+    @Inject
+    public void setConfiguration(Configuration configuration) {
+        this.configuration = configuration;
+        build();
+    }
+
+    @Inject
+    public void setContainer(Container container) {
+        this.container = container;
+        build();
+    }
+
+    /**
+     * Builds a list of UnknowHandlers in the order specified by the configured "unknown-handler-stack".
+     * If "unknown-handler-stack" was not configured, all UnknowHandlers will be returned, in no specific order
+     */
+    protected void build() {
+        if (configuration != null && container != null) {
+            List<UnknownHandlerConfig> unkownHandlerStack = configuration.getUnknownHandlerStack();
+            unknownHandlers = new ArrayList<UnknownHandler>();
+
+            if (unkownHandlerStack != null && !unkownHandlerStack.isEmpty()) {
+                //get UnknownHandlers in the specified order
+                for (UnknownHandlerConfig unknownHandlerConfig : unkownHandlerStack) {
+                    UnknownHandler uh = container.getInstance(UnknownHandler.class, unknownHandlerConfig.getName());
+                    unknownHandlers.add(uh);
+                }
+            } else {
+                //add all available UnknownHandlers
+                Set<String> unknowHandlerNames = container.getInstanceNames(UnknownHandler.class);
+                if (unknowHandlerNames != null) {
+                    for (String unknowHandlerName : unknowHandlerNames) {
+                        UnknownHandler uh = container.getInstance(UnknownHandler.class, unknowHandlerName);
+                        unknownHandlers.add(uh);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Iterate over UnknownHandlers and return the result of the first one that can handle it
+     */
+    public Result handleUnknownResult(ActionContext actionContext, String actionName, ActionConfig actionConfig, String resultCode) {
+        for (UnknownHandler unknownHandler : unknownHandlers) {
+            Result result = unknownHandler.handleUnknownResult(actionContext, actionName, actionConfig, resultCode);
+            if (result != null)
+                return result;
+        }
+
+        return null;
+    }
+
+    /**
+     * Iterate over UnknownHandlers and return the result of the first one that can handle it
+     *
+     * @throws NoSuchMethodException
+     */
+    public Object handleUnknownMethod(Object action, String methodName) throws NoSuchMethodException {
+        for (UnknownHandler unknownHandler : unknownHandlers) {
+            Object result = unknownHandler.handleUnknownActionMethod(action, methodName);
+            if (result != null)
+                return result;
+        }
+
+        return null;
+    }
+
+    /**
+     * Iterate over UnknownHandlers and return the result of the first one that can handle it
+     *
+     * @throws NoSuchMethodException
+     */
+    public ActionConfig handleUnknownAction(String namespace, String actionName) {
+        for (UnknownHandler unknownHandler : unknownHandlers) {
+            ActionConfig result = unknownHandler.handleUnknownAction(namespace, actionName);
+            if (result != null)
+                return result;
+        }
+
+        return null;
+    }
+
+    public boolean hasUnknownHandlers() {
+        return unknownHandlers != null && !unknownHandlers.isEmpty();
+    }
+
+    public List<UnknownHandler> getUnknownHandlers() {
+        return unknownHandlers;
+    }
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultUnknownHandlerManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/DefaultUnknownHandlerManager.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/InvalidMetadataException.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/InvalidMetadataException.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/InvalidMetadataException.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/InvalidMetadataException.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+/**
+ * <code>InvalidMetadataException</code>
+ *
+ * @author Rainer Hermanns
+ * @version $Id$
+ */
+public class InvalidMetadataException extends RuntimeException {
+
+    /**
+	 * Create a new <code>InvalidMetadataException</code> with the supplied error message.
+     * 
+	 * @param msg the error message
+	 */
+	public InvalidMetadataException(String msg) {
+		super(msg);
+	}
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/InvalidMetadataException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/InvalidMetadataException.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/LocaleProvider.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/LocaleProvider.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/LocaleProvider.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/LocaleProvider.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import java.util.Locale;
+
+
+/**
+ * Indicates that the implementing class can provide its own {@link Locale}.
+ * <p/>
+ * This is useful for when an action may wish override the default locale. All that is
+ * needed is to implement this interface and return your own custom locale.
+ * The {@link TextProvider} interface uses this interface heavily for retrieving
+ * internationalized messages from resource bundles.
+ *
+ * @author Jason Carreira
+ */
+public interface LocaleProvider {
+
+    /**
+     * Gets the provided locale.
+     *
+     * @return  the locale.
+     */
+    Locale getLocale();
+
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/LocaleProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/LocaleProvider.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/MockActionInvocation.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/MockActionInvocation.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/MockActionInvocation.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/MockActionInvocation.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+
+package com.opensymphony.xwork2;
+
+/**
+ * Mock for an {@link ActionInvocation}.
+ *
+ * @author plightbo
+ * @deprecated Please use @see com.opensymphony.xwork2.mock.MockActionInvocation instead
+ */
+@Deprecated public class MockActionInvocation extends com.opensymphony.xwork2.mock.MockActionInvocation {
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/MockActionInvocation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/MockActionInvocation.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+
+/**
+ * ModelDriven Actions provide a model object to be pushed onto the ValueStack
+ * in addition to the Action itself, allowing a FormBean type approach like Struts.
+ *
+ * @author Jason Carreira
+ */
+public interface ModelDriven<T> {
+
+    /**
+     * Gets the model to be pushed onto the ValueStack instead of the Action itself.
+     *
+     * @return the model
+     */
+    T getModel();
+
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ObjectFactory.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ObjectFactory.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ObjectFactory.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ObjectFactory.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.InterceptorConfig;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import com.opensymphony.xwork2.util.ClassLoaderUtil;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import com.opensymphony.xwork2.util.reflection.ReflectionException;
+import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
+import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
+import com.opensymphony.xwork2.validator.Validator;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * ObjectFactory is responsible for building the core framework objects. Users may register their 
+ * own implementation of the ObjectFactory to control instantiation of these Objects.
+ * <p/>
+ * This default implementation uses the {@link #buildBean(Class,java.util.Map) buildBean} 
+ * method to create all classes (interceptors, actions, results, etc).
+ * <p/>
+ *
+ * @author Jason Carreira
+ */
+public class ObjectFactory implements Serializable {
+    private static final Logger LOG = LoggerFactory.getLogger(ObjectFactory.class);
+
+    private transient ClassLoader ccl;
+    private Container container;
+    protected ReflectionProvider reflectionProvider;
+
+    @Inject(value="objectFactory.classloader", required=false)
+    public void setClassLoader(ClassLoader cl) {
+        this.ccl = cl;
+    }
+    
+    @Inject
+    public void setReflectionProvider(ReflectionProvider prov) {
+        this.reflectionProvider = prov;
+    }
+
+    public ObjectFactory() {
+    }
+    
+    public ObjectFactory(ReflectionProvider prov) {
+        this.reflectionProvider = prov;
+    }
+    
+    @Inject
+    public void setContainer(Container container) {
+        this.container = container;
+    }
+
+    /**
+     * @deprecated Since 2.1
+     */
+    @Deprecated public static ObjectFactory getObjectFactory() {
+        return ActionContext.getContext().getContainer().getInstance(ObjectFactory.class);
+    }
+
+    /**
+     * Allows for ObjectFactory implementations that support
+     * Actions without no-arg constructors.
+     *
+     * @return true if no-arg constructor is required, false otherwise
+     */
+    public boolean isNoArgConstructorRequired() {
+        return true;
+    }
+
+    /**
+     * Utility method to obtain the class matched to className. Caches look ups so that subsequent
+     * lookups will be faster.
+     *
+     * @param className The fully qualified name of the class to return
+     * @return The class itself
+     * @throws ClassNotFoundException
+     */
+    public Class getClassInstance(String className) throws ClassNotFoundException {
+        if (ccl != null) {
+            return ccl.loadClass(className);
+        }
+
+        return ClassLoaderUtil.loadClass(className, this.getClass());
+    }
+
+    /**
+     * Build an instance of the action class to handle a particular request (eg. web request)
+     * @param actionName the name the action configuration is set up with in the configuration
+     * @param namespace the namespace the action is configured in
+     * @param config the action configuration found in the config for the actionName / namespace
+     * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
+     * @return instance of the action class to handle a web request
+     * @throws Exception
+     */
+    public Object buildAction(String actionName, String namespace, ActionConfig config, Map<String, Object> extraContext) throws Exception {
+        return buildBean(config.getClassName(), extraContext);
+    }
+
+    /**
+     * Build a generic Java object of the given type.
+     *
+     * @param clazz the type of Object to build
+     * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
+     */
+    public Object buildBean(Class clazz, Map<String, Object> extraContext) throws Exception {
+        return clazz.newInstance();
+    }
+
+    /**
+     * @param obj
+     */
+    protected Object injectInternalBeans(Object obj) {
+        if (obj != null && container != null) {
+            container.inject(obj);
+        }
+        return obj;
+    }
+
+    /**
+     * Build a generic Java object of the given type.
+     *
+     * @param className the type of Object to build
+     * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
+     */
+    public Object buildBean(String className, Map<String, Object> extraContext) throws Exception {
+        return buildBean(className, extraContext, true);
+    }
+    
+    /**
+     * Build a generic Java object of the given type.
+     *
+     * @param className the type of Object to build
+     * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
+     */
+    public Object buildBean(String className, Map<String, Object> extraContext, boolean injectInternal) throws Exception {
+        Class clazz = getClassInstance(className);
+        Object obj = buildBean(clazz, extraContext);
+        if (injectInternal) {
+            injectInternalBeans(obj);
+        }
+        return obj;
+    }
+
+    /**
+     * Builds an Interceptor from the InterceptorConfig and the Map of
+     * parameters from the interceptor reference. Implementations of this method
+     * should ensure that the Interceptor is parameterized with both the
+     * parameters from the Interceptor config and the interceptor ref Map (the
+     * interceptor ref params take precedence), and that the Interceptor.init()
+     * method is called on the Interceptor instance before it is returned.
+     *
+     * @param interceptorConfig    the InterceptorConfig from the configuration
+     * @param interceptorRefParams a Map of params provided in the Interceptor reference in the
+     *                             Action mapping or InterceptorStack definition
+     */
+    public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map<String, String> interceptorRefParams) throws ConfigurationException {
+        String interceptorClassName = interceptorConfig.getClassName();
+        Map<String, String> thisInterceptorClassParams = interceptorConfig.getParams();
+        Map<String, String> params = (thisInterceptorClassParams == null) ? new HashMap<String, String>() : new HashMap<String, String>(thisInterceptorClassParams);
+        params.putAll(interceptorRefParams);
+
+        String message;
+        Throwable cause;
+
+        try {
+            // interceptor instances are long-lived and used across user sessions, so don't try to pass in any extra context
+            Interceptor interceptor = (Interceptor) buildBean(interceptorClassName, null);
+            reflectionProvider.setProperties(params, interceptor);
+            interceptor.init();
+
+            return interceptor;
+        } catch (InstantiationException e) {
+            cause = e;
+            message = "Unable to instantiate an instance of Interceptor class [" + interceptorClassName + "].";
+        } catch (IllegalAccessException e) {
+            cause = e;
+            message = "IllegalAccessException while attempting to instantiate an instance of Interceptor class [" + interceptorClassName + "].";
+        } catch (ClassCastException e) {
+            cause = e;
+            message = "Class [" + interceptorClassName + "] does not implement com.opensymphony.xwork2.interceptor.Interceptor";
+        } catch (Exception e) {
+            cause = e;
+            message = "Caught Exception while registering Interceptor class " + interceptorClassName;
+        } catch (NoClassDefFoundError e) {
+            cause = e;
+            message = "Could not load class " + interceptorClassName + ". Perhaps it exists but certain dependencies are not available?";
+        }
+
+        throw new ConfigurationException(message, cause, interceptorConfig);
+    }
+
+    /**
+     * Build a Result using the type in the ResultConfig and set the parameters in the ResultConfig.
+     *
+     * @param resultConfig the ResultConfig found for the action with the result code returned
+     * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
+     */
+    public Result buildResult(ResultConfig resultConfig, Map<String, Object> extraContext) throws Exception {
+        String resultClassName = resultConfig.getClassName();
+        Result result = null;
+
+        if (resultClassName != null) {
+            result = (Result) buildBean(resultClassName, extraContext);
+            Map<String, String> params = resultConfig.getParams();
+            if (params != null) {
+                for (Map.Entry<String, String> paramEntry : params.entrySet()) {
+                    try {
+                        reflectionProvider.setProperty(paramEntry.getKey(), paramEntry.getValue(), result, extraContext, true);
+                    } catch (ReflectionException ex) {
+                        if (result instanceof ReflectionExceptionHandler) {
+                            ((ReflectionExceptionHandler) result).handle(ex);
+                        }
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Build a Validator of the given type and set the parameters on it
+     *
+     * @param className the type of Validator to build
+     * @param params    property name -> value Map to set onto the Validator instance
+     * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
+     */
+    public Validator buildValidator(String className, Map<String, String> params, Map<String, Object> extraContext) throws Exception {
+        Validator validator = (Validator) buildBean(className, null);
+        reflectionProvider.setProperties(params, validator);
+
+        return validator;
+    }
+
+    static class ContinuationsClassLoader extends ClassLoader {
+        
+    }
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ObjectFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ObjectFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Preparable.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Preparable.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Preparable.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Preparable.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+
+/**
+ * Preparable Actions will have their <code>prepare()</code> method called if the {@link com.opensymphony.xwork2.interceptor.PrepareInterceptor}
+ * is applied to the ActionConfig.
+ *
+ * @author Jason Carreira
+ * @see com.opensymphony.xwork2.interceptor.PrepareInterceptor
+ */
+public interface Preparable {
+
+    /**
+     * This method is called to allow the action to prepare itself.
+     *
+     * @throws Exception thrown if a system level exception occurs.
+     */
+    void prepare() throws Exception;
+    
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Preparable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Preparable.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ResourceBundleTextProvider.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ResourceBundleTextProvider.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ResourceBundleTextProvider.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ResourceBundleTextProvider.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import java.util.ResourceBundle;
+
+/**
+ * Extension Interface for TextProvider to help supporting ResourceBundles.
+ *
+ * @author Rene Gielen
+ */
+public interface ResourceBundleTextProvider extends TextProvider {
+
+    /**
+     * Set the resource bundle to use.
+     *
+     * @param bundle the bundle to use.
+     */
+    void setBundle(ResourceBundle bundle);
+
+    /**
+     * Set the class to use for reading the resource bundle.
+     *
+     * @param clazz the class to use for loading.
+     */
+    void setClazz(Class clazz);
+
+    /**
+     * Set the LocaleProvider to use.
+     *
+     * @param localeProvider the LocaleProvider to use.
+     */
+    void setLocaleProvider(LocaleProvider localeProvider);
+
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ResourceBundleTextProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/ResourceBundleTextProvider.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Result.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Result.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Result.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Result.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import java.io.Serializable;
+
+
+/**
+ * All results (except for <code>Action.NONE</code>) of an {@link Action} are mapped to a View implementation.
+ * <p/>
+ * Examples of Views might be:
+ * <ul>
+ * <li>SwingPanelView - pops up a new Swing panel</li>
+ * <li>ActionChainView - executes another action</li>
+ * <li>SerlvetRedirectView - redirects the HTTP response to a URL</li>
+ * <li>ServletDispatcherView - dispatches the HTTP response to a URL</li>
+ * </ul>
+ *
+ * @author plightbo
+ */
+public interface Result extends Serializable {
+
+    /**
+     * Represents a generic interface for all action execution results.
+     * Whether that be displaying a webpage, generating an email, sending a JMS message, etc.
+     *
+     * @param invocation  the invocation context.
+     * @throws Exception can be thrown.
+     */
+    public void execute(ActionInvocation invocation) throws Exception;
+
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Result.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/Result.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java
URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java?rev=894087&view=auto
==============================================================================
--- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java (added)
+++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java Sun Dec 27 18:00:13 2009
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.ConfigurationManager;
+import com.opensymphony.xwork2.config.ConfigurationProvider;
+import com.opensymphony.xwork2.config.impl.MockConfiguration;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.util.XWorkTestCaseHelper;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+
+/**
+ * Base test class for TestNG unit tests.  Provides common XWork variables
+ * and performs XWork setup and teardown processes
+ */
+public class TestNGXWorkTestCase {
+
+    protected ConfigurationManager configurationManager;
+    protected Configuration configuration;
+    protected Container container;
+    protected ActionProxyFactory actionProxyFactory;
+
+    @BeforeTest
+    protected void setUp() throws Exception {
+        configurationManager = XWorkTestCaseHelper.setUp();
+        configuration = new MockConfiguration();
+        ((MockConfiguration) configuration).selfRegister();
+        container = configuration.getContainer();
+        actionProxyFactory = container.getInstance(ActionProxyFactory.class);
+    }
+
+    @AfterTest
+    protected void tearDown() throws Exception {
+        XWorkTestCaseHelper.tearDown(configurationManager);
+        configurationManager = null;
+        configuration = null;
+        container = null;
+        actionProxyFactory = null;
+    }
+
+    protected void loadConfigurationProviders(ConfigurationProvider... providers) {
+        configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers);
+        configuration = configurationManager.getConfiguration();
+        container = configuration.getContainer();
+        actionProxyFactory = container.getInstance(ActionProxyFactory.class);
+    }
+}

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL