Author: crazybob Date: Tue Aug 1 17:07:17 2006 New Revision: 427807 URL: http://svn.apache.org/viewvc?rev=427807&view=rev Log: Initial API implementation.
Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ActionContextImpl.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/InterceptorAdapter.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/MessagesImpl.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/RequestContextImpl.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ResultAdapter.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsActionProxy.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsActionProxyFactory.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsObjectFactory.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ValueStackAdapter.java struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/ struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/MessagesTest.java struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/RequestContextTest.java Removed: struts/struts2/trunk/api/src/main/java/org/apache/struts2/spi/ThreadLocalRequestContext.java struts/struts2/trunk/api/src/test/java/org/apache/struts2/spi/ThreadLocalRequestTest.java Modified: struts/struts2/trunk/api/src/main/java/org/apache/struts2/Messages.java struts/struts2/trunk/api/src/main/java/org/apache/struts2/spi/RequestContext.java struts/struts2/trunk/core/pom.xml struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java Modified: struts/struts2/trunk/api/src/main/java/org/apache/struts2/Messages.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/api/src/main/java/org/apache/struts2/Messages.java?rev=427807&r1=427806&r2=427807&view=diff ============================================================================== --- struts/struts2/trunk/api/src/main/java/org/apache/struts2/Messages.java (original) +++ struts/struts2/trunk/api/src/main/java/org/apache/struts2/Messages.java Tue Aug 1 17:07:17 2006 @@ -13,6 +13,8 @@ */ public interface Messages { + // TODO: Use Object[] for args instead of String[]. + /** * Message severity. */ @@ -70,7 +72,7 @@ * @param arguments message arguments * @see Severity.INFO */ - void addInformation(String key, Object... arguments); + void addInformation(String key, String... arguments); /** * Adds warning message. @@ -87,7 +89,7 @@ * @param arguments message arguments * @see Severity.WARN */ - void addWarning(String key, Object... arguments); + void addWarning(String key, String... arguments); /** * Adds error message. @@ -104,7 +106,7 @@ * @param arguments message arguments * @see Severity.ERROR */ - void addError(String key, Object... arguments); + void addError(String key, String... arguments); /** * Adds message. @@ -121,7 +123,7 @@ * @param key message key * @param arguments message arguments */ - void add(Severity severity, String key, Object... arguments); + void add(Severity severity, String key, String... arguments); /** * Gets set of severities for which this [EMAIL PROTECTED] Messages} instance has messages. Not recursive. Modified: struts/struts2/trunk/api/src/main/java/org/apache/struts2/spi/RequestContext.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/api/src/main/java/org/apache/struts2/spi/RequestContext.java?rev=427807&r1=427806&r2=427807&view=diff ============================================================================== --- struts/struts2/trunk/api/src/main/java/org/apache/struts2/spi/RequestContext.java (original) +++ struts/struts2/trunk/api/src/main/java/org/apache/struts2/spi/RequestContext.java Tue Aug 1 17:07:17 2006 @@ -1,7 +1,6 @@ package org.apache.struts2.spi; import org.apache.struts2.Messages; -import org.apache.struts2.spi.ActionContext; import javax.servlet.ServletContext; import javax.servlet.http.Cookie; @@ -71,11 +70,6 @@ * Gets messages. */ Messages getMessages(); - - /** - * Gets error messages. - */ - Messages getErrors(); /** * Gets the servlet request. Modified: struts/struts2/trunk/core/pom.xml URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/pom.xml?rev=427807&r1=427806&r2=427807&view=diff ============================================================================== --- struts/struts2/trunk/core/pom.xml (original) +++ struts/struts2/trunk/core/pom.xml Tue Aug 1 17:07:17 2006 @@ -37,6 +37,12 @@ </dependency> <dependency> + <groupId>org.apache.struts</groupId> + <artifactId>struts2-api</artifactId> + <version>${pom.version}</version> + </dependency> + + <dependency> <groupId>freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.4</version> Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java?rev=427807&r1=427806&r2=427807&view=diff ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java Tue Aug 1 17:07:17 2006 @@ -18,14 +18,13 @@ package org.apache.struts2.dispatcher; import com.opensymphony.xwork2.ActionContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * <!-- SNIPPET START: description --> Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java?rev=427807&r1=427806&r2=427807&view=diff ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java Tue Aug 1 17:07:17 2006 @@ -17,24 +17,23 @@ */ package org.apache.struts2.dispatcher; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import com.opensymphony.util.ClassLoaderUtil; +import com.opensymphony.util.FileManager; +import com.opensymphony.xwork2.*; +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.config.ConfigurationManager; +import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider; +import com.opensymphony.xwork2.util.*; +import com.opensymphony.xwork2.util.location.Location; +import com.opensymphony.xwork2.util.location.LocationUtils; +import freemarker.template.Template; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsConstants; import org.apache.struts2.StrutsStatics; +import org.apache.struts2.impl.StrutsObjectFactory; +import org.apache.struts2.impl.StrutsActionProxyFactory; import org.apache.struts2.config.Settings; import org.apache.struts2.config.StrutsXMLConfigurationProvider; import org.apache.struts2.dispatcher.mapper.ActionMapping; @@ -45,25 +44,13 @@ import org.apache.struts2.util.ObjectFactoryInitializable; import org.apache.struts2.views.freemarker.FreemarkerManager; -import com.opensymphony.util.ClassLoaderUtil; -import com.opensymphony.util.FileManager; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionProxy; -import com.opensymphony.xwork2.ActionProxyFactory; -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.Result; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.ConfigurationManager; -import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider; -import com.opensymphony.xwork2.util.LocalizedTextUtil; -import com.opensymphony.xwork2.util.ObjectTypeDeterminer; -import com.opensymphony.xwork2.util.ObjectTypeDeterminerFactory; -import com.opensymphony.xwork2.util.OgnlValueStack; -import com.opensymphony.xwork2.util.XWorkContinuationConfig; -import com.opensymphony.xwork2.util.location.Location; -import com.opensymphony.xwork2.util.location.LocationUtils; - -import freemarker.template.Template; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.util.*; /** * A utility class the actual dispatcher delegates most of its tasks to. Each instance @@ -74,6 +61,13 @@ * @see org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher */ public class Dispatcher { + + // Set Struts-specific factories. + static { + ObjectFactory.setObjectFactory(new StrutsObjectFactory()); + ActionProxyFactory.setFactory(new StrutsActionProxyFactory()); + } + private static final Log LOG = LogFactory.getLog(Dispatcher.class); private static ThreadLocal<Dispatcher> instance = new ThreadLocal<Dispatcher>(); Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ActionContextImpl.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ActionContextImpl.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ActionContextImpl.java (added) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ActionContextImpl.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,63 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import com.opensymphony.xwork2.ActionInvocation; +import org.apache.struts2.spi.ActionContext; +import org.apache.struts2.spi.Result; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.ArrayList; + +public class ActionContextImpl implements ActionContext { + + final ActionInvocation invocation; + + public ActionContextImpl(ActionInvocation invocation) { + this.invocation = invocation; + } + + public Object getAction() { + return invocation.getAction(); + } + + public Method getMethod() { + String methodName = invocation.getProxy().getMethod(); + try { + return getAction().getClass().getMethod(methodName); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public String getActionName() { + return invocation.getProxy().getActionName(); + } + + public String getNamespacePath() { + return invocation.getProxy().getNamespace(); + } + + // TODO: Do something with these. + List<Result> resultInterceptors = new ArrayList<Result>(); + + public void addResultInterceptor(Result interceptor) { + resultInterceptors.add(interceptor); + } + + public Result getResult() { + // TODO + throw new UnsupportedOperationException(); + } + + public ActionContext getPrevious() { + // TODO + throw new UnsupportedOperationException(); + } + + public ActionContext getNext() { + // TODO + throw new UnsupportedOperationException(); + } +} Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/InterceptorAdapter.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/InterceptorAdapter.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/InterceptorAdapter.java (added) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/InterceptorAdapter.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,47 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import static org.apache.struts2.impl.RequestContextImpl.ILLEGAL_PROCEED; +import com.opensymphony.xwork2.interceptor.Interceptor; +import com.opensymphony.xwork2.ActionInvocation; + +import java.util.concurrent.Callable; + +public class InterceptorAdapter implements Interceptor { + + final org.apache.struts2.spi.Interceptor delegate; + + public InterceptorAdapter(org.apache.struts2.spi.Interceptor delegate) { + this.delegate = delegate; + } + + public String intercept(final ActionInvocation invocation) throws Exception { + final RequestContextImpl requestContext = RequestContextImpl.get(); + + // Save the existing proceed implementation so we can restore it later. + Callable<String> previous = requestContext.getProceed(); + + requestContext.setProceed(new Callable<String>() { + public String call() throws Exception { + // This proceed implementation is no longer valid past this point. + requestContext.setProceed(ILLEGAL_PROCEED); + try { + return invocation.invoke(); + } finally { + // We're valid again. + requestContext.setProceed(this); + } + } + }); + + try { + return delegate.intercept(requestContext); + } finally { + requestContext.setProceed(previous); + } + } + + public void destroy() {} + public void init() {} +} Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/MessagesImpl.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/MessagesImpl.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/MessagesImpl.java (added) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/MessagesImpl.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,126 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import com.opensymphony.xwork2.TextProvider; +import com.opensymphony.xwork2.DefaultTextProvider; +import org.apache.struts2.Messages; + +import java.util.*; + +public class MessagesImpl implements Messages { + + final TextProvider textProvider = DefaultTextProvider.INSTANCE; + Map<String, Messages> fieldMap = new HashMap<String, Messages>(); + Map<Severity, List<String>> severityMap = new EnumMap<Severity, List<String>>(Severity.class); + + public Messages forField(String fieldName) { + Messages forField = fieldMap.get(fieldName); + if (forField == null) { + forField = new MessagesImpl(); + fieldMap.put(fieldName, forField); + } + return forField; + } + + public Map<String, Messages> forFields() { + return fieldMap; + } + + public void addInformation(String key) { + forSeverity(Severity.INFO).add(textProvider.getText(key)); + } + + public void addInformation(String key, String... arguments) { + forSeverity(Severity.INFO).add(textProvider.getText(key, arguments)); + } + + public void addWarning(String key) { + forSeverity(Severity.WARN).add(textProvider.getText(key)); + } + + public void addWarning(String key, String... arguments) { + forSeverity(Severity.WARN).add(textProvider.getText(key, arguments)); + } + + public void addError(String key) { + forSeverity(Severity.ERROR).add(textProvider.getText(key)); + } + + public void addError(String key, String... arguments) { + forSeverity(Severity.ERROR).add(textProvider.getText(key, arguments)); + } + + public void add(Severity severity, String key) { + forSeverity(severity).add(textProvider.getText(key)); + } + + public void add(Severity severity, String key, String... arguments) { + forSeverity(severity).add(textProvider.getText(key, arguments)); + } + + public Set<Severity> getSeverities() { + Set<Severity> severities = EnumSet.noneOf(Severity.class); + for (Severity severity : Severity.values()) { + List<String> messages = severityMap.get(severity); + if (messages != null && !messages.isEmpty()) { + severities.add(severity); + } + } + return Collections.unmodifiableSet(severities); + } + + public List<String> forSeverity(Severity severity) { + List<String> messages = severityMap.get(severity); + if (messages == null) { + messages = new ArrayList<String>(); + severityMap.put(severity, messages); + } + return messages; + } + + public List<String> getErrors() { + return forSeverity(Severity.ERROR); + } + + public List<String> getWarnings() { + return forSeverity(Severity.WARN); + } + + public List<String> getInformation() { + return forSeverity(Severity.INFO); + } + + public boolean hasErrors() { + return !isEmpty(Severity.ERROR); + } + + public boolean hasWarnings() { + return !isEmpty(Severity.WARN); + } + + public boolean hasInformation() { + return !isEmpty(Severity.INFO); + } + + public boolean isEmpty() { + for (Severity severity : Severity.values()) + if (!isEmpty(severity)) + return false; + + return true; + } + + public boolean isEmpty(Severity severity) { + List<String> messages = severityMap.get(severity); + if (messages != null && !messages.isEmpty()) { + return false; + } + + for (Messages fieldMessages : fieldMap.values()) + if (!fieldMessages.isEmpty(severity)) + return false; + + return true; + } +} Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/RequestContextImpl.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/RequestContextImpl.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/RequestContextImpl.java (added) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/RequestContextImpl.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,172 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import com.opensymphony.xwork2.ActionInvocation; +import org.apache.struts2.Messages; +import static org.apache.struts2.StrutsStatics.*; +import org.apache.struts2.dispatcher.RequestMap; +import org.apache.struts2.spi.ActionContext; +import org.apache.struts2.spi.RequestContext; +import org.apache.struts2.spi.ValueStack; + +import javax.servlet.ServletContext; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.Callable; + +public class RequestContextImpl implements RequestContext { + + com.opensymphony.xwork2.ActionContext xworkContext; + ActionContext actionContext; + Messages messages = new MessagesImpl(); + + public static final Callable<String> ILLEGAL_PROCEED = new Callable<String>() { + public String call() throws Exception { + throw new IllegalStateException(); + } + }; + + public RequestContextImpl(com.opensymphony.xwork2.ActionContext xworkContext) { + this.xworkContext = xworkContext; + } + + public ActionContext getActionContext() { + return actionContext; + } + + public Object getAction() { + return getActionContext().getAction(); + } + + void setActionContext(ActionContext actionContext) { + this.actionContext = actionContext; + } + + public Map<String, String[]> getParameterMap() { + return xworkContext.getParameters(); + } + + Map<String, Object> attributeMap; + + public Map<String, Object> getAttributeMap() { + if (attributeMap == null) { + attributeMap = new RequestMap(getServletRequest()); + } + return attributeMap; + } + + public Map<String, Object> getSessionMap() { + return xworkContext.getSession(); + } + + public Map<String, Object> getApplicationMap() { + return xworkContext.getApplication(); + } + + public List<Cookie> findCookiesForName(String name) { + List<Cookie> cookies = new ArrayList<Cookie>(); + for (Cookie cookie : getServletRequest().getCookies()) + if (name.equals(cookie.getName())) + cookies.add(cookie); + + return cookies; + } + + public Locale getLocale() { + return xworkContext.getLocale(); + } + + public void setLocale(Locale locale) { + xworkContext.setLocale(locale); + } + + public Messages getMessages() { + return messages; + } + + public HttpServletRequest getServletRequest() { + return (HttpServletRequest) xworkContext.get(HTTP_REQUEST); + } + + public HttpServletResponse getServletResponse() { + return (HttpServletResponse) xworkContext.get(HTTP_RESPONSE); + } + + public ServletContext getServletContext() { + return (ServletContext) xworkContext.get(SERVLET_CONTEXT); + } + + ValueStack valueStack; + + public ValueStack getValueStack() { + if (valueStack == null) { + valueStack = new ValueStackAdapter(xworkContext.getValueStack()); + } + return valueStack; + } + + Callable<String> proceed = ILLEGAL_PROCEED; + + public String proceed() throws Exception { + return proceed.call(); + } + + public void setProceed(Callable<String> proceed) { + this.proceed = proceed; + } + + public Callable<String> getProceed() { + return proceed; + } + + static ThreadLocal<RequestContextImpl[]> threadLocalRequestContext = new ThreadLocal<RequestContextImpl[]>() { + protected RequestContextImpl[] initialValue() { + return new RequestContextImpl[1]; + } + }; + + /** + * Creates RequestContext if necessary. Always creates a new ActionContext and restores an existing ActionContext + * when finished. + */ + public static String callInContext(ActionInvocation invocation, Callable<String> callable) + throws Exception { + RequestContextImpl[] reference = threadLocalRequestContext.get(); + + if (reference[0] == null) { + // Initial invocation. + reference[0] = new RequestContextImpl(invocation.getInvocationContext()); + reference[0].setActionContext(new ActionContextImpl(invocation)); + try { + return callable.call(); + } finally { + reference[0] = null; + } + } else { + // Nested invocation. + RequestContextImpl requestContext = reference[0]; + ActionContext previous = requestContext.getActionContext(); + requestContext.setActionContext(new ActionContextImpl(invocation)); + try { + return callable.call(); + } finally { + requestContext.setActionContext(previous); + } + } + } + + public static RequestContextImpl get() { + RequestContextImpl requestContext = threadLocalRequestContext.get()[0]; + + if (requestContext == null) + throw new IllegalStateException("RequestContext has not been created."); + + return requestContext; + } +} Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ResultAdapter.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ResultAdapter.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ResultAdapter.java (added) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ResultAdapter.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,19 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import com.opensymphony.xwork2.Result; +import com.opensymphony.xwork2.ActionInvocation; + +public class ResultAdapter implements Result { + + final org.apache.struts2.spi.Result delegate; + + public ResultAdapter(org.apache.struts2.spi.Result delegate) { + this.delegate = delegate; + } + + public void execute(ActionInvocation invocation) throws Exception { + delegate.execute(RequestContextImpl.get()); + } +} Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsActionProxy.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsActionProxy.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsActionProxy.java (added) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsActionProxy.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,33 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import com.opensymphony.xwork2.DefaultActionProxy; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.config.Configuration; + +import java.util.Map; +import java.util.concurrent.Callable; + +public class StrutsActionProxy extends DefaultActionProxy { + + public StrutsActionProxy(Configuration cfg, String namespace, String actionName, Map extraContext, + boolean executeResult, boolean cleanupContext) throws Exception { + super(cfg, namespace, actionName, extraContext, executeResult, cleanupContext); + } + + public String execute() throws Exception { + ActionContext previous = ActionContext.getContext(); + ActionContext.setContext(invocation.getInvocationContext()); + try { + return RequestContextImpl.callInContext(invocation, new Callable<String>() { + public String call() throws Exception { + return invocation.invoke(); + } + }); + } finally { + if (cleanupContext) + ActionContext.setContext(previous); + } + } +} Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsActionProxyFactory.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsActionProxyFactory.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsActionProxyFactory.java (added) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsActionProxyFactory.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,22 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import com.opensymphony.xwork2.ActionProxy; +import com.opensymphony.xwork2.DefaultActionProxyFactory; +import com.opensymphony.xwork2.config.Configuration; + +import java.util.Map; + +public class StrutsActionProxyFactory extends DefaultActionProxyFactory { + + public ActionProxy createActionProxy(Configuration config, String namespace, String actionName, Map extraContext) + throws Exception { + return new StrutsActionProxy(config, namespace, actionName, extraContext, true, true); + } + + public ActionProxy createActionProxy(Configuration config, String namespace, String actionName, Map extraContext, + boolean executeResult, boolean cleanupContext) throws Exception { + return new StrutsActionProxy(config, namespace, actionName, extraContext, executeResult, cleanupContext); + } +} Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsObjectFactory.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsObjectFactory.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsObjectFactory.java (added) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/StrutsObjectFactory.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,84 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.Result; +import com.opensymphony.xwork2.util.OgnlUtil; +import com.opensymphony.xwork2.config.entities.InterceptorConfig; +import com.opensymphony.xwork2.config.entities.ResultConfig; +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.interceptor.Interceptor; + +import java.util.Map; +import java.util.HashMap; + +public class StrutsObjectFactory extends ObjectFactory { + + public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map refParams) + throws ConfigurationException { + String className = interceptorConfig.getClassName(); + + Map<String, String> params = new HashMap<String, String>(); + Map typeParams = interceptorConfig.getParams(); + if (typeParams != null && !typeParams.isEmpty()) + params.putAll(typeParams); + if (refParams != null && !refParams.isEmpty()) + params.putAll(refParams); + params.putAll(refParams); + + try { + // interceptor instances are long-lived and used across user sessions, so don't try to pass in any extra + // context + Object o = buildBean(className, null); + OgnlUtil.setProperties(params, o); + + if (o instanceof Interceptor) { + Interceptor interceptor = (Interceptor) o; + interceptor.init(); + return interceptor; + } + + if (o instanceof org.apache.struts2.spi.Interceptor) + return new InterceptorAdapter((org.apache.struts2.spi.Interceptor) o); + + throw new ConfigurationException( + "Class [" + className + "] does not implement Interceptor", interceptorConfig); + } catch (InstantiationException e) { + throw new ConfigurationException( + "Unable to instantiate an instance of Interceptor class [" + className + "].", + e, interceptorConfig); + } catch (IllegalAccessException e) { + throw new ConfigurationException( + "IllegalAccessException while attempting to instantiate an instance of Interceptor class [" + + className + "].", + e, interceptorConfig); + } catch (Exception e) { + throw new ConfigurationException( + "Caught Exception while registering Interceptor class " + className, + e, interceptorConfig); + } catch (NoClassDefFoundError e) { + throw new ConfigurationException( + "Could not load class " + className + + ". Perhaps it exists but certain dependencies are not available?", + e, interceptorConfig); + } + } + + public Result buildResult(ResultConfig resultConfig, Map extraContext) throws Exception { + String resultClassName = resultConfig.getClassName(); + if (resultClassName == null) + return null; + + Object result = buildBean(resultClassName, extraContext); + OgnlUtil.setProperties(resultConfig.getParams(), result, extraContext); + + if (result instanceof Result) + return (Result) result; + + if (result instanceof org.apache.struts2.spi.Result) + return new ResultAdapter((org.apache.struts2.spi.Result) result); + + throw new ConfigurationException(result.getClass().getName() + " does not implement Result."); + } +} Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ValueStackAdapter.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ValueStackAdapter.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ValueStackAdapter.java (added) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/impl/ValueStackAdapter.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,57 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import com.opensymphony.xwork2.util.OgnlValueStack; +import org.apache.struts2.spi.ValueStack; + +import java.util.Iterator; + +public class ValueStackAdapter implements ValueStack { + + final OgnlValueStack delegate; + + public ValueStackAdapter(OgnlValueStack delegate) { + this.delegate = delegate; + } + + public Object peek() { + return delegate.peek(); + } + + public Object pop() { + return delegate.pop(); + } + + public void push(Object o) { + delegate.push(o); + } + + public ValueStack clone() { + return new ValueStackAdapter(new OgnlValueStack(delegate)); + } + + public Object get(String expr) { + return delegate.findValue(expr); + } + + public <T> T get(String expr, Class<T> requiredType) { + return (T) delegate.findValue(expr, requiredType); + } + + public String getString(String expr) { + return delegate.findString(expr); + } + + public void set(String expr, Object o) { + delegate.set(expr, o); + } + + public int size() { + return delegate.size(); + } + + public Iterator<Object> iterator() { + return delegate.getRoot().iterator(); + } +} \ No newline at end of file Added: struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/MessagesTest.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/MessagesTest.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/MessagesTest.java (added) +++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/MessagesTest.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,30 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import junit.framework.TestCase; +import org.apache.struts2.Messages; + +public class MessagesTest extends TestCase { + + public void testForField() { + Messages messages = new MessagesImpl(); + Messages fieldMessages = messages.forField("foo"); + fieldMessages.addError("foo"); + assertFalse(fieldMessages.getErrors().isEmpty()); + assertTrue(messages.hasErrors()); + } + + public void testHasMessagesForSeverity() { + for (Messages.Severity severity : Messages.Severity.values()) { + Messages messages = new MessagesImpl(); + messages.add(severity, "foo"); + + assertFalse(messages.isEmpty(severity)); + + for (Messages.Severity other : Messages.Severity.values()) + if (other != severity) + assertTrue(messages.isEmpty(other)); + } + } +} Added: struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/RequestContextTest.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/RequestContextTest.java?rev=427807&view=auto ============================================================================== --- struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/RequestContextTest.java (added) +++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/impl/RequestContextTest.java Tue Aug 1 17:07:17 2006 @@ -0,0 +1,67 @@ +// Copyright 2006 Google Inc. All Rights Reserved. + +package org.apache.struts2.impl; + +import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.ActionContext; +import junit.framework.TestCase; +import static org.easymock.EasyMock.*; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.List; +import java.util.HashMap; +import java.util.concurrent.Callable; + +public class RequestContextTest extends TestCase { + + public void testFindCookiesForName() { + final HttpServletRequest servletRequest = createMock(HttpServletRequest.class); + Cookie one = new Cookie("foo", "one"); + Cookie two = new Cookie("foo", "two"); + Cookie three = new Cookie("bar", "three"); + Cookie[] cookies = { one, two, three }; + expect(servletRequest.getCookies()).andReturn(cookies); + + replay(servletRequest); + + RequestContextImpl requestContext = new RequestContextImpl(null) { + public HttpServletRequest getServletRequest() { + return servletRequest; + } + }; + + List<Cookie> fooCookies = Arrays.asList(one, two); + assertEquals(fooCookies, requestContext.findCookiesForName("foo")); + } + + public void testInitialCallInContext() throws Exception { + final ActionInvocation invocation = createMock(ActionInvocation.class); + final ActionContext actionContext = new ActionContext(new HashMap()); + expect(invocation.getInvocationContext()).andReturn(actionContext); + + final boolean[] called = new boolean[1]; + Callable<String> callable = new Callable<String>() { + public String call() throws Exception { + RequestContextImpl requestContext = RequestContextImpl.get(); + assertSame(actionContext, requestContext.xworkContext); + assertSame(invocation, + ((ActionContextImpl) requestContext.getActionContext()).invocation); + called[0] = true; + return "foo"; + } + }; + + replay(invocation); + + assertEquals("foo", RequestContextImpl.callInContext(invocation, callable)); + assertTrue(called[0]); + assertNull(RequestContextImpl.threadLocalRequestContext.get()[0]); + } + + public void testNestedCallInContext() throws Exception { + // TODO: After we implement ActionContext.getNext(), getPrevious(). + } +} +