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

commit f017e678a31da6f2a7aa20e52640612d1e7ac788
Author: JamesBognar <[email protected]>
AuthorDate: Fri Sep 25 09:49:17 2020 -0400

    REST API refactoring.
---
 .../annotation/RestMethod_ClientVersion_Test.java  |   6 +-
 .../main/java/org/apache/juneau/rest/RestCall.java |  22 +++
 .../java/org/apache/juneau/rest/RestContext.java   | 151 ++++++++++-----------
 .../org/apache/juneau/rest/RestMethodContext.java  |  94 ++++++++++---
 4 files changed, 169 insertions(+), 104 deletions(-)

diff --git 
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_ClientVersion_Test.java
 
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_ClientVersion_Test.java
index 6d2b052..fac19aa 100644
--- 
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_ClientVersion_Test.java
+++ 
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_ClientVersion_Test.java
@@ -55,13 +55,13 @@ public class RestMethod_ClientVersion_Test {
                RestClient a = MockRestClient.build(A.class);
                a.get("/").run().assertBody().is("no-version");
                for (String s : "1, 1.0, 1.0.0, 1.0.1".split("\\s*,\\s*")) {
-                       
a.get("/").clientVersion(s).run().assertBody().is("[1.0,1.0]");
+                       
a.get("/").clientVersion(s).run().assertBody().msg("s=[{0}]",s).is("[1.0,1.0]");
                }
                for (String s : "1.1, 1.1.1, 1.2, 1.9.9".split("\\s*,\\s*")) {
-                       
a.get("/").clientVersion(s).run().assertBody().is("[1.1,2)");
+                       
a.get("/").clientVersion(s).run().assertBody().msg("s=[{0}]").is("[1.1,2)");
                }
                for (String s : "2, 2.0, 2.1, 9, 9.9".split("\\s*,\\s*")) {
-                       a.get("/").clientVersion(s).run().assertBody().is("2");
+                       
a.get("/").clientVersion(s).run().assertBody().msg("s=[{0}]").is("2");
                }
        }
 
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCall.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCall.java
index fc79cad..aa034d6 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCall.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCall.java
@@ -43,6 +43,8 @@ public class RestCall {
        private RestCallLogger logger;
        private RestCallLoggerConfig loggerConfig;
 
+       private UrlPathPatternMatch urlPathPatternMatch;
+
        /**
         * Constructor.
         *
@@ -303,6 +305,26 @@ public class RestCall {
                return this;
        }
 
+       /**
+        * Sets the URL path pattern match on this call.
+        *
+        * @param urlPathPatternMatch The match pattern.
+        * @return This object (for method chaining).
+        */
+       public RestCall urlPathPatternMatch(UrlPathPatternMatch 
urlPathPatternMatch) {
+               this.urlPathPatternMatch = urlPathPatternMatch;
+               return this;
+       }
+
+       /**
+        * Returns the URL path pattern match on this call.
+        *
+        * @return The URL path pattern match on this call.
+        */
+       public UrlPathPatternMatch getUrlPathPatternMatch() {
+               return urlPathPatternMatch;
+       }
+
        
//------------------------------------------------------------------------------------------------------------------
        // Lifecycle methods.
        
//------------------------------------------------------------------------------------------------------------------
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 762264f..582c481 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
@@ -3911,17 +3911,15 @@ public class RestContext extends BeanContext {
                                                        sm = new 
RestMethodContext(smb) {
 
                                                                @Override
-                                                               int 
invoke(RestCall call) throws Throwable {
+                                                               void 
invoke(RestCall call) throws Throwable {
 
-                                                                       int rc 
= super.invoke(call);
-                                                                       if (rc 
!= SC_OK)
-                                                                               
return rc;
+                                                                       
super.invoke(call);
 
                                                                        final 
Object o = call.getOutput();
 
                                                                        if 
("GET".equals(call.getMethod())) {
                                                                                
call.output(rim.getMethodsByPath().keySet());
-                                                                               
return SC_OK;
+                                                                               
return;
 
                                                                        } else 
if ("POST".equals(call.getMethod())) {
                                                                                
String pip = call.getUrlPathInfo().getPath();
@@ -3945,13 +3943,13 @@ public class RestContext extends BeanContext {
                                                                                
                }
                                                                                
                Object output = m.invoke(o, args);
                                                                                
                call.output(output);
-                                                                               
                return SC_OK;
+                                                                               
                return;
                                                                                
        } catch (Exception e) {
                                                                                
                throw toHttpException(e, InternalServerError.class);
                                                                                
        }
                                                                                
}
                                                                        }
-                                                                       return 
SC_NOT_FOUND;
+                                                                       throw 
new NotFound();
                                                                }
                                                        };
 
@@ -4109,32 +4107,6 @@ public class RestContext extends BeanContext {
                }
        }
 
