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 */

Reply via email to