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 cb1b14c  REST refactoring.
cb1b14c is described below

commit cb1b14c13136caf8800a0463bbf93df012202220
Author: JamesBognar <[email protected]>
AuthorDate: Sun Jan 10 13:55:32 2021 -0500

    REST refactoring.
---
 .../java/org/apache/juneau/cp/BeanFactory.java     |  18 ++-
 .../java/org/apache/juneau/rest/RestContext.java   |   9 +-
 .../org/apache/juneau/rest/RestContextBuilder.java | 174 +++++++++++++--------
 .../org/apache/juneau/rest/RestParamDefaults.java  |  19 ++-
 4 files changed, 150 insertions(+), 70 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanFactory.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanFactory.java
index 7583549..a1b20a0 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanFactory.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanFactory.java
@@ -82,6 +82,8 @@ public class BeanFactory {
         * @return This object (for method chaining).
         */
        public <T> BeanFactory addBean(Class<T> c, T t) {
+               if (t != null && ! c.isInstance(t))
+                       throw new BasicRuntimeException("Object not of type 
{0}: {1}", c.getName(), t.getClass().getName());
                if (t == null)
                        beanMap.remove(c);
                else
@@ -171,7 +173,13 @@ public class BeanFactory {
                return null;
        }
 
-       private List<ClassInfo> getMissingParamTypes(List<ClassInfo> 
paramTypes) {
+       /**
+        * Given the list of param types, returns a list of types that are 
missing from this factory.
+        *
+        * @param paramTypes The param types to chec.
+        * @return A list of types that are missing from this factory.
+        */
+       public List<ClassInfo> getMissingParamTypes(List<ClassInfo> paramTypes) 
{
                List<ClassInfo> l = AList.of();
                for (int i = 0; i < paramTypes.size(); i++) {
                        ClassInfo pt = paramTypes.get(i);
@@ -183,7 +191,13 @@ public class BeanFactory {
                return l;
        }
 
-       private Object[] getParams(List<ClassInfo> paramTypes) {
+       /**
+        * Returns the corresponding beans in this factory for the specified 
param types.
+        *
+        * @param paramTypes The param types to get from this factory.
+        * @return The corresponding beans in this factory for the specified 
param types.
+        */
+       public Object[] getParams(List<ClassInfo> paramTypes) {
                Object[] o = new Object[paramTypes.size()];
                for (int i = 0; i < paramTypes.size(); i++) {
                        ClassInfo pt = paramTypes.get(i);
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 acadeba..5932161 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
@@ -3208,7 +3208,8 @@ public class RestContext extends BeanContext {
        private final RestInfoProvider infoProvider;
        private final HttpException initException;
        private final RestContext parentContext;
-       private final BeanFactory rootBeanFactory, beanFactory;
+       final BeanFactory rootBeanFactory;
+       private final BeanFactory beanFactory;
        private final UriResolution uriResolution;
        private final UriRelativity uriRelativity;
        private final ConcurrentHashMap<String,MethodExecStats> methodExecStats 
= new ConcurrentHashMap<>();
@@ -3250,7 +3251,7 @@ public class RestContext extends BeanContext {
         * @throws ServletException Something bad happened.
         */
        public static RestContextBuilder create(Object resource) throws 
ServletException {
-               return new RestContextBuilder(null, resource.getClass(), 
null).init(resource);
+               return new RestContextBuilder(resource.getClass(), 
Optional.empty(), Optional.empty(), Optional.of(resource)).init(resource);
        }
 
        /**
@@ -3263,7 +3264,7 @@ public class RestContext extends BeanContext {
         * @throws ServletException Something bad happened.
         */
        static RestContextBuilder create(ServletConfig servletConfig, Class<?> 
resourceClass, RestContext parentContext) throws ServletException {
-               return new RestContextBuilder(servletConfig, resourceClass, 
parentContext);
+               return new RestContextBuilder(resourceClass, 
Optional.ofNullable(servletConfig), Optional.ofNullable(parentContext), 
Optional.empty());
        }
 
        /**
@@ -5047,6 +5048,8 @@ public class RestContext extends BeanContext {
                                rp[i] = new 
RestParamDefaults.HasQueryObject(mpi);
                        } else if 
(mpi.hasAnnotation(org.apache.juneau.rest.annotation.Method.class)) {
                                rp[i] = new RestParamDefaults.MethodObject(mi, 
t, mpi);
+                       } else if (beanFactory.hasBean(t.inner())) {
+                               rp[i] = new 
RestParamDefaults.BeanFactoryObject(mi, t, mpi, beanFactory);
                        }
 
                        if (rp[i] == null && ! isPreOrPost)
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
index 879cbb6..4fbe9a0 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
@@ -22,6 +22,7 @@ import java.lang.annotation.*;
 import java.lang.reflect.Method;
 import java.nio.charset.*;
 import java.util.*;
+import java.util.stream.*;
 
 import javax.servlet.*;
 
@@ -92,11 +93,9 @@ import org.apache.juneau.utils.*;
 public class RestContextBuilder extends BeanContextBuilder implements 
ServletConfig {
 
        final ServletConfig inner;
-
-       Class<?> resourceClass;
-       Object resource;
-       ServletContext servletContext;
-       RestContext parentContext;
+       final Class<?> resourceClass;
+       final RestContext parentContext;
+       final BeanFactory beanFactory;
 
        
//-----------------------------------------------------------------------------------------------------------------
        // The following fields are meant to be modifiable.
@@ -104,27 +103,43 @@ public class RestContextBuilder extends 
BeanContextBuilder implements ServletCon
        // Read-only snapshots of these will be made in RestServletContext.
        
//-----------------------------------------------------------------------------------------------------------------
 
+       Object resource;
+       ServletContext servletContext;
+
        Config config;
        VarResolverBuilder varResolverBuilder;
 
-       RestContextBuilder(ServletConfig servletConfig, Class<?> resourceClass, 
RestContext parentContext) throws ServletException {
-               this.inner = servletConfig;
-               this.resourceClass = resourceClass;
-               this.parentContext = parentContext;
-
-               ClassInfo rci = ClassInfo.of(resourceClass);
+       RestContextBuilder(Class<?> resourceClass, Optional<ServletConfig> 
servletConfig, Optional<RestContext> parentContext, Optional<Object> resource) 
throws ServletException {
+               try {
 
-               // Default values.
-               partSerializer(OpenApiSerializer.class);
-               partParser(OpenApiParser.class);
-               encoders(IdentityEncoder.INSTANCE);
-               responseHandlers(
-                       ReaderHandler.class,
-                       InputStreamHandler.class,
-                       DefaultHandler.class
-               );
+                       this.resourceClass = resourceClass;
+                       this.inner = servletConfig.orElse(null);
+                       this.parentContext = parentContext.orElse(null);
+
+                       ClassInfo rci = ClassInfo.of(resourceClass);
+
+                       // Default values.
+                       partSerializer(OpenApiSerializer.class);
+                       partParser(OpenApiParser.class);
+                       encoders(IdentityEncoder.INSTANCE);
+                       responseHandlers(
+                               ReaderHandler.class,
+                               InputStreamHandler.class,
+                               DefaultHandler.class
+                       );
+
+                       // Pass-through default values.
+                       if (parentContext.isPresent()) {
+                               RestContext pc = parentContext.get();
+                               set(REST_callLoggerDefault, 
pc.getProperty(REST_callLoggerDefault));
+                               set(REST_debugDefault, 
pc.getProperty(REST_debugDefault));
+                               set(REST_staticFilesDefault, 
pc.getProperty(REST_staticFilesDefault));
+                               set(REST_fileFinderDefault, 
pc.getProperty(REST_fileFinderDefault));
+                       }
 
-               try {
+                       beanFactory = createBeanFactory(parentContext, 
resource);
+                       beanFactory.addBean(RestContextBuilder.class, this);
+                       beanFactory.addBean(ServletConfig.class, 
servletConfig.orElse(this));
 
                        varResolverBuilder = new VarResolverBuilder()
                                .defaultVars()
@@ -133,46 +148,27 @@ public class RestContextBuilder extends 
BeanContextBuilder implements ServletCon
                                .contextObject("crm", 
FileFinder.create().cp(resourceClass,null,true).build());
 
                        VarResolver vr = varResolverBuilder.build();
-
-                       List<AnnotationInfo<Rest>> restAnnotationsParentFirst = 
rci.getAnnotationInfos(Rest.class);
+                       beanFactory.addBean(VarResolver.class, vr);
 
                        // Find our config file.  It's the last non-empty 
@RestResource(config).
-                       String configPath = "";
-                       for (AnnotationInfo<Rest> r : 
restAnnotationsParentFirst)
-                               if (! r.getAnnotation().config().isEmpty())
-                                       configPath = r.getAnnotation().config();
-                       String cf = vr.resolve(configPath);
-
-                       if ("SYSTEM_DEFAULT".equals(cf))
-                               this.config = Config.getSystemDefault();
-
-                       if (this.config == null) {
-                               ConfigBuilder cb = 
Config.create().varResolver(vr);
-                               if (! cf.isEmpty())
-                                       cb.name(cf);
-                               this.config = cb.build();
-                       }
+                       config = createConfig(resourceClass, beanFactory);
+                       beanFactory.addBean(Config.class, config);
 
                        // Add our config file to the variable resolver.
                        
varResolverBuilder.contextObject(ConfigVar.SESSION_config, config);
                        vr = varResolverBuilder.build();
+                       beanFactory.addBean(VarResolver.class, vr);
 
                        // Add the servlet init parameters to our properties.
-                       if (servletConfig != null) {
-                               for (Enumeration<String> ep = 
servletConfig.getInitParameterNames(); ep.hasMoreElements();) {
+                       if (servletConfig.isPresent()) {
+                               ServletConfig sc = servletConfig.get();
+                               for (Enumeration<String> ep = 
sc.getInitParameterNames(); ep.hasMoreElements();) {
                                        String p = ep.nextElement();
-                                       String initParam = 
servletConfig.getInitParameter(p);
+                                       String initParam = 
sc.getInitParameter(p);
                                        set(vr.resolve(p), 
vr.resolve(initParam));
                                }
                        }
 
-                       if (parentContext != null) {
-                               set(REST_callLoggerDefault, 
parentContext.getProperty(REST_callLoggerDefault));
-                               set(REST_debugDefault, 
parentContext.getProperty(REST_debugDefault));
-                               set(REST_staticFilesDefault, 
parentContext.getProperty(REST_staticFilesDefault));
-                               set(REST_fileFinderDefault, 
parentContext.getProperty(REST_fileFinderDefault));
-                       }
-
                        
applyAnnotations(rci.getAnnotationList(ConfigAnnotationFilter.INSTANCE), 
vr.createSession());
 
                } catch (Exception e) {
@@ -194,11 +190,68 @@ public class RestContextBuilder extends 
BeanContextBuilder implements ServletCon
                }
        }
 
+       /**
+        * Creates the bean factory for this builder.
+        *
+        * @param parentContext The parent context if there is one.
+        * @param resource The resource object if it's instantiated at this 
time.
+        * @return A new bean factory.
+        * @throws Exception If bean factory could not be instantiated.
+        */
+       protected BeanFactory createBeanFactory(Optional<RestContext> 
parentContext, Optional<Object> resource) throws Exception {
+               BeanFactory x = null;
+               if (resource.isPresent()) {
+                       BeanFactory bf = new 
BeanFactory(parentContext.isPresent() ? parentContext.get().rootBeanFactory : 
null, resource);
+                       x = bf.createBeanViaMethod(BeanFactory.class, resource, 
"createBeanFactory");
+               }
+               if (x == null && parentContext.isPresent()) {
+                       x = parentContext.get().rootBeanFactory;
+               }
+               return new BeanFactory(x, resource.orElse(null));
+       }
+
+       /**
+        * Creates the config for this builder.
+        *
+        * @param resourceClass The resource class.
+        * @param beanFactory The bean factory to use for creating the config.
+        * @return A new bean factory.
+        * @throws Exception If bean factory could not be instantiated.
+        */
+       protected Config createConfig(Class<?> resourceClass, BeanFactory 
beanFactory) throws Exception {
+               ClassInfo rci = ClassInfo.of(resourceClass);
+               Config x = null;
+               if (resource instanceof Config)
+                       x = (Config)resource;
+               if (x == null)
+                       x = beanFactory.getBean(Config.class).orElse(null);
+
+               // Find our config file.  It's the last non-empty 
@RestResource(config).
+               String configPath = "";
+               for (AnnotationInfo<Rest> r : 
rci.getAnnotationInfos(Rest.class))
+                       if (! r.getAnnotation().config().isEmpty())
+                               configPath = r.getAnnotation().config();
+               VarResolver vr = 
beanFactory.getBean(VarResolver.class).orElseThrow(()->new 
RuntimeException("VarResolver not found."));
+               String cf = vr.resolve(configPath);
+
+               if ("SYSTEM_DEFAULT".equals(cf))
+                       x = Config.getSystemDefault();
+
+               if (x == null) {
+                       ConfigBuilder cb = Config.create().varResolver(vr);
+                       if (! cf.isEmpty())
+                               cb.name(cf);
+                       x = cb.build();
+               }
+               return x;
+       }
+
        /*
         * Calls all @RestHook(INIT) methods on the specified resource object.
         */
        RestContextBuilder init(Object resource) throws ServletException {
                this.resource = resource;
+
                ClassInfo rci = ClassInfo.of(resource).resolved();
 
                Map<String,MethodInfo> map = new LinkedHashMap<>();
@@ -211,31 +264,24 @@ public class RestContextBuilder extends 
BeanContextBuilder implements ServletCon
                        }
                }
                for (MethodInfo m : map.values()) {
-                       assertArgsOnlyOfType(m, RestContextBuilder.class, 
ServletConfig.class);
-                       Class<?>[] pt = 
(Class<?>[])m.getRawParamTypes().toArray();
-                       Object[] args = new Object[pt.length];
-                       for (int i = 0; i < args.length; i++) {
-                               if (pt[i] == RestContextBuilder.class)
-                                       args[i] = this;
-                               else
-                                       args[i] = this.inner;
-                       }
+                       List<ClassInfo> paramTypes = m.getParamTypes();
+
+                       List<ClassInfo> missing = 
beanFactory.getMissingParamTypes(paramTypes);
+                       if (!missing.isEmpty())
+                               throw new RestServletException("Could not call 
@RestHook(INIT) method {0}.{1}.  Could not find prerequisites: {2}.", 
m.getDeclaringClass().getSimpleName(), m.getSignature(), 
missing.stream().map(x->x.getSimpleName()).collect(Collectors.joining(",")));
+
                        try {
-                               m.invoke(resource, args);
+                               m.invoke(resource, 
beanFactory.getParams(paramTypes));
                        } catch (Exception e) {
-                               throw new RestServletException(e, "Exception 
thrown from @RestHook(INIT) method {0}.{0}.", 
m.getDeclaringClass().getSimpleName(), m.getSignature());
+                               throw new RestServletException(e, "Exception 
thrown from @RestHook(INIT) method {0}.{1}.", 
m.getDeclaringClass().getSimpleName(), m.getSignature());
                        }
                }
                return this;
        }
 
-       private static void assertArgsOnlyOfType(MethodInfo m, Class<?>...args) 
{
-               if (! m.argsOnlyOfType(args))
-                       throw new BasicIllegalArgumentException("Invalid 
arguments passed to method {0}.  Only arguments of type {1} are allowed.", m, 
args);
-       }
-
        RestContextBuilder servletContext(ServletContext servletContext) {
                this.servletContext = servletContext;
+               beanFactory.addBean(ServletContext.class, servletContext);
                return this;
        }
 
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 3d0676c..f13a7a2 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
@@ -25,7 +25,7 @@ import javax.servlet.http.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.config.*;
-import org.apache.juneau.cp.Messages;
+import org.apache.juneau.cp.*;
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.http.annotation.Body;
@@ -429,6 +429,23 @@ class RestParamDefaults {
                }
        }
 
+       static final class BeanFactoryObject extends RestMethodParam {
+
+               private final BeanFactory beanFactory;
+               private final ClassInfo type;
+
+               protected BeanFactoryObject(MethodInfo m, ClassInfo t, 
ParamInfo mpi, BeanFactory beanFactory) {
+                       super(OTHER, mpi);
+                       this.beanFactory = beanFactory;
+                       this.type = t;
+               }
+
+               @Override /* RestMethodParam */
+               public Object resolve(RestRequest req, RestResponse res) throws 
Exception {
+                       return 
beanFactory.getBean(type.inner()).orElseThrow(()->new ServletException("Could 
not resolve bean type :" + type.inner().getName()));
+               }
+       }
+
        static final class FormDataObject extends RestMethodParam {
                private final boolean multi;
                private final HttpPartParser partParser;

Reply via email to