You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by mr...@apache.org on 2007/10/20 16:48:29 UTC
svn commit: r586735 - in /struts/sandbox/trunk/struts2-rest-plugin: ./
src/main/java/org/apache/struts2/rest/
src/main/java/org/apache/struts2/rest/handler/ src/main/resources/
src/test/java/org/apache/struts2/rest/
Author: mrdon
Date: Sat Oct 20 07:48:27 2007
New Revision: 586735
URL: http://svn.apache.org/viewvc?rev=586735&view=rev
Log:
Redesigned rest plugin to fit in better with Struts 2 apps and work with the codebehind plugin
Added:
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ContentTypeHandlerSelector.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ContentTypeInterceptor.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/DefaultRestInfo.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ResourceClasspathPackageProvider.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestInfo.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/ContentTypeHandler.java
struts/sandbox/trunk/struts2-rest-plugin/src/test/java/org/apache/struts2/rest/RestActionMapperTest.java
Removed:
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/BasicRestful.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionProxy.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/Restful.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/MimeTypeHandler.java
struts/sandbox/trunk/struts2-rest-plugin/src/test/java/org/apache/struts2/rest/RestActionInvoicationTest.java
Modified:
struts/sandbox/trunk/struts2-rest-plugin/pom.xml
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionInvocation.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionMapper.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionProxyFactory.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/HtmlHandler.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/XStreamJsonHandler.java
struts/sandbox/trunk/struts2-rest-plugin/src/main/resources/struts-plugin.xml
Modified: struts/sandbox/trunk/struts2-rest-plugin/pom.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/pom.xml?rev=586735&r1=586734&r2=586735&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/pom.xml (original)
+++ struts/sandbox/trunk/struts2-rest-plugin/pom.xml Sat Oct 20 07:48:27 2007
@@ -2,18 +2,21 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
-
+ <parent>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-plugins</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ </parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-rest-plugin</artifactId>
- <version>1.0-SNAPSHOT</version>
+ <version>2.1.0-SNAPSHOT</version>
<name>Struts 2 Plugin</name>
<dependencies>
-
<dependency>
<groupId>org.apache.struts</groupId>
- <artifactId>struts2-core</artifactId>
- <version>2.0.8</version>
+ <artifactId>struts2-codebehind-plugin</artifactId>
+ <version>${pom.version}</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
@@ -42,28 +45,7 @@
<version>3.8.1</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>mockobjects</groupId>
- <artifactId>mockobjects-core</artifactId>
- <version>0.09</version>
- <scope>test</scope>
- </dependency>
</dependencies>
-
- <build>
- <defaultGoal>install</defaultGoal>
- <pluginManagement>
- <plugins>
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.5</source>
- <target>1.5</target>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
</project>
Added: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ContentTypeHandlerSelector.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ContentTypeHandlerSelector.java?rev=586735&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ContentTypeHandlerSelector.java (added)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ContentTypeHandlerSelector.java Sat Oct 20 07:48:27 2007
@@ -0,0 +1,49 @@
+package org.apache.struts2.rest;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.struts2.rest.handler.ContentTypeHandler;
+
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+
+public class ContentTypeHandlerSelector {
+
+ private Map<String,ContentTypeHandler> handlers = new HashMap<String,ContentTypeHandler>();
+ private String defaultHandlerName;
+
+ @Inject("struts.rest.defaultHandlerName")
+ public void setDefaultHandlerName(String name) {
+ this.defaultHandlerName = name;
+ }
+
+ @Inject
+ public void setContainer(Container container) {
+ Set<String> names = container.getInstanceNames(ContentTypeHandler.class);
+ for (String name : names) {
+ ContentTypeHandler handler = container.getInstance(ContentTypeHandler.class, name);
+ this.handlers.put(handler.getExtension(), handler);
+ }
+ }
+
+ public ContentTypeHandler getHandlerForRequest(HttpServletRequest req) {
+ String extension = findExtension(req.getRequestURI());
+ if (extension == null) {
+ extension = defaultHandlerName;
+ }
+ return handlers.get(extension);
+ }
+
+ protected String findExtension(String url) {
+ int dotPos = url.lastIndexOf('.');
+ int slashPos = url.lastIndexOf('/');
+ if (dotPos > slashPos && dotPos > -1) {
+ return url.substring(dotPos+1);
+ }
+ return null;
+ }
+}
Added: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ContentTypeInterceptor.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ContentTypeInterceptor.java?rev=586735&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ContentTypeInterceptor.java (added)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ContentTypeInterceptor.java Sat Oct 20 07:48:27 2007
@@ -0,0 +1,41 @@
+package org.apache.struts2.rest;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.rest.handler.ContentTypeHandler;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ModelDriven;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+
+public class ContentTypeInterceptor implements Interceptor {
+
+ ContentTypeHandlerSelector selector;
+
+ @Inject
+ public void setContentTypeHandlerSelector(ContentTypeHandlerSelector sel) {
+ this.selector = sel;
+ }
+
+ public void destroy() {}
+
+ public void init() {}
+
+ public String intercept(ActionInvocation invocation) throws Exception {
+ HttpServletRequest request = ServletActionContext.getRequest();
+ ContentTypeHandler handler = selector.getHandlerForRequest(request);
+
+ Object target = invocation.getAction();
+ if (target instanceof ModelDriven) {
+ target = ((ModelDriven)target).getModel();
+ }
+
+ if (request.getContentLength() > 0) {
+ handler.toObject(request.getInputStream(), target);
+ }
+ return invocation.invoke();
+ }
+
+}
Added: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/DefaultRestInfo.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/DefaultRestInfo.java?rev=586735&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/DefaultRestInfo.java (added)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/DefaultRestInfo.java Sat Oct 20 07:48:27 2007
@@ -0,0 +1,88 @@
+package org.apache.struts2.rest;
+
+import static javax.servlet.http.HttpServletResponse.*;
+
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class DefaultRestInfo implements RestInfo {
+ String resultCode;
+ int status = SC_OK;
+ Object etag;
+ Object locationId;
+ String location;
+ boolean disableCaching;
+ Date lastModified;
+
+ public DefaultRestInfo renderResult(String code) {
+ this.resultCode = code;
+ return this;
+ }
+
+ public DefaultRestInfo withStatus(int code) {
+ this.status = code;
+ return this;
+ }
+
+ public DefaultRestInfo withETag(Object etag) {
+ this.etag = etag;
+ return this;
+ }
+
+ public DefaultRestInfo setLocationId(Object id) {
+ this.locationId = id;
+ return this;
+ }
+
+ public DefaultRestInfo setLocation(String loc) {
+ this.location = loc;
+ return this;
+ }
+
+ public DefaultRestInfo lastModified(Date date) {
+ this.lastModified = date;
+ return this;
+ }
+
+ public DefaultRestInfo disableCaching() {
+ this.disableCaching = true;
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.struts2.rest.RestInfo#apply(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
+ */
+ public String apply(HttpServletRequest request, HttpServletResponse response, Object target) {
+ response.setStatus(status);
+ if (disableCaching) {
+ response.setHeader("Cache-Control", "no-cache");
+ } else if (lastModified != null) {
+ response.setDateHeader("LastModified", lastModified.getTime());
+ } else {
+ if (etag == null) {
+ etag = String.valueOf(target.hashCode());
+ }
+ response.setHeader("ETag", etag.toString());
+ }
+ if (locationId != null) {
+ String url = request.getRequestURL().toString();
+ int lastSlash = url.lastIndexOf("/");
+ int lastDot = url.lastIndexOf(".");
+ if (lastDot > lastSlash && lastDot > -1) {
+ url = url.substring(0, lastDot)+locationId+url.substring(lastDot);
+ } else {
+ url += locationId;
+ }
+ response.setHeader("Location", url);
+ } else if (location != null) {
+ response.setHeader("Location", location);
+ }
+ return resultCode;
+ }
+
+
+
+
+}
Added: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ResourceClasspathPackageProvider.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ResourceClasspathPackageProvider.java?rev=586735&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ResourceClasspathPackageProvider.java (added)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/ResourceClasspathPackageProvider.java Sat Oct 20 07:48:27 2007
@@ -0,0 +1,27 @@
+package org.apache.struts2.rest;
+
+import org.apache.struts2.config.ClasspathPackageProvider;
+
+import com.opensymphony.xwork2.util.ResolverUtil.ClassTest;
+
+/**
+ * Checks for actions ending in Resource indicating a Rest resource
+ */
+public class ResourceClasspathPackageProvider extends ClasspathPackageProvider {
+
+ @Override
+ protected ClassTest createActionClassTest() {
+ return new ClassTest() {
+ // Match Action implementations and classes ending with "Resource"
+ public boolean matches(Class type) {
+ return (type.getSimpleName().endsWith("Resource"));
+ }
+ };
+ }
+
+ @Override
+ protected String getClassSuffix() {
+ return "Resource";
+ }
+
+}
Modified: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionInvocation.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionInvocation.java?rev=586735&r1=586734&r2=586735&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionInvocation.java (original)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionInvocation.java Sat Oct 20 07:48:27 2007
@@ -25,6 +25,7 @@
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.DefaultActionInvocation;
+import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.UnknownHandler;
@@ -32,20 +33,21 @@
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.conversion.impl.XWorkConverter;
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.XWorkConverter;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
+import com.opensymphony.xwork2.util.logging.Logger;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.rest.handler.MimeTypeHandler;
+import org.apache.struts2.rest.handler.ContentTypeHandler;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@@ -75,52 +77,24 @@
*/
public class RestActionInvocation extends DefaultActionInvocation {
- private final Log LOG = LogFactory.getLog(RestActionInvocation.class);
+ private static final long serialVersionUID = 3485701178946428716L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(RestActionInvocation.class);
- private XWorkConverter converter;
- private Map<String,MimeTypeHandler> handlers = new HashMap<String,MimeTypeHandler>();
- private String defaultHandlerName;
-
- protected RestActionInvocation(ObjectFactory objectFactory, UnknownHandler handler, ActionProxy proxy, Map extraContext, boolean pushAction, ActionEventListener actionEventListener) throws Exception {
- super(objectFactory, handler, proxy, extraContext, pushAction,
- actionEventListener);
- }
+ private ContentTypeHandlerSelector handlerSelector;
- protected RestActionInvocation(ObjectFactory objectFactory, UnknownHandler handler, ActionProxy proxy, Map extraContext, boolean pushAction) throws Exception {
- super(objectFactory, handler, proxy, extraContext, pushAction);
+ protected RestActionInvocation(Map extraContext, boolean pushAction) throws Exception {
+ super(extraContext, pushAction);
}
- protected RestActionInvocation(ObjectFactory objectFactory, UnknownHandler handler, ActionProxy proxy, Map extraContext) throws Exception {
- super(objectFactory, handler, proxy, extraContext);
- }
-
- public void setXWorkConverter(XWorkConverter conv) {
- this.converter = conv;
- }
-
- public void setDefaultHandlerName(String name) {
- this.defaultHandlerName = name;
+ @Inject
+ public void setMimeTypeHandlerSelector(ContentTypeHandlerSelector sel) {
+ this.handlerSelector = sel;
}
- public void addMimeTypeHandler(String name, MimeTypeHandler handler) {
- this.handlers.put(name, handler);
- }
-
protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
-
- HttpServletRequest req = ServletActionContext.getRequest();
- String extension = findExtension(req.getRequestURI());
- if (extension == null) {
- extension = defaultHandlerName;
- }
- System.out.println("extension:"+extension);
- MimeTypeHandler handler = handlers.get(extension);
- if (handler != null && req.getContentLength() > 0) {
- invocationContext.getParameters().put("body", handler.toObject(req.getInputStream()));
- }
-
String methodName = proxy.getMethod();
-
+
if (LOG.isDebugEnabled()) {
LOG.debug("Executing action method = " + actionConfig.getMethodName());
}
@@ -131,36 +105,37 @@
boolean methodCalled = false;
Object methodResult = null;
- MethodMatch methodMatch = null;
+ Method method = null;
try {
- methodMatch = findMethod(action, methodName, invocationContext.getParameters());
+ method = getAction().getClass().getMethod(methodName, new Class[0]);
} catch (NoSuchMethodException e) {
// hmm -- OK, try doXxx instead
try {
String altMethodName = "do" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
- methodMatch = findMethod(action, altMethodName, invocationContext.getParameters());
+ method = getAction().getClass().getMethod(altMethodName, new Class[0]);
} catch (NoSuchMethodException e1) {
- throw e;
+ // well, give the unknown handler a shot
+ if (unknownHandler != null) {
+ try {
+ methodResult = unknownHandler.handleUnknownActionMethod(action, methodName);
+ methodCalled = true;
+ } catch (NoSuchMethodException e2) {
+ // throw the original one
+ throw e;
+ }
+ } else {
+ throw e;
+ }
}
}
-
- if (!methodCalled) {
- methodResult = callAction(action, methodMatch, invocationContext.getParameters());
- }
-
- if (methodResult instanceof Result) {
- this.result = (Result) methodResult;
- return null;
- } else {
- if (handler != null && methodResult != null) {
- return handler.fromObject(methodResult, this);
- } else {
- // treat as normal result code
- return (String) methodResult;
- }
+
+ if (!methodCalled) {
+ methodResult = method.invoke(action, new Object[0]);
}
+
+ return processResult(actionConfig, methodResult);
} catch (NoSuchMethodException e) {
- throw new IllegalArgumentException("The " + methodName + "() is not defined in action " + getAction().getClass() + "", 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();
@@ -181,93 +156,41 @@
}
}
- protected Object callAction(Object action, MethodMatch methodMatch, Map reqParams) throws IllegalAccessException, InvocationTargetException {
- Object methodResult;
- Class[] argTypes = methodMatch.method.getParameterTypes();
- Object[] args = new Object[argTypes.length];
-
- int x=0;
- for (String name : methodMatch.params) {
- args[x] = converter.convertValue(null, reqParams.get(name), argTypes[x]);
- x++;
- }
-
- methodResult = methodMatch.method.invoke(action, args);
- return methodResult;
- }
-
- protected MethodMatch findMethod(Object action, String actionName, Map<String,String> params) throws NoSuchMethodException {
-
- // Short cut so that only restful actions get the full method scan treatment
- if (action.getClass().getAnnotation(Restful.class) == null && !(action instanceof BasicRestful)) {
- return new MethodMatch(action.getClass().getMethod(actionName, new Class[0]), Collections.EMPTY_LIST);
- }
- Set<String> paramsInReq = params.keySet();
-
- int max = -1;
- Method method = null;
- List<String> nameParams = null;
-
- for (Method m : action.getClass().getMethods()) {
- String methodName = m.getName();
- if (methodName.startsWith(actionName)) {
- int count = 0;
- List<String> paramsInName = findParamsInName(methodName);
- for (String paramName : paramsInName) {
- if (paramsInReq.contains(paramName)) {
- count++;
- } else {
- count = -1;
- break;
- }
- }
+ protected String processResult(ActionConfig actionConfig, Object methodResult) throws IOException {
+ if (methodResult instanceof Result) {
+ this.explicitResult = (Result) methodResult;
+ return null;
+ } else if (methodResult != null) {
+ HttpServletRequest req = ServletActionContext.getRequest();
+ HttpServletResponse res = ServletActionContext.getResponse();
+ ContentTypeHandler handler = handlerSelector.getHandlerForRequest(req);
+ Object target = action;
+ if (target instanceof ModelDriven) {
+ target = ((ModelDriven)target).getModel();
+ }
+
+ if (methodResult instanceof RestInfo) {
+ RestInfo info = (RestInfo) methodResult;
+ resultCode = info.apply(req, res, target);
+ } else {
+ resultCode = (String) methodResult;
+ }
+
+ String extCode = resultCode+"-"+handler.getExtension();
+ if (actionConfig.getResults().get(extCode) != null) {
+ resultCode = extCode;
+ } else {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
- if (count > max) {
- max = count;
- method = m;
- nameParams = paramsInName;
+ resultCode = handler.fromObject(target, resultCode, bout);
+ if (bout.size() > 0) {
+ res.setContentLength(bout.size());
+ res.setContentType(handler.getContentType());
+ res.getOutputStream().write(bout.toByteArray());
+ res.getOutputStream().close();
}
}
}
-
- if (method == null) {
- throw new NoSuchMethodException("Unable to find method for "+actionName+" with params "+params.keySet());
- }
- return new MethodMatch(method, nameParams);
+ return resultCode;
}
-
- protected List<String> findParamsInName(String name) {
- List<String> list = new ArrayList<String>();
- int withPos = name.indexOf("With");
- if (withPos > -1) {
- String[] params = name.substring(withPos+4).split("And");
- for (int x=0; x<params.length; x++) {
- list.add(params[x].toLowerCase());
- }
- }
- return list;
- }
-
- protected String findExtension(String url) {
- int dotPos = url.lastIndexOf('.');
- int slashPos = url.lastIndexOf('/');
- if (dotPos > slashPos && dotPos > -1) {
- return url.substring(dotPos+1);
- }
- return null;
- }
-
- static class MethodMatch {
- public Method method;
- public List<String> params;
- public MethodMatch(Method method, List<String> params) {
- super();
- this.method = method;
- this.params = params;
- }
-
-
- }
-
-
}
Modified: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionMapper.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionMapper.java?rev=586735&r1=586734&r2=586735&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionMapper.java (original)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionMapper.java Sat Oct 20 07:48:27 2007
@@ -24,6 +24,8 @@
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
@@ -34,8 +36,6 @@
import java.util.StringTokenizer;
import java.net.URLDecoder;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.apache.struts2.RequestUtils;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
@@ -80,12 +80,12 @@
* </p>
* <ul>
* <li><code>GET: /movie/ => method="index"</code></li>
- * <li><code>GET: /movie/Thrillers => method="view", id="Thrillers"</code></li>
- * <li><code>GET: /movie/Thrillers!edit => method="edit", id="Thrillers"</code></li>
- * <li><code>GET: /movie/new => method="editNew"</code></li>
+ * <li><code>GET: /movie/Thrillers => method="show", id="Thrillers"</code></li>
+ * <li><code>GET: /movie/Thrillers;edit => method="input", id="Thrillers"</code></li>
+ * <li><code>GET: /movie/new => method="input"</code></li>
* <li><code>POST: /movie/ => method="create"</code></li>
* <li><code>PUT: /movie/Thrillers => method="update", id="Thrillers"</code></li>
- * <li><code>DELETE: /movie/Thrillers => method="remove", id="Thrillers"</code></li>
+ * <li><code>DELETE: /movie/Thrillers => method="destroy", id="Thrillers"</code></li>
* </ul>
* <p>
* To simulate the HTTP methods PUT and DELETE, since they aren't supported by HTML,
@@ -102,41 +102,33 @@
*/
public class RestActionMapper extends DefaultActionMapper {
- protected static final Log LOG = LogFactory.getLog(RestActionMapper.class);
- public static final String HTTP_METHOD_PARAM = "__http_method";
- private String idParameterName = null;
- private boolean allowDynamicMethodCalls;
- private List<String> extensions;
+ protected static final Logger LOG = LoggerFactory.getLogger(RestActionMapper.class);
+ public static final String HTTP_METHOD_PARAM = "_method";
+ private String idParameterName = "id";
public RestActionMapper() {
}
- @Inject(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION)
- public void setAllowDynamicMethodCalls(String allow) {
- allowDynamicMethodCalls = "true".equals(allow);
+ public String getIdParameterName() {
+ return idParameterName;
}
-
- @Inject(StrutsConstants.STRUTS_ACTION_EXTENSION)
- public void setExtensions(String extensions) {
- if (!"".equals(extensions)) {
- this.extensions = Arrays.asList(extensions.split(","));
- } else {
- this.extensions = null;
- }
+
+ @Inject(required=false,value=StrutsConstants.STRUTS_ID_PARAMETER_NAME)
+ public void setIdParameterName(String idParameterName) {
+ this.idParameterName = idParameterName;
}
-
public ActionMapping getMapping(HttpServletRequest request,
ConfigurationManager configManager) {
ActionMapping mapping = new ActionMapping();
String uri = getUri(request);
- uri = dropExtension(uri);
+ uri = dropExtension(uri, mapping);
if (uri == null) {
return null;
}
- String fullName = parseNameAndNamespace(uri, mapping, configManager);
+ parseNameAndNamespace(uri, mapping, configManager);
handleSpecialParameters(request, mapping);
@@ -144,23 +136,27 @@
return null;
}
- if (allowDynamicMethodCalls) {
- // handle "name!method" convention.
- String name = mapping.getName();
- int exclamation = name.lastIndexOf("!");
- if (exclamation != -1) {
- mapping.setName(name.substring(0, exclamation));
- mapping.setMethod(name.substring(exclamation + 1));
- }
+ // handle "name!method" convention.
+ String name = mapping.getName();
+ int exclamation = name.lastIndexOf("!");
+ if (exclamation != -1) {
+ mapping.setName(name.substring(0, exclamation));
+ mapping.setMethod(name.substring(exclamation + 1));
}
+ String fullName = mapping.getName();
// Only try something if the action name is specified
if (fullName != null && fullName.length() > 0) {
int lastSlashPos = fullName.lastIndexOf('/');
+ String id = null;
+ if (lastSlashPos > -1) {
+ id = fullName.substring(lastSlashPos+1);
+ }
// If a method hasn't been explicitly named, try to guess using ReST-style patterns
if (mapping.getMethod() == null) {
+ // Handle uris ending in '/'
if (lastSlashPos == fullName.length() -1) {
// Index e.g. foo/
@@ -172,75 +168,44 @@
mapping.setMethod("create");
}
- } else if (lastSlashPos > -1) {
- String id = fullName.substring(lastSlashPos+1);
-
+ // Handle uris with an id at the end
+ } else if (id != null) {
+
+ // Viewing the form to edit an item e.g. foo/1;edit
+ if (isGet(request) && id.endsWith(";edit")) {
+ id = id.substring(0, id.length() - ";edit".length());
+ mapping.setMethod("input");
+
// Viewing the form to create a new item e.g. foo/new
- if (isGet(request) && "new".equals(id)) {
- mapping.setMethod("editNew");
-
- // Viewing an item e.g. foo/1
- } else if (isGet(request)) {
- mapping.setMethod("view");
+ } else if (isGet(request) && "new".equals(id)) {
+ mapping.setMethod("input");
// Removing an item e.g. foo/1
} else if (isDelete(request)) {
- mapping.setMethod("remove");
+ mapping.setMethod("destroy");
+
+ // Viewing an item e.g. foo/1
+ } else if (isGet(request)) {
+ mapping.setMethod("show");
// Updating an item e.g. foo/1
} else if (isPut(request)) {
mapping.setMethod("update");
}
-
- if (idParameterName != null) {
- if (mapping.getParams() == null) {
- mapping.setParams(new HashMap());
- }
- mapping.getParams().put(idParameterName, id);
- }
- }
-
- if (idParameterName != null && lastSlashPos > -1) {
- fullName = fullName.substring(0, lastSlashPos);
}
}
-
- // Try to determine parameters from the url before the action name
- int actionSlashPos = fullName.lastIndexOf('/', lastSlashPos - 1);
- if (actionSlashPos > 0 && actionSlashPos < lastSlashPos) {
- String params = fullName.substring(0, actionSlashPos);
- HashMap<String,String> parameters = new HashMap<String,String>();
- try {
- StringTokenizer st = new StringTokenizer(params, "/");
- boolean isNameTok = true;
- String paramName = null;
- String paramValue;
-
- while (st.hasMoreTokens()) {
- if (isNameTok) {
- paramName = URLDecoder.decode(st.nextToken(), "UTF-8");
- isNameTok = false;
- } else {
- paramValue = URLDecoder.decode(st.nextToken(), "UTF-8");
-
- if ((paramName != null) && (paramName.length() > 0)) {
- parameters.put(paramName, paramValue);
- }
-
- isNameTok = true;
- }
- }
- if (parameters.size() > 0) {
- if (mapping.getParams() == null) {
- mapping.setParams(new HashMap());
- }
- mapping.getParams().putAll(parameters);
+
+ // cut off the id parameter, even if a method is specified
+ if (id != null) {
+ if (!"new".equals(id)) {
+ if (mapping.getParams() == null) {
+ mapping.setParams(new HashMap());
}
- } catch (Exception e) {
- LOG.warn(e);
+ mapping.getParams().put(idParameterName, new String[]{id});
}
- fullName = fullName.substring(actionSlashPos+1);
+ fullName = fullName.substring(0, lastSlashPos);
}
+
mapping.setName(fullName);
}
@@ -248,38 +213,14 @@
}
/**
- * Gets the uri from the request
- *
- * @param request
- * The request
- * @return The uri
- */
- String getUri(HttpServletRequest request) {
- // handle http dispatcher includes.
- String uri = (String) request
- .getAttribute("javax.servlet.include.servlet_path");
- if (uri != null) {
- return uri;
- }
-
- uri = RequestUtils.getServletPath(request);
- if (uri != null && !"".equals(uri)) {
- return uri;
- }
-
- uri = request.getRequestURI();
- return uri.substring(request.getContextPath().length());
- }
-
- /**
- * Parses the name and namespace from the uri
+ * Parses the name and namespace from the uri. Doesn't allow slashes in name.
*
* @param uri
* The uri
* @param mapping
* The action mapping to populate
*/
- String parseNameAndNamespace(String uri, ActionMapping mapping,
+ protected void parseNameAndNamespace(String uri, ActionMapping mapping,
ConfigurationManager configManager) {
String namespace, name;
int lastSlash = uri.lastIndexOf("/");
@@ -293,66 +234,21 @@
namespace = "/";
name = uri.substring(lastSlash + 1);
} else {
- // Try to find the namespace in those defined, defaulting to ""
- Configuration config = configManager.getConfiguration();
- String prefix = uri.substring(0, lastSlash);
- namespace = "";
- // Find the longest matching namespace, defaulting to the default
- for (Iterator i = config.getPackageConfigs().values().iterator(); i
- .hasNext();) {
- String ns = ((PackageConfig) i.next()).getNamespace();
- if (ns != null && prefix.startsWith(ns) && (prefix.length() == ns.length() || prefix.charAt(ns.length()) == '/')) {
- if (ns.length() > namespace.length()) {
- namespace = ns;
- }
- }
- }
-
- name = uri.substring(namespace.length() + 1);
- }
- String fullName = name;
-
- if (name != null) {
- int pos = name.lastIndexOf('/');
- if (pos > -1 && pos < name.length() - 1) {
- name = name.substring(pos + 1);
+ int secondToLastSlash = uri.lastIndexOf('/', lastSlash - 1);
+ if (secondToLastSlash == 0) {
+ namespace = "/";
+ name = uri.substring(secondToLastSlash + 1);
+ } else if (secondToLastSlash > -1) {
+ namespace = uri.substring(0, secondToLastSlash);
+ name = uri.substring(secondToLastSlash + 1);
+ } else {
+ namespace = "";
+ name = uri;
}
}
mapping.setNamespace(namespace);
mapping.setName(name);
- return fullName;
- }
-
- /**
- * Drops the extension from the action name
- *
- * @param name
- * The action name
- * @return The action name without its extension
- */
- String dropExtension(String name) {
- if (name != null) {
- int pos = name.lastIndexOf('.');
- if (pos > -1) {
- return name.substring(0, name.lastIndexOf('.'));
- } else {
- return name;
- }
-
- }
- return null;
- }
-
- /**
- * Returns null if no extension is specified.
- */
- String getDefaultExtension() {
- if (extensions == null) {
- return null;
- } else {
- return (String) extensions.get(0);
- }
}
protected boolean isGet(HttpServletRequest request) {
@@ -375,19 +271,8 @@
if ("delete".equalsIgnoreCase(request.getMethod())) {
return true;
} else {
- return isPost(request) && "delete".equalsIgnoreCase(request.getParameter(HTTP_METHOD_PARAM));
+ return "delete".equalsIgnoreCase(request.getParameter(HTTP_METHOD_PARAM));
}
}
-
- public String getIdParameterName() {
- return idParameterName;
- }
-
- @Inject(required=false,value=StrutsConstants.STRUTS_ID_PARAMETER_NAME)
- public void setIdParameterName(String idParameterName) {
- this.idParameterName = idParameterName;
- }
-
-
}
Modified: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionProxyFactory.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionProxyFactory.java?rev=586735&r1=586734&r2=586735&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionProxyFactory.java (original)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestActionProxyFactory.java Sat Oct 20 07:48:27 2007
@@ -22,7 +22,9 @@
import java.util.Map;
+import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
+import com.opensymphony.xwork2.DefaultActionInvocation;
import com.opensymphony.xwork2.DefaultActionProxyFactory;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
@@ -34,10 +36,9 @@
public class RestActionProxyFactory extends DefaultActionProxyFactory {
public ActionProxy createActionProxy(String namespace, String actionName, Map extraContext, boolean executeResult, boolean cleanupContext) throws Exception {
- ActionProxy proxy = new RestActionProxy(namespace, actionName, extraContext, executeResult, cleanupContext);
- container.inject(proxy);
- proxy.prepare();
- return proxy;
+ ActionInvocation inv = new RestActionInvocation(extraContext, true);
+ container.inject(inv);
+ return createActionProxy(inv, namespace, actionName, extraContext, executeResult, cleanupContext);
}
}
Added: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestInfo.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestInfo.java?rev=586735&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestInfo.java (added)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/RestInfo.java Sat Oct 20 07:48:27 2007
@@ -0,0 +1,10 @@
+package org.apache.struts2.rest;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public interface RestInfo {
+
+ String apply(HttpServletRequest request,
+ HttpServletResponse response, Object target);
+}
\ No newline at end of file
Added: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/ContentTypeHandler.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/ContentTypeHandler.java?rev=586735&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/ContentTypeHandler.java (added)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/ContentTypeHandler.java Sat Oct 20 07:48:27 2007
@@ -0,0 +1,37 @@
+/*
+ * $Id: Restful2ActionMapper.java 540819 2007-05-23 02:48:36Z mrdon $
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.rest.handler;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import com.opensymphony.xwork2.ActionInvocation;
+
+public interface ContentTypeHandler {
+ void toObject(InputStream in, Object target);
+
+ String fromObject(Object obj, String resultCode, OutputStream stream) throws IOException;
+
+ String getContentType();
+
+ String getExtension();
+}
Modified: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/HtmlHandler.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/HtmlHandler.java?rev=586735&r1=586734&r2=586735&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/HtmlHandler.java (original)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/HtmlHandler.java Sat Oct 20 07:48:27 2007
@@ -22,20 +22,27 @@
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Collections;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
-public class HtmlHandler implements MimeTypeHandler {
+public class HtmlHandler implements ContentTypeHandler {
- public String fromObject(Object obj, ActionInvocation inv) throws IOException {
- inv.getStack().push(Collections.singletonMap("body", obj));
- return Action.SUCCESS;
+ public String fromObject(Object obj, String resultCode, OutputStream out) throws IOException {
+ return resultCode;
}
- public Object toObject(InputStream in) {
- return null;
+ public void toObject(InputStream in, Object target) {
+ }
+
+ public String getExtension() {
+ return "xhtml";
+ }
+
+ public String getContentType() {
+ return "application/xhtml+xml";
}
}
Modified: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java?rev=586735&r1=586734&r2=586735&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java (original)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java Sat Oct 20 07:48:27 2007
@@ -32,22 +32,17 @@
import com.opensymphony.xwork2.ActionInvocation;
import com.thoughtworks.xstream.XStream;
-public class XStreamHandler implements MimeTypeHandler {
+public class XStreamHandler implements ContentTypeHandler {
- public String fromObject(Object obj, ActionInvocation inv) throws IOException {
- HttpServletResponse response = ServletActionContext.getResponse();
+ public String fromObject(Object obj, String resultCode, OutputStream out) throws IOException {
XStream xstream = createXStream();
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- xstream.toXML(obj, bout);
- response.getOutputStream().write(bout.toByteArray());
- response.setContentLength(bout.size());
- response.setContentType(getContentType());
+ xstream.toXML(obj, out);
return null;
}
- public Object toObject(InputStream in) {
+ public void toObject(InputStream in, Object target) {
XStream xstream = createXStream();
- return xstream.fromXML(in);
+ xstream.fromXML(in, target);
}
protected XStream createXStream() {
@@ -55,7 +50,10 @@
}
public String getContentType() {
- return "text/xml";
+ return "application/xml";
}
+ public String getExtension() {
+ return "xml";
+ }
}
Modified: struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/XStreamJsonHandler.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/XStreamJsonHandler.java?rev=586735&r1=586734&r2=586735&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/XStreamJsonHandler.java (original)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/java/org/apache/struts2/rest/handler/XStreamJsonHandler.java Sat Oct 20 07:48:27 2007
@@ -35,5 +35,7 @@
return "text/javascript";
}
-
+ public String getExtension() {
+ return "json";
+ }
}
Modified: struts/sandbox/trunk/struts2-rest-plugin/src/main/resources/struts-plugin.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/main/resources/struts-plugin.xml?rev=586735&r1=586734&r2=586735&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/main/resources/struts-plugin.xml (original)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/main/resources/struts-plugin.xml Sat Oct 20 07:48:27 2007
@@ -8,10 +8,14 @@
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="rest" class="org.apache.struts2.rest.RestActionProxyFactory" />
<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="rest" class="org.apache.struts2.rest.RestActionMapper" />
+
+ <bean type="com.opensymphony.xwork2.config.PackageProvider" name="rest" class="org.apache.struts2.rest.ResourceClasspathPackageProvider" />
- <bean type="org.apache.struts2.rest.handler.MimeTypeHandler" name="xml" class="org.apache.struts2.rest.handler.XStreamHandler" />
- <bean type="org.apache.struts2.rest.handler.MimeTypeHandler" name="js" class="org.apache.struts2.rest.handler.XStreamJsonHandler" />
- <bean type="org.apache.struts2.rest.handler.MimeTypeHandler" name="html" class="org.apache.struts2.rest.handler.HtmlHandler" />
+ <bean class="org.apache.struts2.rest.ContentTypeHandlerSelector" />
+
+ <bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="xml" class="org.apache.struts2.rest.handler.XStreamHandler" />
+ <bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="json" class="org.apache.struts2.rest.handler.XStreamJsonHandler" />
+ <bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="html" class="org.apache.struts2.rest.handler.HtmlHandler" />
<constant name="struts.actionProxyFactory" value="rest" />
<constant name="struts.rest.defaultHandlerName" value="xml" />
@@ -21,7 +25,51 @@
<constant name="struts.configuration.classpath.defaultParentPackage" value="rest-default" />
<package name="rest-default" extends="struts-default">
- <default-interceptor-ref name="basicStack"/>
+ <interceptors>
+ <interceptor name="rest" class="org.apache.struts2.rest.ContentTypeInterceptor"/>
+
+ <!-- A complete stack with all the common interceptors in place.
+ Generally, this stack should be the one you use, though it
+ may do more than you need. Also, the ordering can be
+ switched around (ex: if you wish to have your servlet-related
+ objects applied before prepare() is called, you'd need to move
+ servlet-config interceptor up.
+
+ This stack also excludes from the normal validation and workflow
+ the method names input, back, and cancel. These typically are
+ associated with requests that should not be validated.
+ -->
+ <interceptor-stack name="restDefaultStack">
+ <interceptor-ref name="exception"/>
+ <interceptor-ref name="alias"/>
+ <interceptor-ref name="servletConfig"/>
+ <interceptor-ref name="prepare"/>
+ <interceptor-ref name="i18n"/>
+ <interceptor-ref name="chain"/>
+ <interceptor-ref name="debugging"/>
+ <interceptor-ref name="profiling"/>
+ <interceptor-ref name="scopedModelDriven"/>
+ <interceptor-ref name="modelDriven"/>
+ <interceptor-ref name="fileUpload"/>
+ <interceptor-ref name="checkbox"/>
+ <interceptor-ref name="staticParams"/>
+ <interceptor-ref name="params">
+ <param name="excludeParams">dojo\..*</param>
+ </interceptor-ref>
+ <interceptor-ref name="rest" />
+ <interceptor-ref name="conversionError"/>
+ <interceptor-ref name="validation">
+ <param name="excludeMethods">input,back,cancel,browse</param>
+ </interceptor-ref>
+ <interceptor-ref name="workflow">
+ <param name="excludeMethods">input,back,cancel,browse</param>
+ </interceptor-ref>
+ </interceptor-stack>
+
+ </interceptors>
+
+
+ <default-interceptor-ref name="restDefaultStack"/>
</package>
</struts>
Added: struts/sandbox/trunk/struts2-rest-plugin/src/test/java/org/apache/struts2/rest/RestActionMapperTest.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-rest-plugin/src/test/java/org/apache/struts2/rest/RestActionMapperTest.java?rev=586735&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-rest-plugin/src/test/java/org/apache/struts2/rest/RestActionMapperTest.java (added)
+++ struts/sandbox/trunk/struts2-rest-plugin/src/test/java/org/apache/struts2/rest/RestActionMapperTest.java Sat Oct 20 07:48:27 2007
@@ -0,0 +1,38 @@
+package org.apache.struts2.rest;
+
+import org.apache.struts2.dispatcher.mapper.ActionMapping;
+
+import junit.framework.TestCase;
+
+public class RestActionMapperTest extends TestCase {
+
+ private RestActionMapper mapper;
+
+ public void setUp() throws Exception {
+ mapper = new RestActionMapper();
+ }
+
+ public void testParseNameAndNamespace() {
+ tryUri("/foo/23", "/", "foo/23");
+ tryUri("/foo/", "/", "foo/");
+ tryUri("foo", "", "foo");
+ tryUri("/", "/", "");
+ }
+
+ public void testParseNameAndNamespaceWithNamespaces() {
+ tryUri("/ns/foo/23", "/ns", "foo/23");
+ tryUri("/ns/foo/", "/ns", "foo/");
+ }
+
+ public void testParseNameAndNamespaceWithEdit() {
+ tryUri("/ns/foo/23;edit", "/ns", "foo/23;edit");
+ }
+
+ private void tryUri(String uri, String expectedNamespace, String expectedName) {
+ ActionMapping mapping = new ActionMapping();
+ mapper.parseNameAndNamespace(uri, mapping, null);
+ assertEquals(expectedName, mapping.getName());
+ assertEquals(expectedNamespace, mapping.getNamespace());
+ }
+
+}