You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2018/10/19 14:35:08 UTC

[juneau] branch master updated: Re-add support for @Path variables without names.

This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 1039c1f  Re-add support for @Path variables without names.
1039c1f is described below

commit 1039c1f2e6c33dc090cfd0fafd107cad564ea066
Author: JamesBognar <ja...@apache.org>
AuthorDate: Fri Oct 19 10:34:50 2018 -0400

    Re-add support for @Path variables without names.
---
 .../java/org/apache/juneau/rest/RestContext.java   | 10 +++--
 .../org/apache/juneau/rest/RestJavaMethod.java     |  2 +-
 .../org/apache/juneau/rest/RestParamDefaults.java  | 26 +++++++++--
 .../rest/annotation2/PathAnnotationTest.java       | 51 ++++++++++++++++++++++
 4 files changed, 81 insertions(+), 8 deletions(-)

diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 57b3b9b..42f6e98 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -59,6 +59,7 @@ import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.converters.*;
 import org.apache.juneau.rest.exception.*;
 import org.apache.juneau.rest.reshandlers.*;
+import org.apache.juneau.rest.util.UrlPathPattern;
 import org.apache.juneau.rest.vars.*;
 import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.serializer.*;
@@ -3314,7 +3315,7 @@ public final class RestContext extends BeanContext {
 							if (! _preCallMethods.containsKey(sig)) {
 								setAccessible(m, false);
 								_preCallMethods.put(sig, m);
-								_preCallMethodParams.add(findParams(m, true));
+								_preCallMethodParams.add(findParams(m, true, null));
 							}
 							break;
 						}
@@ -3322,7 +3323,7 @@ public final class RestContext extends BeanContext {
 							if (! _postCallMethods.containsKey(sig)) {
 								setAccessible(m, false);
 								_postCallMethods.put(sig, m);
-								_postCallMethodParams.add(findParams(m, true));
+								_postCallMethodParams.add(findParams(m, true, null));
 							}
 							break;
 						}