-       static class MethodMapBuilder  {
-               TreeMap<String,TreeSet<RestMethodContext>> map = new 
TreeMap<>();
-               Set<RestMethodContext> list = ASet.of();
-
-
-               MethodMapBuilder add(String httpMethodName, RestMethodContext 
mc) {
-                       httpMethodName = httpMethodName.toUpperCase();
-                       if (! map.containsKey(httpMethodName))
-                               map.put(httpMethodName, new TreeSet<>());
-                       map.get(httpMethodName).add(mc);
-                       list.add(mc);
-                       return this;
-               }
-
-               Map<String,List<RestMethodContext>> getMap() {
-                       Map<String,List<RestMethodContext>> m = new 
LinkedHashMap<>();
-                       for (Map.Entry<String,TreeSet<RestMethodContext>> e : 
map.entrySet())
-                               m.put(e.getKey(), AList.of(e.getValue()));
-                       return Collections.unmodifiableMap(m);
-               }
-
-               List<RestMethodContext> getList() {
-                       return AList.of(list);
-               }
-       }
-
        /**
         * Returns the resource resolver associated with this context.
         *
@@ -5223,18 +5195,13 @@ public class RestContext extends BeanContext {
                        } else {
 
                                // If the specified method has been defined in 
a subclass, invoke it.
-                               int rc = findMethodAndInvoke(call);
-
-                               // Should be 404 if URL pattern didn't match.
-                               if (rc == 0)
-                                       rc = SC_NOT_FOUND;
-
-                               // If not invoked above, see if it's an OPTIONs 
request
-                               if (rc != SC_OK)
-                                       handleNotFound(call.status(rc));
-
-                               if (call.getStatus() == 0)
-                                       call.status(rc);
+                               try {
+                                       findMethod(call).invoke(call);
+                               } catch (NotFound e) {
+                                       if (call.getStatus() == 0)
+                                               call.status(404);
+                                       handleNotFound(call);
+                               }
                        }
 
                        if (call.hasOutput()) {
@@ -5254,50 +5221,44 @@ public class RestContext extends BeanContext {
                finishCall(call);
        }
 
-       private int findMethodAndInvoke(RestCall call) throws Throwable {
+       private RestMethodContext findMethod(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 (List<RestMethodContext> rcc : methodMap.values())
-                               if (matches(rcc, call))
-                                       rc = SC_METHOD_NOT_ALLOWED;
-
-               return rc;
-       }
-
-       private boolean matches(List<RestMethodContext> mc, RestCall call) 
throws Throwable {
-               UrlPathInfo pi = call.getUrlPathInfo();
-               for (RestMethodContext m : mc)
-                       if (m.matches(pi))
-                               return true;
-               return false;
-       }
+               if (methodMap.containsKey(m)) {
+                       for (RestMethodContext mc : methodMap.get(m)) {
+                               int mrc = mc.match(call);
+                               if (mrc == 2)
+                                       return mc;
+                               rc = Math.max(rc, mrc);
+                       }
+               }
 
-       private int invoke(List<RestMethodContext> mc, RestCall call) throws 
Throwable {
-               if (mc.size() == 1) {
-                       call.restMethodContext(mc.get(0));
-                       return mc.get(0).invoke(call);
+               if (methodMap.containsKey("*")) {
+                       for (RestMethodContext mc : methodMap.get("*")) {
+                               int mrc = mc.match(call);
+                               if (mrc == 2)
+                                       return mc;
+                               rc = Math.max(rc, mrc);
+                       }
                }
 
-               int maxRc = 0;
-               for (RestMethodContext m : mc) {
-                       int rc = m.invoke(call);
-                       if (rc == SC_OK) {
-                               call.restMethodContext(m);
-                               return SC_OK;
+               // If no paths matched, see if the path matches any other 
methods.
+               // Note that we don't want to match against "/*" patterns such 
as getOptions().
+               if (rc == 0) {
+                       for (RestMethodContext mc : methods) {
+                               if (! mc.getPathPattern().endsWith("/*")) {
+                                       int mrc = mc.match(call);
+                                       if (mrc == 2)
+                                               throw new MethodNotAllowed();
+                               }
                        }
-                       maxRc = Math.max(maxRc, rc);
                }
-               return maxRc;
 
+               if (rc == 1)
+                       throw new PreconditionFailed("Method ''{0}'' not found 
on resource on path ''{1}'' with matching matcher.", m, call.getPathInfo());
+
+               throw new NotFound();
        }
 
        private boolean isDebug(RestCall call) {
@@ -5743,4 +5704,34 @@ public class RestContext extends BeanContext {
                                .a("useClasspathResourceCaching", 
useClasspathResourceCaching)
                        );
        }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Helpers.
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       static class MethodMapBuilder  {
+               TreeMap<String,TreeSet<RestMethodContext>> map = new 
TreeMap<>();
+               Set<RestMethodContext> set = ASet.of();
+
+
+               MethodMapBuilder add(String httpMethodName, RestMethodContext 
mc) {
+                       httpMethodName = httpMethodName.toUpperCase();
+                       if (! map.containsKey(httpMethodName))
+                               map.put(httpMethodName, new TreeSet<>());
+                       map.get(httpMethodName).add(mc);
+                       set.add(mc);
+                       return this;
+               }
+
+               Map<String,List<RestMethodContext>> getMap() {
+                       AMap<String,List<RestMethodContext>> m = AMap.of();
+                       for (Map.Entry<String,TreeSet<RestMethodContext>> e : 
map.entrySet())
+                               m.put(e.getKey(), AList.of(e.getValue()));
+                       return m.unmodifiable();
+               }
+
+               List<RestMethodContext> getList() {
+                       return AList.of(set).unmodifiable();
+               }
+       }
 }
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 25b20cc..f980e58 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
@@ -13,7 +13,6 @@
 package org.apache.juneau.rest;
 
 import static org.apache.juneau.rest.Enablement.*;
-import static javax.servlet.http.HttpServletResponse.*;
 import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.ObjectUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
@@ -929,21 +928,87 @@ public class RestMethodContext extends BeanContext 
implements Comparable<RestMet
        }
 
        /**
-        * Workhorse method.
+        * Identifies if this method can process the specified call.
         *
-        * @param pathInfo The value of {@link 
HttpServletRequest#getPathInfo()} (sorta)
-        * @return The HTTP response code.
+        * <p>
+        * To process the call, the following must be true:
+        * <ul>
+        *      <li>Path pattern must match.
+        *      <li>Matchers (if any) must match.
+        * </ul>
+        *
+        * @param call The call to check.
+        * @return
+        *      One of the following values:
+        *      <ul>
+        *              <li><c>0</c> - Path doesn't match.
+        *              <li><c>1</c> - Path matched but matchers did not.
+        *              <li><c>2</c> - Matches.
+        *      </ul>
         */
