You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by mb...@apache.org on 2021/08/08 21:50:52 UTC

[roller] 15/19: Extracted common reflection code into new Reflection util.

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

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

commit 5a675ae518c1eb693e7198c6bded776a55369dc0
Author: Michael Bien <mb...@gmail.com>
AuthorDate: Sat Jul 10 10:23:23 2021 +0200

    Extracted common reflection code into new Reflection util.
---
 .../weblogger/business/GuiceWebloggerProvider.java |  3 +-
 .../weblogger/business/WebloggerFactory.java       |  3 +-
 .../business/plugins/PluginManagerImpl.java        | 63 ++++++-----------
 .../weblogger/business/runnable/TaskRunner.java    |  3 +-
 .../business/runnable/ThreadManagerImpl.java       |  3 +-
 .../roller/weblogger/ui/core/RollerContext.java    | 14 ++--
 .../ui/core/plugins/UIPluginManagerImpl.java       | 32 +++------
 .../weblogger/ui/rendering/RendererManager.java    | 62 ++++++-----------
 .../ui/rendering/filters/RequestMappingFilter.java | 52 ++++----------
 .../weblogger/ui/rendering/model/ModelLoader.java  |  3 +-
 .../plugins/comments/CommentValidationManager.java | 23 ++-----
 .../servlets/CommentAuthenticatorServlet.java      |  3 +-
 .../ui/rendering/servlets/CommentServlet.java      |  3 +-
 .../apache/roller/weblogger/util/Reflection.java   | 79 ++++++++++++++++++++++
 .../roller/weblogger/util/cache/CacheManager.java  | 42 +++++-------
 15 files changed, 185 insertions(+), 203 deletions(-)

diff --git a/app/src/main/java/org/apache/roller/weblogger/business/GuiceWebloggerProvider.java b/app/src/main/java/org/apache/roller/weblogger/business/GuiceWebloggerProvider.java
index 021ccfb..f48f86a 100644
--- a/app/src/main/java/org/apache/roller/weblogger/business/GuiceWebloggerProvider.java
+++ b/app/src/main/java/org/apache/roller/weblogger/business/GuiceWebloggerProvider.java
@@ -23,6 +23,7 @@ import com.google.inject.Injector;
 import com.google.inject.Module;
 import java.util.Objects;
 import org.apache.roller.weblogger.config.WebloggerConfig;
