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 0fed1f5 RestContext refactoring.
0fed1f5 is described below
commit 0fed1f55931774eb30d39ebaf35671869296a613
Author: JamesBognar <[email protected]>
AuthorDate: Mon Aug 3 11:38:45 2020 -0400
RestContext refactoring.
---
.../org/apache/juneau/rest/RestCallRouter.java | 107 ---------------------
.../java/org/apache/juneau/rest/RestContext.java | 105 +++++++++++++-------
.../org/apache/juneau/rest/RestMethodContext.java | 16 ++-
3 files changed, 84 insertions(+), 144 deletions(-)
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallRouter.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallRouter.java
deleted file mode 100644
index b945b10..0000000
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallRouter.java
+++ /dev/null
@@ -1,107 +0,0 @@
-//
***************************************************************************************************************************
-// * 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.juneau.rest;
-
-import static javax.servlet.http.HttpServletResponse.*;
-
-import java.util.*;
-
-import javax.servlet.http.*;
-
-import org.apache.juneau.rest.util.*;
-
-/**
- * Represents a group of CallMethods on a REST resource that handle the same
HTTP Method name but with different
- * paths/matchers/guards/etc...
- *
- * <p>
- * Incoming requests for a particular HTTP method type (e.g. <js>"GET"</js>)
are handed off to this class and then
- * dispatched to the appropriate RestJavaMethod.
- */
-public class RestCallRouter {
- private final RestMethodContext[] restJavaMethods;
-
- RestCallRouter(RestMethodContext[] callMethods) {
- this.restJavaMethods = callMethods;
- }
-
- /**
- * Builder class.
- */
- static final class Builder {
- private List<RestMethodContext> childMethods = new
ArrayList<>();
- private String httpMethodName;
-
- Builder(String httpMethodName) {
- this.httpMethodName = httpMethodName;
- }
-
- String getHttpMethodName() {
- return httpMethodName;
- }
-
- Builder add(RestMethodContext m) {
- childMethods.add(m);
- return this;
- }
-
- RestCallRouter build() {
- Collections.sort(childMethods);
- return new RestCallRouter(childMethods.toArray(new
RestMethodContext[childMethods.size()]));
- }
- }
-
- boolean matches(RestCall call) {
- UrlPathInfo pi = call.getUrlPathInfo();
- for (RestMethodContext m : restJavaMethods)
- if (m.matches(pi))
- return true;
- return false;
- }
-
- /**
- * Workhorse method.
- *
- * <p>
- * Routes this request to one of the CallMethods.
- *
- * @param pathInfo The value of {@link
HttpServletRequest#getPathInfo()} (sorta)
- * @return The HTTP response code.
- */
- int invoke(RestCall call) throws Throwable {
- if (restJavaMethods.length == 1) {
- call.restMethodContext(restJavaMethods[0]);
- return restJavaMethods[0].invoke(call);
- }
-
- int maxRc = 0;
- for (RestMethodContext m : restJavaMethods) {
- int rc = m.invoke(call);
- if (rc == SC_OK) {
- call.restMethodContext(m);
- return SC_OK;
- }
- maxRc = Math.max(maxRc, rc);
- }
- return maxRc;
- }
-
- @Override /* Object */
- public String toString() {
- StringBuilder sb = new StringBuilder("RestCallRouter: [\n");
- for (RestMethodContext sm : restJavaMethods)
- sb.append("\t" + sm + "\n");
- sb.append("]");
- return sb.toString();
- }
-}
\ No newline at end of file
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 f3ead19..e6666bd 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
@@ -3598,7 +3598,7 @@ public class RestContext extends BeanContext {
private final Messages msgs;
private final Config config;
private final VarResolver varResolver;
- private final Map<String,RestCallRouter> callRouters;
+ private final Map<String,RestMethodContext[]> methodMap;
private final Map<String,RestMethodContext> callMethods;
private final Map<String,RestContext> childResources;
@SuppressWarnings("deprecation") private final RestLogger logger;
@@ -3855,7 +3855,7 @@ public class RestContext extends BeanContext {
// Done after initializing fields above since we pass
this object to the child resources.
//----------------------------------------------------------------------------------------------------
List<String> methodsFound = new LinkedList<>(); //
Temporary to help debug transient duplicate method issue.
- AMap<String,RestCallRouter.Builder> routers = AMap.of();
+ MethodMapBuilder methodMapBuilder = new
MethodMapBuilder();
AMap<String,RestMethodContext> _javaRestMethods =
AMap.of();
AMap<String,Method>
_startCallMethods = AMap.of(),
@@ -3957,12 +3957,11 @@ public class RestContext extends BeanContext {
};
_javaRestMethods.put(mi.getSimpleName(), sm);
- addToRouter(routers,
"GET", sm);
- addToRouter(routers,
"POST", sm);
+
methodMapBuilder.add("GET", sm).add("POST", sm);
} else {
_javaRestMethods.put(mi.getSimpleName(), sm);
- addToRouter(routers,
httpMethod, sm);
+
methodMapBuilder.add(httpMethod, sm);
}
} catch (Throwable e) {
throw new
RestServletException(e, "Problem occurred trying to initialize methods on class
{0}, methods={1}", rci.inner().getName(),
SimpleJsonSerializer.DEFAULT.serialize(methodsFound));
@@ -4057,10 +4056,7 @@ public class RestContext extends BeanContext {
this.postInitChildFirstMethodParams =
_postInitChildFirstMethodParams.toArray(new
Class[_postInitChildFirstMethodParams.size()][]);
this.destroyMethodParams =
_destroyMethodParams.toArray(new Class[_destroyMethodParams.size()][]);
- AMap<String,RestCallRouter> _callRouters = AMap.of();
- for (RestCallRouter.Builder crb : routers.values())
- _callRouters.put(crb.getHttpMethodName(),
crb.build());
- this.callRouters = _callRouters.unmodifiable();
+ this.methodMap = methodMapBuilder.build();
// Initialize our child resources.
for (Object o : getArrayProperty(REST_children,
Object.class)) {
@@ -4116,10 +4112,23 @@ public class RestContext extends BeanContext {
}
}
- private static void addToRouter(Map<String, RestCallRouter.Builder>
routers, String httpMethodName, RestMethodContext cm) {
- if (! routers.containsKey(httpMethodName))
- routers.put(httpMethodName, new
RestCallRouter.Builder(httpMethodName));
- routers.get(httpMethodName).add(cm);
+ static class MethodMapBuilder extends
TreeMap<String,TreeSet<RestMethodContext>> {
+ private static final long serialVersionUID = 1L;
+
+ MethodMapBuilder add(String httpMethodName, RestMethodContext
mc) {
+ httpMethodName = httpMethodName.toUpperCase();
+ if (! containsKey(httpMethodName))
+ put(httpMethodName, new TreeSet<>());
+ get(httpMethodName).add(mc);
+ return this;
+ }
+
+ Map<String,RestMethodContext[]> build() {
+ Map<String,RestMethodContext[]> m = new
LinkedHashMap<>();
+ for (Map.Entry<String,TreeSet<RestMethodContext>> e :
this.entrySet())
+ m.put(e.getKey(), e.getValue().toArray(new
RestMethodContext[0]));
+ return Collections.unmodifiableMap(m);
+ }
}
/**
@@ -4503,15 +4512,6 @@ public class RestContext extends BeanContext {
}
/**
- * Returns a map of HTTP method names to call routers.
- *
- * @return A map with HTTP method names upper-cased as the keys, and
call routers as the values.
- */
- protected Map<String,RestCallRouter> getCallRouters() {
- return callRouters;
- }
-
- /**
* Returns the resource object.
*
* <p>
@@ -5229,20 +5229,7 @@ public class RestContext extends BeanContext {
} else {
// If the specified method has been defined in
a subclass, invoke it.
- int rc = 0;
- String m = call.getMethod();
-
- if (callRouters.containsKey(m))
- rc = callRouters.get(m).invoke(call);
-
- if ((rc == 0 || rc == 404) &&
callRouters.containsKey("*"))
- rc = callRouters.get("*").invoke(call);
-
- // Should be 405 if the URL pattern matched but
HTTP method did not.
- if (rc == 0)
- for (RestCallRouter rcc :
callRouters.values())
- if (rcc.matches(call))
- rc =
SC_METHOD_NOT_ALLOWED;
+ int rc = findMethodAndInvoke(call);
// Should be 404 if URL pattern didn't match.
if (rc == 0)
@@ -5273,6 +5260,52 @@ public class RestContext extends BeanContext {
finishCall(call);
}
+ private int findMethodAndInvoke(RestCall call) throws Throwable {
+ String m = call.getMethod();
+
+ int rc = 0;
+ if (methodMap.containsKey(m))
+ rc = invoke(methodMap.get(m), call);
+
+ if ((rc == 0 || rc == 404) && methodMap.containsKey("*"))
+ rc = invoke(methodMap.get("*"), call);
+
+ // Should be 405 if the URL pattern matched but HTTP method did
not.
+ if (rc == 0)
+ for (RestMethodContext[] rcc : methodMap.values())
+ if (matches(rcc, call))
+ rc = SC_METHOD_NOT_ALLOWED;
+
+ return rc;
+ }
+
+ private boolean matches(RestMethodContext[] mc, RestCall call) throws
Throwable {
+ UrlPathInfo pi = call.getUrlPathInfo();
+ for (RestMethodContext m : mc)
+ if (m.matches(pi))
+ return true;
+ return false;
+ }
+
+ private int invoke(RestMethodContext[] mc, RestCall call) throws
Throwable {
+ if (mc.length == 1) {
+ call.restMethodContext(mc[0]);
+ return mc[0].invoke(call);
+ }
+
+ int maxRc = 0;
+ for (RestMethodContext m : mc) {
+ int rc = m.invoke(call);
+ if (rc == SC_OK) {
+ call.restMethodContext(m);
+ return SC_OK;
+ }
+ maxRc = Math.max(maxRc, rc);
+ }
+ return maxRc;
+
+ }
+
private boolean isDebug(RestCall call) {
Enablement e = null;
RestMethodContext mc = call.getRestMethodContext();
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
index 5973e96..25b20cc 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodContext.java
@@ -1115,6 +1115,20 @@ public class RestMethodContext extends BeanContext
implements Comparable<RestMet
if (c != 0)
return c;
+ c = compare(method.getParameterCount(),
o.method.getParameterCount());
+ if (c != 0)
+ return c;
+
+ for (int i = 0; i < method.getParameterCount(); i++) {
+ c = compare(method.getParameterTypes()[i].getName(),
o.method.getParameterTypes()[i].getName());
+ if (c != 0)
+ return c;
+ }
+
+ c = compare(method.getReturnType().getName(),
o.method.getReturnType().getName());
+ if (c != 0)
+ return c;
+
return 0;
}
@@ -1176,7 +1190,7 @@ public class RestMethodContext extends BeanContext
implements Comparable<RestMet
@Override /* Object */
public boolean equals(Object o) {
- return (o instanceof RestMethodContext) && eq(this,
(RestMethodContext)o, (x,y)->x.compareTo(y) == 0);
+ return (o instanceof RestMethodContext) && eq(this,
(RestMethodContext)o, (x,y)->x.method.equals(y.method));
}
@Override /* Object */