-       int invoke(RestCall call) throws Throwable {
+       protected int match(RestCall call) {
 
-               UrlPathPatternMatch pm = null;
+               UrlPathPatternMatch pm = matchPattern(call);
+
+               if (pm == null)
+                       return 0;
+
+               if (requiredMatchers.length == 0 && optionalMatchers.length == 
0) {
+                       call.urlPathPatternMatch(pm);  // Cache so we don't 
have to recalculate.
+                       return 2;
+               }
+
+               try {
+                       RestRequest req = call.getRestRequest();
+                       RestResponse res = call.getRestResponse();
+
+                       @SuppressWarnings("deprecation")
+                       RequestProperties requestProperties = new 
RequestProperties(req.getVarResolverSession(), properties);
+
+                       req.init(this, requestProperties);
+                       res.init(this, requestProperties);
+
+                       // If the method implements matchers, test them.
+                       for (RestMatcher m : requiredMatchers)
+                               if (! m.matches(req))
+                                       return 1;
+                       if (optionalMatchers.length > 0) {
+                               boolean matches = false;
+                               for (RestMatcher m : optionalMatchers)
+                                       matches |= m.matches(req);
+                               if (! matches)
+                                       return 1;
+                       }
 
+                       call.urlPathPatternMatch(pm);  // Cache so we don't 
have to recalculate.
+                       return 2;
+               } catch (Exception e) {
+                       throw new InternalServerError(e);
+               }
+       }
+
+       private UrlPathPatternMatch matchPattern(RestCall call) {
+               UrlPathPatternMatch pm = null;
                for (UrlPathPattern pp : pathPatterns)
                        if (pm == null)
                                pm = pp.match(call.getUrlPathInfo());
+               return pm;
+       }
 
+
+       /**
+        * Workhorse method.
+        *
+        * @param pathInfo The value of {@link 
HttpServletRequest#getPathInfo()} (sorta)
+        */
+       void invoke(RestCall call) throws Throwable {
+
+               UrlPathPatternMatch pm = call.getUrlPathPatternMatch();
                if (pm == null)
-                       return SC_NOT_FOUND;
+                       pm = matchPattern(call);
+
+               if (pm == null)
+                       throw new NotFound();
 
                RestRequest req = call.getRestRequest();
                RestResponse res = call.getRestResponse();
@@ -960,18 +1025,6 @@ public class RestMethodContext extends BeanContext 
implements Comparable<RestMet
                req.init(this, requestProperties);
                res.init(this, requestProperties);
 
-               // If the method implements matchers, test them.
-               for (RestMatcher m : requiredMatchers)
-                       if (! m.matches(req))
-                               return SC_PRECONDITION_FAILED;
-               if (optionalMatchers.length > 0) {
-                       boolean matches = false;
-                       for (RestMatcher m : optionalMatchers)
-                               matches |= m.matches(req);
-                       if (! matches)
-                               return SC_PRECONDITION_FAILED;
-               }
-
                context.preCall(call);
 
                call.loggerConfig(callLoggerConfig);
@@ -1006,7 +1059,7 @@ public class RestMethodContext extends BeanContext 
implements Comparable<RestMet
 
                        for (RestGuard guard : guards)
                                if (! guard.guard(req, res))
-                                       return SC_OK;
+                                       return;
 
                        Object output;
                        try {
@@ -1055,7 +1108,6 @@ public class RestMethodContext extends BeanContext 
implements Comparable<RestMet
                } catch (InvocationTargetException e) {
                        throw e.getTargetException();
                }
-               return SC_OK;
        }
 //
 //     protected void addStatusCode(int code) {

Reply via email to