+import org.apache.roller.weblogger.util.Reflection;
 
 
 /**
@@ -58,7 +59,7 @@ public class GuiceWebloggerProvider implements WebloggerProvider {
         Objects.requireNonNull(moduleClassname, "moduleClassname cannot be null");
         
         try {
-            Module module = (Module) Class.forName(moduleClassname).getDeclaredConstructor().newInstance();
+            Module module = (Module) Reflection.newInstance(moduleClassname);
             injector = Guice.createInjector(module);
         } catch (ThreadDeath t) {
             throw t;
diff --git a/app/src/main/java/org/apache/roller/weblogger/business/WebloggerFactory.java b/app/src/main/java/org/apache/roller/weblogger/business/WebloggerFactory.java
index 12303fe..6e1f4cb 100644
--- a/app/src/main/java/org/apache/roller/weblogger/business/WebloggerFactory.java
+++ b/app/src/main/java/org/apache/roller/weblogger/business/WebloggerFactory.java
@@ -22,6 +22,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.weblogger.business.startup.WebloggerStartup;
 import org.apache.roller.weblogger.config.WebloggerConfig;
+import org.apache.roller.weblogger.util.Reflection;
 
 
 /**
@@ -84,7 +85,7 @@ public final class WebloggerFactory {
         String providerClassname = WebloggerConfig.getProperty("weblogger.provider.class");
         if(providerClassname != null) {
             try {
-                defaultProvider = (WebloggerProvider) Class.forName(providerClassname).getDeclaredConstructor().newInstance();
+                defaultProvider = (WebloggerProvider) Reflection.newInstance(providerClassname);
             } catch (ReflectiveOperationException ex) {
                 throw new BootstrapException("Error instantiating default provider: " + providerClassname + "; exception message: " + ex.getMessage(), ex);
             }
diff --git a/app/src/main/java/org/apache/roller/weblogger/business/plugins/PluginManagerImpl.java b/app/src/main/java/org/apache/roller/weblogger/business/plugins/PluginManagerImpl.java
index 7f6dc2a..27c77e9 100644
--- a/app/src/main/java/org/apache/roller/weblogger/business/plugins/PluginManagerImpl.java
+++ b/app/src/main/java/org/apache/roller/weblogger/business/plugins/PluginManagerImpl.java
@@ -23,6 +23,7 @@ import org.apache.roller.weblogger.business.plugins.entry.WeblogEntryPlugin;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.weblogger.config.WebloggerConfig;
@@ -33,6 +34,7 @@ import org.apache.roller.weblogger.WebloggerException;
 import org.apache.roller.weblogger.business.plugins.comment.WeblogEntryCommentPlugin;
 import org.apache.roller.weblogger.pojos.WeblogEntryComment;
 import org.apache.roller.weblogger.util.HTMLSanitizer;
+import org.apache.roller.weblogger.util.Reflection;
 
 
 /**
@@ -43,7 +45,7 @@ public class PluginManagerImpl implements PluginManager {
     private static final Log log = LogFactory.getLog(PluginManagerImpl.class);
     
     // Plugin classes keyed by plugin name
-    static Map<String, Class<? extends WeblogEntryPlugin>> mPagePlugins = new LinkedHashMap<>();
+    private static final Map<String, Class<? extends WeblogEntryPlugin>> mPagePlugins = new LinkedHashMap<>();
     
     // Comment plugins
     private final List<WeblogEntryCommentPlugin> commentPlugins = new ArrayList<>();
@@ -78,7 +80,7 @@ public class PluginManagerImpl implements PluginManager {
         
         for (Class<? extends WeblogEntryPlugin> pluginClass : mPagePlugins.values()) {
             try {
-                WeblogEntryPlugin plugin = pluginClass.getDeclaredConstructor().newInstance();
+                WeblogEntryPlugin plugin = Reflection.newInstance(pluginClass);
                 plugin.init(website);
                 ret.put(plugin.getName(), plugin);
             } catch (ReflectiveOperationException | WebloggerException e) {
@@ -92,17 +94,14 @@ public class PluginManagerImpl implements PluginManager {
     public String applyWeblogEntryPlugins(Map<String, WeblogEntryPlugin> pagePlugins, WeblogEntry entry, String str) {
 
         String ret = str;
-        WeblogEntry copy = new WeblogEntry(entry);
-        List<String> entryPlugins = copy.getPluginsList();
+        List<String> plugins = entry.getPluginsList();
 
-        if (entryPlugins != null) {
-            for (String key : entryPlugins) {
-                WeblogEntryPlugin pagePlugin = pagePlugins.get(key);
-                if (pagePlugin != null) {
-                    ret = pagePlugin.render(entry, ret);
-                } else {
-                    log.error("ERROR: plugin not found: " + key);
-                }
+        for (String key : plugins) {
+            WeblogEntryPlugin pagePlugin = pagePlugins.get(key);
+            if (pagePlugin != null) {
+                ret = pagePlugin.render(entry, ret);
+            } else {
+                log.warn("plugin not found: " + key);
             }
         }
 
@@ -159,8 +158,7 @@ public class PluginManagerImpl implements PluginManager {
             log.debug(pluginStr);
         }
         if (pluginStr != null) {
-            String[] plugins = StringUtils.stripAll(
-                    StringUtils.split(pluginStr, ",") );
+            String[] plugins = StringUtils.stripAll(StringUtils.split(pluginStr, ","));
             for (String plugin : plugins) {
                 if (log.isDebugEnabled()) {
                     log.debug("try " + plugin);
@@ -168,10 +166,10 @@ public class PluginManagerImpl implements PluginManager {
                 try {
                     Class<?> clazz = Class.forName(plugin);
                     
-                    if (isPagePlugin(clazz)) {
+                    if (Reflection.implementsInterface(clazz, WeblogEntryPlugin.class)) {
                         @SuppressWarnings("unchecked")
                         Class<? extends WeblogEntryPlugin> pluginClass = (Class<? extends WeblogEntryPlugin>)clazz;
-                        WeblogEntryPlugin weblogEntryPlugin = pluginClass.getDeclaredConstructor().newInstance();
+                        WeblogEntryPlugin weblogEntryPlugin = Reflection.newInstance(pluginClass);
                         mPagePlugins.put(weblogEntryPlugin.getName(), pluginClass);
                     } else {
                         log.warn(clazz + " is not a PagePlugin");
@@ -189,35 +187,14 @@ public class PluginManagerImpl implements PluginManager {
      */
     private void loadCommentPlugins() {
         
-        log.debug("Initializing comment plugins");
-        
-        String pluginStr = WebloggerConfig.getProperty("comment.formatter.classnames");
-        if (pluginStr != null) {
-            String[] plugins = StringUtils.stripAll(StringUtils.split(pluginStr, ","));
-            for (int i=0; i < plugins.length; i++) {
-                log.debug("trying " + plugins[i]);
-                
-                try {
-                    WeblogEntryCommentPlugin plugin = (WeblogEntryCommentPlugin) Class.forName(plugins[i]).getDeclaredConstructor().newInstance();
-                    
-                    // make sure and maintain ordering
-                    commentPlugins.add(i, plugin);
-                    
-                    log.debug("Configured comment plugin: "+plugins[i]);
-                    
-                } catch (ReflectiveOperationException e) {
-                    log.error("unable to create " + plugins[i]);
-                }
-            }
+        try {
+            commentPlugins.addAll(Reflection.newInstancesFromProperty("comment.formatter.classnames"));
+        } catch (ReflectiveOperationException e) {
+            log.error("unable to create comment plugins", e);
         }
         
-    }
-    
-    private static boolean isPagePlugin(Class<?> clazz) {
-        for (Class<?> inter : clazz.getInterfaces())
-            if (inter.equals(WeblogEntryPlugin.class))
-                return true;
-        return false;
+        log.info("Configured comment plugins");
+        log.info(commentPlugins.stream().map(t -> t.getClass().toString()).collect(Collectors.joining(",", "[", "]")));
     }
     
     @Override
diff --git a/app/src/main/java/org/apache/roller/weblogger/business/runnable/TaskRunner.java b/app/src/main/java/org/apache/roller/weblogger/business/runnable/TaskRunner.java
index 8cd3494..27c614a 100644
--- a/app/src/main/java/org/apache/roller/weblogger/business/runnable/TaskRunner.java
+++ b/app/src/main/java/org/apache/roller/weblogger/business/runnable/TaskRunner.java
@@ -18,6 +18,7 @@
 package org.apache.roller.weblogger.business.runnable;
         
 import java.io.File;
+import org.apache.roller.weblogger.util.Reflection;
 import org.apache.roller.weblogger.util.StandaloneWebappClassLoader;
 
 /**
@@ -57,7 +58,7 @@ public class TaskRunner {
         Thread.currentThread().setContextClassLoader(cl);
 
         // Go!
-        Runnable task = (Runnable)Class.forName(taskClassName).getDeclaredConstructor().newInstance();
+        Runnable task = (Runnable) Reflection.newInstance(taskClassName);
         task.run();
     }
 }
diff --git a/app/src/main/java/org/apache/roller/weblogger/business/runnable/ThreadManagerImpl.java b/app/src/main/java/org/apache/roller/weblogger/business/runnable/ThreadManagerImpl.java
index c515bed..15ec908 100644
--- a/app/src/main/java/org/apache/roller/weblogger/business/runnable/ThreadManagerImpl.java
+++ b/app/src/main/java/org/apache/roller/weblogger/business/runnable/ThreadManagerImpl.java
@@ -34,6 +34,7 @@ import org.apache.roller.weblogger.WebloggerException;
 import org.apache.roller.weblogger.business.InitializationException;
 import org.apache.roller.weblogger.config.WebloggerConfig;
 import org.apache.roller.weblogger.pojos.TaskLock;
+import org.apache.roller.weblogger.util.Reflection;
 
 import static org.apache.roller.util.RollerConstants.GRACEFUL_SHUTDOWN_WAIT_IN_MILLISECONDS;
 import static org.apache.roller.util.RollerConstants.GRACEFUL_SHUTDOWN_WAIT_IN_SECONDS;
@@ -75,7 +76,7 @@ public abstract class ThreadManagerImpl implements ThreadManager {
                 LOG.info("Initializing task: " + taskName);
                 
                 try {
-                    RollerTask task = (RollerTask) Class.forName(taskClassName).getDeclaredConstructor().newInstance();
+                    RollerTask task = (RollerTask) Reflection.newInstance(taskClassName);
                     task.init(taskName);
                     
                     // make sure there is a tasklock record in the db
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java b/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java
index cc0f749..2979fcf 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java
@@ -45,6 +45,7 @@ import org.apache.roller.weblogger.business.startup.WebloggerStartup;
 import org.apache.roller.weblogger.ui.core.plugins.UIPluginManager;
 import org.apache.roller.weblogger.ui.core.plugins.UIPluginManagerImpl;
 import org.apache.roller.weblogger.ui.core.security.AutoProvision;
+import org.apache.roller.weblogger.util.Reflection;
 import org.apache.roller.weblogger.util.cache.CacheManager;
 import org.apache.velocity.runtime.RuntimeSingleton;
 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@@ -365,14 +366,11 @@ public class RollerContext extends ContextLoaderListener
             return null;
         }
 
-        Class<?>[] interfaces = clazz.getInterfaces();
-        for (Class<?> clazz2 : interfaces) {
-            if (clazz2.equals(AutoProvision.class)) {
-                try {
-                    return (AutoProvision) clazz.getDeclaredConstructor().newInstance();
-                } catch (ReflectiveOperationException e) {
-                    log.warn("ReflectiveOperationException while creating: " + clazzName, e);
-                }
+        if (Reflection.implementsInterface(clazz, AutoProvision.class)) {
+            try {
+                return (AutoProvision) Reflection.newInstance(clazz);
+            } catch (ReflectiveOperationException e) {
+                log.warn("ReflectiveOperationException while creating: " + clazzName, e);
             }
         }
         return null;
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/core/plugins/UIPluginManagerImpl.java b/app/src/main/java/org/apache/roller/weblogger/ui/core/plugins/UIPluginManagerImpl.java
index 51f96c3..07fd5e2 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/core/plugins/UIPluginManagerImpl.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/core/plugins/UIPluginManagerImpl.java
@@ -25,7 +25,7 @@ import java.util.Map;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.weblogger.config.WebloggerConfig;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.roller.weblogger.util.Reflection;
 
 
 /**
@@ -91,28 +91,14 @@ public final class UIPluginManagerImpl implements UIPluginManager {
         
         log.debug("Initializing entry editor plugins");
         
-        String editorStr = WebloggerConfig.getProperty("plugins.weblogEntryEditors");
-        if (editorStr != null) {
-            
-            String[] editorList = StringUtils.stripAll(StringUtils.split(editorStr, ","));
-            for (int i=0; i < editorList.length; i++) {
-                
-                log.debug("trying editor " + editorList[i]);
-                
-                try {
-                    WeblogEntryEditor editor = (WeblogEntryEditor) Class.forName(editorList[i])
-                            .getDeclaredConstructor().newInstance();
-                    
-                    // looks okay, add it to the map
-                    this.editors.put(editor.getId(), editor);
-                    
-                } catch(ClassCastException cce) {
-                    log.error("It appears that your editor does not implement "+
-                            "the WeblogEntryEditor interface", cce);
-                } catch(Exception e) {
-                    log.error("Unable to instantiate editor ["+editorList[i]+"]", e);
-                }
-            }
+        try {
+            Reflection.<WeblogEntryEditor>newInstancesFromProperty("plugins.weblogEntryEditors")
+                    .forEach(editor -> this.editors.put(editor.getId(), editor));
+        } catch(ClassCastException cce) {
+            log.error("It appears that your editor does not implement "+
+                    "the WeblogEntryEditor interface", cce);
+        } catch(Exception e) {
+            log.error("Unable to instantiate editors", e);
         }
         
         if(this.editors.isEmpty()) {
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/RendererManager.java b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/RendererManager.java
index 4a1defc..6769714 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/RendererManager.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/RendererManager.java
@@ -17,14 +17,15 @@
  */
 package org.apache.roller.weblogger.ui.rendering;
 
+import java.util.ArrayList;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.weblogger.config.WebloggerConfig;
 import org.apache.roller.weblogger.pojos.Template;
 
-import java.util.HashSet;
-import java.util.Set;
+import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.roller.weblogger.ui.rendering.mobile.MobileDeviceRepository;
+import org.apache.roller.weblogger.util.Reflection;
 
 /**
  * Returns Renderer for Template via configured RendererFactories.
@@ -37,48 +38,22 @@ import org.apache.roller.weblogger.ui.rendering.mobile.MobileDeviceRepository;
 public final class RendererManager {
 
     private static final Log log = LogFactory.getLog(RendererManager.class);
+    
     // a set of all renderer factories we are consulting
-    private static final Set<RendererFactory> rendererFactories = new HashSet<>();
+    private static final List<RendererFactory> rendererFactories = new ArrayList<>();
 
     static {
+        
         // lookup set of renderer factories we are going to use
-        String rollerFactories = WebloggerConfig.getProperty("rendering.rollerRendererFactories");
-        String userFactories = WebloggerConfig.getProperty("rendering.userRendererFactories");
-
-        // instantiate user defined renderer factory classes
-        if (userFactories != null && !userFactories.isBlank()) {
-
-            RendererFactory rendererFactory;
-            String[] uFactories = userFactories.split(",");
-            for (String uFactory :uFactories) {
-                try {
-                    rendererFactory = (RendererFactory) Class.forName(uFactory).getDeclaredConstructor().newInstance();
-                    rendererFactories.add(rendererFactory);
-                } catch (ClassCastException cce) {
-                    log.error("It appears that your factory does not implement "
-                            + "the RendererFactory interface", cce);
-                } catch (ReflectiveOperationException e) {
-                    log.error("Unable to instantiate renderer factory [" + uFactory + "]", e);
-                }
-            }
+        try {
+            rendererFactories.addAll(Reflection.newInstancesFromProperty("rendering.userRendererFactories"));
+        } catch (ReflectiveOperationException ex) {
+            log.error("Unable to create user rendering factories", ex);
         }
-
-        // instantiate roller standard renderer factory classes
-        if (rollerFactories != null && !rollerFactories.isBlank()) {
-
-            RendererFactory rendererFactory;
-            String[] rFactories = rollerFactories.split(",");
-            for (String rFactory : rFactories) {
-                try {
-                    rendererFactory = (RendererFactory) Class.forName(rFactory).getDeclaredConstructor().newInstance();
-                    rendererFactories.add(rendererFactory);
-                } catch (ClassCastException cce) {
-                    log.error("It appears that your factory does not implement "
-                            + "the RendererFactory interface", cce);
-                } catch (ReflectiveOperationException e) {
-                    log.error("Unable to instantiate renderer factory [" + rFactory + "]", e);
-                }
-            }
+        try {
+            rendererFactories.addAll(Reflection.newInstancesFromProperty("rendering.rollerRendererFactories"));
+        } catch (ReflectiveOperationException ex) {
+            log.error("Unable to create roller rendering factories", ex);
         }
 
         if (rendererFactories.isEmpty()) {
@@ -87,7 +62,9 @@ public final class RendererManager {
                     + "Rendering probably won't function as you expect.");
         }
 
-        log.info("Renderer Manager Initialized.");
+        log.info("Renderer Manager Initialized, "+ rendererFactories.size()+" factories configured.");
+        log.info(rendererFactories.stream().map(t -> t.getClass().toString()).collect(Collectors.joining(",", "[", "]")));
+        
     }
 
     // this class is non-instantiable
@@ -115,7 +92,6 @@ public final class RendererManager {
             }
         }
 
-        throw new RenderingException("No renderer found for template "
-                + template.getId() + "!");
+        throw new RenderingException("No renderer found for template " + template.getId() + "!");
     }
 }
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/filters/RequestMappingFilter.java b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/filters/RequestMappingFilter.java
index 46d828c..4c56fb9 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/filters/RequestMappingFilter.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/filters/RequestMappingFilter.java
@@ -21,6 +21,7 @@ package org.apache.roller.weblogger.ui.rendering.filters;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
@@ -31,8 +32,8 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.weblogger.config.WebloggerConfig;
 import org.apache.roller.weblogger.ui.rendering.RequestMapper;
+import org.apache.roller.weblogger.util.Reflection;
 
 /**
  * Provides generalized request mapping capabilities.
@@ -52,42 +53,16 @@ public class RequestMappingFilter implements Filter {
     @Override
     public void init(FilterConfig filterConfig) {
         
-        // lookup set of request mappers we are going to use
-        String rollerMappers = WebloggerConfig.getProperty("rendering.rollerRequestMappers");
-        String userMappers = WebloggerConfig.getProperty("rendering.userRequestMappers");
-        
-        // instantiate user defined request mapper classes
-        if(userMappers != null && !userMappers.isBlank()) {
-            RequestMapper requestMapper;
-            String[] uMappers = userMappers.split(",");
-            for (String uMapper : uMappers) {
-                try {
-                    requestMapper = (RequestMapper) Class.forName(uMapper).getDeclaredConstructor().newInstance();
-                    requestMappers.add(requestMapper);
-                } catch(ClassCastException cce) {
-                    log.error("It appears that your mapper does not implement "+
-                            "the RequestMapper interface", cce);
-                } catch(ReflectiveOperationException e) {
-                    log.error("Unable to instantiate request mapper ["+uMapper+"]", e);
-                }
-            }
+        // instantiate user defined and standard roller request mapper classes
+        try {
+            requestMappers.addAll(Reflection.newInstancesFromProperty("rendering.userRequestMappers"));
+        } catch (ReflectiveOperationException ex) {
+            log.error("Unable to load user request mappers", ex);
         }
-        
-        // instantiate roller standard request mapper classes
-        if(rollerMappers != null && !rollerMappers.isBlank()) {
-            RequestMapper requestMapper;
-            String[] rMappers = rollerMappers.split(",");
-            for (String rMapper : rMappers) {
-                try {
-                    requestMapper = (RequestMapper) Class.forName(rMapper).getDeclaredConstructor().newInstance();
-                    requestMappers.add(requestMapper);
-                } catch(ClassCastException cce) {
-                    log.error("It appears that your mapper does not implement "+
-                            "the RequestMapper interface", cce);
-                } catch(ReflectiveOperationException e) {
-                    log.error("Unable to instantiate request mapper ["+rMapper+"]", e);
-                }
-            }
+        try {
+            requestMappers.addAll(Reflection.newInstancesFromProperty("rendering.rollerRequestMappers"));
+        } catch (ReflectiveOperationException ex) {
+            log.error("Unable to load roller request mappers", ex);
         }
         
         if(requestMappers.isEmpty()) {
@@ -96,8 +71,9 @@ public class RequestMappingFilter implements Filter {
                     "Weblog urls probably won't function as you expect.");
         }
         
-        log.info("Request mapping filter initialized, "+requestMappers.size()+
-                " mappers configured.");
+        log.info("Request mapping filter initialized, "+requestMappers.size()+" mappers configured.");
+        log.info(requestMappers.stream().map(t -> t.getClass().toString()).collect(Collectors.joining(",", "[", "]")));
+        
     }
     
     
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/model/ModelLoader.java b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/model/ModelLoader.java
index 1a2e9cf..01404fb 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/model/ModelLoader.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/model/ModelLoader.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.weblogger.WebloggerException;
+import org.apache.roller.weblogger.util.Reflection;
 import org.apache.roller.weblogger.util.Utilities;
 
 
@@ -45,7 +46,7 @@ public class ModelLoader {
         if (models != null) {
             for (String model : models) {
                 try {
-                    Model pageModel = (Model) Class.forName(model).getDeclaredConstructor().newInstance();
+                    Model pageModel = (Model) Reflection.newInstance(model);
                     pageModel.init(initData);
                     modelMap.put(pageModel.getModelName(), pageModel);
                 } catch (WebloggerException re) {
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/CommentValidationManager.java b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/CommentValidationManager.java
index 162d615..f09580b 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/CommentValidationManager.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/CommentValidationManager.java
@@ -20,13 +20,13 @@ package org.apache.roller.weblogger.ui.rendering.plugins.comments;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.util.RollerConstants;
-import org.apache.roller.weblogger.config.WebloggerConfig;
 import org.apache.roller.weblogger.pojos.WeblogEntryComment;
+import org.apache.roller.weblogger.util.Reflection;
 import org.apache.roller.weblogger.util.RollerMessages;
-import org.apache.roller.weblogger.util.Utilities;
 
 /**
  * Responsible for loading validators and using them to validate comments.
@@ -40,22 +40,13 @@ public class CommentValidationManager {
         
         // instantiate the validators that are configured
         try {
-            String vals = WebloggerConfig.getProperty("comment.validator.classnames");
-            String[] valsarray = Utilities.stringToStringArray(vals, ",");
-            for (String arrayVal : valsarray) {
-                try {
-                    CommentValidator val = (CommentValidator) Class.forName(arrayVal).getDeclaredConstructor().newInstance();
-                    validators.add(val);
-                    log.info("Configured CommentValidator: " + val.getName() + " / " + val.getClass().getName());
-                } catch (ReflectiveOperationException ex) {
-                    log.warn("Error creating comment validator: " + arrayVal, ex);
-                }
-            }
-                        
-        } catch (Exception e) {
-            log.error("Error instantiating comment validators");
+            validators.addAll(Reflection.newInstancesFromProperty("comment.validator.classnames"));
+        } catch (ReflectiveOperationException ex) {
+            log.error("Error instantiating comment validators", ex);
         }
+        
         log.info("Configured " + validators.size() + " CommentValidators");
+        log.info(validators.stream().map(t -> t.getClass().toString()).collect(Collectors.joining(",", "[", "]")));
     }
     
     /**
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentAuthenticatorServlet.java b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentAuthenticatorServlet.java
index 860fc93..b808050 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentAuthenticatorServlet.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentAuthenticatorServlet.java
@@ -30,6 +30,7 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.roller.weblogger.config.WebloggerConfig;
 import org.apache.roller.weblogger.ui.rendering.plugins.comments.CommentAuthenticator;
 import org.apache.roller.weblogger.ui.rendering.plugins.comments.DefaultCommentAuthenticator;
+import org.apache.roller.weblogger.util.Reflection;
 
 
 /**
@@ -77,7 +78,7 @@ public class CommentAuthenticatorServlet extends HttpServlet {
         // lookup the authenticator we are going to use and instantiate it
         try {
             String name = WebloggerConfig.getProperty("comment.authenticator.classname");
-            this.authenticator = (CommentAuthenticator) Class.forName(name).getDeclaredConstructor().newInstance();
+            this.authenticator = (CommentAuthenticator) Reflection.newInstance(name);
             
         } catch(ReflectiveOperationException e) {
             mLogger.error(e);
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java
index fbb6263..ed27db1 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java
@@ -53,6 +53,7 @@ import org.apache.roller.weblogger.util.GenericThrottle;
 import org.apache.roller.weblogger.util.IPBanList;
 import org.apache.roller.weblogger.util.MailUtil;
 import org.apache.roller.weblogger.util.I18nMessages;
+import org.apache.roller.weblogger.util.Reflection;
 import org.apache.roller.weblogger.util.RollerMessages;
 import org.apache.roller.weblogger.util.RollerMessages.RollerMessage;
 import org.apache.roller.weblogger.util.URLUtilities;
@@ -92,7 +93,7 @@ public class CommentServlet extends HttpServlet {
         // lookup the authenticator we are going to use and instantiate it
         try {
             String name = WebloggerConfig.getProperty("comment.authenticator.classname");
-            this.authenticator = (CommentAuthenticator) Class.forName(name).getDeclaredConstructor().newInstance();
+            this.authenticator = (CommentAuthenticator) Reflection.newInstance(name);
         } catch (ReflectiveOperationException e) {
             log.error(e);
         } finally {
diff --git a/app/src/main/java/org/apache/roller/weblogger/util/Reflection.java b/app/src/main/java/org/apache/roller/weblogger/util/Reflection.java
new file mode 100644
index 0000000..92b1364
--- /dev/null
+++ b/app/src/main/java/org/apache/roller/weblogger/util/Reflection.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.util;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.roller.weblogger.config.WebloggerConfig;
+
+/**
+ * Utility methods for common reflection tasks.
+ */
+public final class Reflection {
+
+    private Reflection() {}
+    
+        
+    public static Object newInstance(String className) throws ReflectiveOperationException {
+        return newInstance(Class.forName(className));
+    }
+    
+    public static <T> T newInstance(Class<T> clazz) throws ReflectiveOperationException {
+        Constructor<T> constructor = clazz.getDeclaredConstructor();
+        constructor.setAccessible(true);
+        return constructor.newInstance();
+    }
+        
+    public static <T> List<T> newInstances(String[] classList) throws ReflectiveOperationException {
+        
+        List<T> instances = new ArrayList<>();
+            
+        for (String klass : classList) {
+            @SuppressWarnings("unchecked")
+            T instance = (T) Reflection.newInstance(klass);  // throws CCE if instance dos not match T
+            instances.add(instance);
+        }
+        
+        return instances;
+    }
+    
+    public static <T> List<T> newInstancesFromProperty(String property) throws ReflectiveOperationException {
+        
+        String classList = WebloggerConfig.getProperty(property);
+        
+        if (classList != null && !classList.isBlank()) {
+            return newInstances(classList.split(","));
+        }
+        
+        return Collections.emptyList();
+    }
+    
+    /**
+     * Returns true if the given class directly implements the given interface.
+     */
+    public static boolean implementsInterface(Class<?> clazz, Class<?> interfaze) {
+        for (Class<?> inter : clazz.getInterfaces())
+            if (inter.equals(interfaze))
+                return true;
+        return false;
+    }
+    
+}
diff --git a/app/src/main/java/org/apache/roller/weblogger/util/cache/CacheManager.java b/app/src/main/java/org/apache/roller/weblogger/util/cache/CacheManager.java
index 9b44a30..3b6c0a7 100644
--- a/app/src/main/java/org/apache/roller/weblogger/util/cache/CacheManager.java
+++ b/app/src/main/java/org/apache/roller/weblogger/util/cache/CacheManager.java
@@ -33,6 +33,7 @@ import org.apache.roller.weblogger.pojos.WeblogCategory;
 import org.apache.roller.weblogger.pojos.WeblogEntry;
 import org.apache.roller.weblogger.pojos.WeblogTemplate;
 import org.apache.roller.weblogger.pojos.Weblog;
+import org.apache.roller.weblogger.util.Reflection;
 
 
 /**
@@ -50,19 +51,19 @@ import org.apache.roller.weblogger.pojos.Weblog;
  */
 public final class CacheManager {
     
-    private final static Log log = LogFactory.getLog(CacheManager.class);
+    private static final Log log = LogFactory.getLog(CacheManager.class);
     
     private static final String DEFAULT_FACTORY = 
             "org.apache.roller.weblogger.util.cache.ExpiringLRUCacheFactoryImpl";
     
     // a reference to the cache factory in use
-    private static CacheFactory cacheFactory = null;
+    private static final CacheFactory cacheFactory;
     
     // a set of all registered cache handlers
-    private static Set<CacheHandler> cacheHandlers = new HashSet<>();
+    private static final Set<CacheHandler> cacheHandlers = new HashSet<>();
     
     // a map of all registered caches
-    private static Map<String, Cache> caches = new HashMap<>();
+    private static final Map<String, Cache> caches = new HashMap<>();
     
     
     static {
@@ -70,8 +71,9 @@ public final class CacheManager {
         String classname = WebloggerConfig.getProperty("cache.defaultFactory");
         
         // use reflection to instantiate our factory class
+        CacheFactory factory = null;
         try {
-            cacheFactory = (CacheFactory) Class.forName(classname).getDeclaredConstructor().newInstance();
+            factory = (CacheFactory) Reflection.newInstance(classname);
         } catch(ClassCastException cce) {
             log.error("It appears that your factory does not implement "+
                     "the CacheFactory interface",cce);
@@ -80,39 +82,29 @@ public final class CacheManager {
                     " falling back on default", e);
         }
         
-        if(cacheFactory == null) {
+        if(factory == null) {
             try {
                 // hmm ... failed to load the specified cache factory
                 // lets try our default
-                cacheFactory = (CacheFactory) Class.forName(DEFAULT_FACTORY).getDeclaredConstructor().newInstance();
+                factory = (CacheFactory) Reflection.newInstance(DEFAULT_FACTORY);
             } catch(ReflectiveOperationException e) {
                 log.fatal("Failed to instantiate a cache factory", e);
                 throw new RuntimeException(e);
             }
         }
+        cacheFactory = factory;
         
         log.info("Cache Manager Initialized.");
         log.info("Cache Factory = "+cacheFactory.getClass().getName());
         
         
         // add custom handlers
-        String customHandlers = WebloggerConfig.getProperty("cache.customHandlers");
-        if(customHandlers != null && !customHandlers.isBlank()) {
-            
-            String[] cHandlers = customHandlers.split(",");
-            for (String cHandler : cHandlers) {
-                // use reflection to instantiate the handler class
-                try {
-                    CacheHandler customHandler = (CacheHandler) Class.forName(cHandler).getDeclaredConstructor().newInstance();
-                    
-                    cacheHandlers.add(customHandler);
-                } catch(ClassCastException cce) {
-                    log.error("It appears that your handler does not implement "+
-                            "the CacheHandler interface",cce);
-                } catch(ReflectiveOperationException e) {
-                    log.error("Unable to instantiate cache handler ["+cHandler+"]", e);
-                }
-            }
+        try {
+            cacheHandlers.addAll(Reflection.newInstancesFromProperty("cache.customHandlers"));
+        } catch(ClassCastException cce) {
+            log.error("It appears that at least one custom handler does not implement the CacheHandler interface", cce);
+        } catch(ReflectiveOperationException e) {
+            log.error("Unable to instantiate custom cache handlers", e);
         }
     }
     
@@ -151,7 +143,7 @@ public final class CacheManager {
             
             try {
                 // use reflection to instantiate the factory class
-                CacheFactory factory = (CacheFactory) Class.forName(classname).getDeclaredConstructor().newInstance();
+                CacheFactory factory = (CacheFactory) Reflection.newInstance(classname);
                 
                 // now ask for a new cache
                 cache = factory.constructCache(properties);