@@ -4564,11 +4565,12 @@ public final class RestContext extends BeanContext {
 	 *
 	 * @param method The Java method being called.
 	 * @param isPreOrPost Whether this is a {@link HookEvent#PRE_CALL} or {@link HookEvent#POST_CALL}.
+	 * @param pathPattern
 	 * @return The array of resolvers.
 	 * @throws ServletException If an annotation usage error was detected.
 	 */
 	@SuppressWarnings("deprecation")
-	protected RestMethodParam[] findParams(Method method, boolean isPreOrPost) throws ServletException {
+	protected RestMethodParam[] findParams(Method method, boolean isPreOrPost, UrlPathPattern pathPattern) throws ServletException {
 
 		Type[] pt = method.getGenericParameterTypes();
 		RestMethodParam[] rp = new RestMethodParam[pt.length];
@@ -4591,7 +4593,7 @@ public final class RestContext extends BeanContext {
 			} else if (hasAnnotation(FormData.class, method, i) || hasAnnotation(org.apache.juneau.rest.annotation.FormData.class, method, i)) {
 				rp[i] = new RestParamDefaults.FormDataObject(method, i, ps);
 			} else if (hasAnnotation(Path.class, method, i) || hasAnnotation(org.apache.juneau.rest.annotation.Path.class, method, i)) {
-				rp[i] = new RestParamDefaults.PathObject(method, i, ps);
+				rp[i] = new RestParamDefaults.PathObject(method, i, ps, pathPattern);
 			} else if (hasAnnotation(Body.class, method, i) || hasAnnotation(org.apache.juneau.rest.annotation.Body.class, method, i)) {
 				rp[i] = new RestParamDefaults.BodyObject(method, i, ps);
 			} else if (hasAnnotation(Request.class, method, i)) {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
index 6732a7c..a8cb9a5 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
@@ -391,7 +391,7 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 					? immutableList(MediaType.forStrings(resolveVars(vr, m.consumes())))
 					: parsers.getSupportedMediaTypes();
 
-				methodParams = context.findParams(method, false);
+				methodParams = context.findParams(method, false, pathPattern);
 
 				if (hasAnnotation(Response.class, method))
 					responseMeta = ResponseBeanMeta.create(method, serializers.getPropertyStore());
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
index d79c453..11325fe 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
@@ -42,6 +42,7 @@ import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.exception.*;
+import org.apache.juneau.rest.util.UrlPathPattern;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.utils.*;
 
@@ -195,8 +196,8 @@ class RestParamDefaults {
 		private final HttpPartParser partParser;
 		private final HttpPartSchema schema;
 
-		protected PathObject(Method m, int i, PropertyStore ps) {
-			super(PATH, m, i, getName(m, i));
+		protected PathObject(Method m, int i, PropertyStore ps, UrlPathPattern pathPattern) {
+			super(PATH, m, i, getName(m, i, pathPattern));
 			org.apache.juneau.rest.annotation.Path old = getAnnotation(org.apache.juneau.rest.annotation.Path.class, m, i);
 			this.schema = HttpPartSchema.create(Path.class, m, i);
 			if (old != null)
@@ -205,7 +206,7 @@ class RestParamDefaults {
 				this.partParser = createPartParser(schema.getParser(), ps);
 		}
 
-		private static String getName(Method m, int i) {
+		private static String getName(Method m, int i, UrlPathPattern pathPattern) {
 			for (Path h : getAnnotations(Path.class, m, i)) {
 				if (! h.name().isEmpty())
 					return h.name();
@@ -218,6 +219,25 @@ class RestParamDefaults {
 				if (! h.value().isEmpty())
 					return h.value();
 			}
+			if (pathPattern != null) {
+				int idx = 0;
+
+				for (int j = 0; j < i; j++)
+					if (getAnnotation(Path.class, m, i) != null || getAnnotation(org.apache.juneau.rest.annotation.Path.class, m, i) != null)
+						idx++;
+
+				String[] vars = pathPattern.getVars();
+				if (vars.length <= idx)
+					throw new InternalServerError("Number of attribute parameters in method ''{0}'' exceeds the number of URL pattern variables.", m);
+
+				// Check for {#} variables.
+				String idxs = String.valueOf(idx);
+				for (int j = 0; j < vars.length; j++)
+					if (StringUtils.isNumeric(vars[j]) && vars[j].equals(idxs))
+						return vars[j];
+
+				return pathPattern.getVars()[idx];
+			}
 			throw new InternalServerError("@Path used without name or value on method ''{0}'' parameter ''{1}''.", m, i);
 		}
 
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
index e0cf27f..d659603 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
@@ -18,6 +18,7 @@ import static org.junit.Assert.assertEquals;
 
 import java.util.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.http.annotation.Path;
 import org.apache.juneau.rest.*;
@@ -282,6 +283,56 @@ public class PathAnnotationTest {
 	}
 
 	//=================================================================================================================
+	// @Path annotation without name.
+	//=================================================================================================================
+
+	@RestResource
+	public static class E  {
+		@RestMethod(name=GET, path="/x/{foo}/{bar}")
+		public Object normal1(@Path String foo, @Path String bar) {
+			return new ObjectMap().append("m","normal1").append("foo", foo).append("bar", bar);
+		}
+		@RestMethod(name=GET, path="/x/{foo}/x/{bar}/x")
+		public Object normal2(@Path String foo, @Path String bar) {
+			return new ObjectMap().append("m","normal2").append("foo", foo).append("bar", bar);
+		}
+		@RestMethod(name=GET, path="/y/{0}/{1}")
+		public Object numbers1(@Path String foo, @Path String bar) {
+			return new ObjectMap().append("m","numbers1").append("0", foo).append("1", bar);
+		}
+		@RestMethod(name=GET, path="/y/{0}/y/{1}/y")
+		public Object numbers2(@Path String foo, @Path String bar) {
+			return new ObjectMap().append("m","numbers2").append("0", foo).append("1", bar);
+		}
+		@RestMethod(name=GET, path="/z/{1}/z/{0}/z")
+		public Object numbers3(@Path String foo, @Path String bar) {
+			return new ObjectMap().append("m","numbers3").append("0", foo).append("1", bar);
+		}
+	}
+	static MockRest e = MockRest.create(E.class);
+
+	@Test
+	public void e01_normal1() throws Exception {
+		e.get("/x/x1/x2").execute().assertBody("{m:'normal1',foo:'x1',bar:'x2'}");
+	}
+	@Test
+	public void e02_normal2() throws Exception {
+		e.get("/x/x1/x/x2/x").execute().assertBody("{m:'normal2',foo:'x1',bar:'x2'}");
+	}
+	@Test
+	public void e03_numbers1() throws Exception {
+		e.get("/y/y1/y2").execute().assertBody("{m:'numbers1','0':'y1','1':'y2'}");
+	}
+	@Test
+	public void e04_numbers2() throws Exception {
+		e.get("/y/y1/y/y2/y").execute().assertBody("{m:'numbers2','0':'y1','1':'y2'}");
+	}
+	@Test
+	public void e05_numbers3() throws Exception {
+		e.get("/z/z1/z/z2/z").execute().assertBody("{m:'numbers3','0':'z2','1':'z1'}");
+	}
+
+	//=================================================================================================================
 	// @Path on POJO
 	//=================================================================================================================