You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2012/03/28 14:48:41 UTC

svn commit: r1306294 - in /incubator/syncope/trunk/core/src/main/java/org/syncope/core: init/ rest/controller/ rest/data/

Author: ilgrosso
Date: Wed Mar 28 12:48:40 2012
New Revision: 1306294

URL: http://svn.apache.org/viewvc?rev=1306294&view=rev
Log:
[SYNCOPE-50] A separated ImplementationClassNamesLoader class, invoked on webapp init, has been provided: this will make things easier in WAR overlays

Added:
    incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/ImplementationClassNamesLoader.java   (with props)
Modified:
    incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/SpringContextInitializer.java
    incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/ConfigurationController.java
    incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/ReportController.java
    incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/TaskController.java
    incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/data/ReportDataBinder.java

Added: incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/ImplementationClassNamesLoader.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/ImplementationClassNamesLoader.java?rev=1306294&view=auto
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/ImplementationClassNamesLoader.java (added)
+++ incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/ImplementationClassNamesLoader.java Wed Mar 28 12:48:40 2012
@@ -0,0 +1,123 @@
+/*
+ * 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.syncope.core.init;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.quartz.Job;
+import org.quartz.StatefulJob;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.ResourcePatternResolver;
+import org.springframework.core.type.ClassMetadata;
+import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ClassUtils;
+import org.syncope.core.persistence.validation.attrvalue.Validator;
+import org.syncope.core.report.Reportlet;
+import org.syncope.core.scheduling.NotificationJob;
+import org.syncope.core.scheduling.ReportJob;
+import org.syncope.core.scheduling.SyncJob;
+import org.syncope.core.scheduling.SyncJobActions;
+
+/**
+ * Cache class names for all implementations of Syncope interfaces found in classpath, for later usage.
+ */
+@Component
+public class ImplementationClassNamesLoader {
+
+    public enum Type {
+
+        REPORTLET,
+        JOB,
+        JOB_ACTIONS,
+        VALIDATOR
+
+    }
+
+    /**
+     * Logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(ImplementationClassNamesLoader.class);
+
+    @Autowired
+    private ResourcePatternResolver resResolver;
+
+    private Map<Type, Set<String>> classNames;
+
+    public void load() {
+        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
+
+        classNames = new EnumMap<Type, Set<String>>(Type.class);
+        for (Type type : Type.values()) {
+            classNames.put(type, new HashSet<String>());
+        }
+
+        try {
+            for (Resource resource : resResolver.getResources("classpath*:**/*.class")) {
+                ClassMetadata metadata = factory.getMetadataReader(resource).getClassMetadata();
+
+                try {
+                    Class clazz = ClassUtils.forName(metadata.getClassName(), ClassUtils.getDefaultClassLoader());
+                    Set<Class> interfaces = ClassUtils.getAllInterfacesForClassAsSet(clazz);
+
+                    if (interfaces.contains(Reportlet.class) && !metadata.isAbstract()) {
+                        classNames.get(Type.REPORTLET).add(clazz.getName());
+                    }
+
+                    if ((interfaces.contains(Job.class) || interfaces.contains(StatefulJob.class))
+                            && !metadata.isAbstract() && !SyncJob.class.getName().equals(metadata.getClassName())
+                            && !ReportJob.class.getName().equals(metadata.getClassName())
+                            && !NotificationJob.class.getName().equals(metadata.getClassName())) {
+
+                        classNames.get(Type.JOB).add(metadata.getClassName());
+                    }
+
+                    if (interfaces.contains(SyncJobActions.class) && !metadata.isAbstract()) {
+                        classNames.get(Type.JOB_ACTIONS).add(metadata.getClassName());
+                    }
+
+                    if (interfaces.contains(Validator.class) && !metadata.isAbstract()) {
+                        classNames.get(Type.VALIDATOR).add(metadata.getClassName());
+                    }
+                } catch (ClassNotFoundException e) {
+                    LOG.warn("Could not load class {}", metadata.getClassName());
+                } catch (LinkageError e) {
+                    LOG.warn("Could not link class {}", metadata.getClassName());
+                }
+            }
+        } catch (IOException e) {
+            LOG.error("While searching for class implementing {}", Reportlet.class.getName(), e);
+        }
+
+        classNames = Collections.unmodifiableMap(classNames);
+
+        LOG.debug("Implementation classes found: {}", classNames);
+    }
+
+    public Set<String> getClassNames(final Type type) {
+        return classNames.get(type);
+    }
+}

Propchange: incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/ImplementationClassNamesLoader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/ImplementationClassNamesLoader.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/ImplementationClassNamesLoader.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/SpringContextInitializer.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/SpringContextInitializer.java?rev=1306294&r1=1306293&r2=1306294&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/SpringContextInitializer.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/syncope/core/init/SpringContextInitializer.java Wed Mar 28 12:48:40 2012
@@ -48,6 +48,9 @@ public class SpringContextInitializer im
     @Autowired
     private LoggerLoader loggerLoader;
 
+    @Autowired
+    private ImplementationClassNamesLoader classNamesLoader;
+
     @Override
     public void setServletContext(final ServletContext servletContext) {
     }
@@ -64,5 +67,6 @@ public class SpringContextInitializer im
         jobInstanceLoader.load();
         activitiWorkflowLoader.load();
         loggerLoader.load();
+        classNamesLoader.load();
     }
 }

Modified: incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/ConfigurationController.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/ConfigurationController.java?rev=1306294&r1=1306293&r2=1306294&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/ConfigurationController.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/ConfigurationController.java Wed Mar 28 12:48:40 2012
@@ -28,13 +28,10 @@ import javax.servlet.http.HttpServletRes
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.Resource;
 import org.springframework.core.io.support.ResourcePatternResolver;
-import org.springframework.core.type.ClassMetadata;
-import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
 import org.springframework.http.MediaType;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.ClassUtils;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -42,6 +39,7 @@ import org.springframework.web.bind.anno
 import org.springframework.web.servlet.ModelAndView;
 import org.syncope.client.to.ConfigurationTO;
 import org.syncope.core.audit.AuditManager;
+import org.syncope.core.init.ImplementationClassNamesLoader;
 import org.syncope.core.persistence.beans.SyncopeConf;
 import org.syncope.core.persistence.dao.ConfDAO;
 import org.syncope.core.persistence.dao.MissingConfKeyException;
@@ -69,12 +67,15 @@ public class ConfigurationController ext
     private ImportExport importExport;
 
     @Autowired
+    private ImplementationClassNamesLoader classNamesLoader;
+
+    @Autowired
     private ResourcePatternResolver resResolver;
 
     @PreAuthorize("hasRole('CONFIGURATION_CREATE')")
     @RequestMapping(method = RequestMethod.POST, value = "/create")
-    public ConfigurationTO create(final HttpServletResponse response, @RequestBody final ConfigurationTO configurationTO) {
-
+    public ConfigurationTO create(final HttpServletResponse response,
+            @RequestBody final ConfigurationTO configurationTO) {
         LOG.debug("Configuration create called with parameters {}", configurationTO);
 
         SyncopeConf conf = configurationDataBinder.createSyncopeConfiguration(configurationTO);
@@ -157,29 +158,7 @@ public class ConfigurationController ext
     @PreAuthorize("hasRole('CONFIGURATION_LIST')")
     @RequestMapping(method = RequestMethod.GET, value = "/validators")
     public ModelAndView getValidators() {
-        CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
-
-        Set<String> validators = new HashSet<String>();
-        try {
-            for (Resource resource : resResolver
-                    .getResources("classpath:org/syncope/core/persistence/validation/attrvalue/*.class")) {
-
-                ClassMetadata metadata = cachingMetadataReaderFactory.getMetadataReader(resource).getClassMetadata();
-
-                try {
-                    Set<Class> interfaces = ClassUtils.getAllInterfacesForClassAsSet(ClassUtils.forName(metadata
-                            .getClassName(), ClassUtils.getDefaultClassLoader()));
-
-                    if (interfaces.contains(Validator.class) && !metadata.isAbstract()) {
-                        validators.add(metadata.getClassName());
-                    }
-                } catch (ClassNotFoundException e) {
-                    LOG.error("Could not load class {}", metadata.getClassName(), e);
-                }
-            }
-        } catch (IOException e) {
-            LOG.error("While searching for class implementing {}", Validator.class.getName(), e);
-        }
+        Set<String> validators = classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.VALIDATOR);
 
         auditManager.audit(Category.configuration, ConfigurationSubCategory.getValidators, Result.success,
                 "Successfully listed all validators: " + validators.size());
@@ -198,11 +177,11 @@ public class ConfigurationController ext
 
                 String template = resource.getURL().toExternalForm();
                 if (template.endsWith(".html.vm")) {
-                    htmlTemplates.add(template.substring(template.indexOf("mailTemplates/") + 14, template
-                            .indexOf(".html.vm")));
+                    htmlTemplates.add(
+                            template.substring(template.indexOf("mailTemplates/") + 14, template.indexOf(".html.vm")));
                 } else if (template.endsWith(".txt.vm")) {
-                    textTemplates.add(template.substring(template.indexOf("mailTemplates/") + 14, template
-                            .indexOf(".txt.vm")));
+                    textTemplates.add(
+                            template.substring(template.indexOf("mailTemplates/") + 14, template.indexOf(".txt.vm")));
                 } else {
                     LOG.warn("Unexpected template found: {}, ignoring...", template);
                 }

Modified: incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/ReportController.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/ReportController.java?rev=1306294&r1=1306293&r2=1306294&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/ReportController.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/ReportController.java Wed Mar 28 12:48:40 2012
@@ -41,7 +41,6 @@ import org.apache.xmlgraphics.util.MimeC
 import org.quartz.JobDataMap;
 import org.quartz.Scheduler;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.io.support.ResourcePatternResolver;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@@ -96,9 +95,6 @@ public class ReportController extends Ab
     @Autowired
     private ReportDataBinder binder;
 
-    @Autowired
-    private ResourcePatternResolver resResolver;
-
     @PreAuthorize("hasRole('REPORT_CREATE')")
     @RequestMapping(method = RequestMethod.POST, value = "/create")
     public ReportTO create(final HttpServletResponse response, @RequestBody final ReportTO reportTO) {

Modified: incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/TaskController.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/TaskController.java?rev=1306294&r1=1306293&r2=1306294&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/TaskController.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/controller/TaskController.java Wed Mar 28 12:48:40 2012
@@ -18,28 +18,19 @@
  */
 package org.syncope.core.rest.controller;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import javassist.NotFoundException;
 import javax.servlet.http.HttpServletResponse;
-import org.quartz.Job;
 import org.quartz.JobDataMap;
 import org.quartz.Scheduler;
-import org.quartz.StatefulJob;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.ResourcePatternResolver;
-import org.springframework.core.type.ClassMetadata;
-import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
 import org.springframework.http.HttpStatus;
 import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
-import org.springframework.util.ClassUtils;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -53,6 +44,7 @@ import org.syncope.client.to.TaskTO;
 import org.syncope.client.validation.SyncopeClientCompositeErrorException;
 import org.syncope.client.validation.SyncopeClientException;
 import org.syncope.core.audit.AuditManager;
+import org.syncope.core.init.ImplementationClassNamesLoader;
 import org.syncope.core.init.JobInstanceLoader;
 import org.syncope.core.notification.NotificationManager;
 import org.syncope.core.persistence.beans.NotificationTask;
@@ -65,10 +57,6 @@ import org.syncope.core.persistence.dao.
 import org.syncope.core.propagation.PropagationManager;
 import org.syncope.core.rest.data.TaskDataBinder;
 import org.syncope.core.scheduling.AbstractTaskJob;
-import org.syncope.core.scheduling.NotificationJob;
-import org.syncope.core.scheduling.ReportJob;
-import org.syncope.core.scheduling.SyncJob;
-import org.syncope.core.scheduling.SyncJobActions;
 import org.syncope.core.util.TaskUtil;
 import org.syncope.types.AuditElements.Category;
 import org.syncope.types.AuditElements.Result;
@@ -106,7 +94,7 @@ public class TaskController extends Abst
     private SchedulerFactoryBean scheduler;
 
     @Autowired
-    private ResourcePatternResolver resResolver;
+    private ImplementationClassNamesLoader classNamesLoader;
 
     @PreAuthorize("hasRole('TASK_CREATE')")
     @RequestMapping(method = RequestMethod.POST, value = "/create/sync")
@@ -252,32 +240,7 @@ public class TaskController extends Abst
     @PreAuthorize("hasRole('TASK_LIST')")
     @RequestMapping(method = RequestMethod.GET, value = "/jobClasses")
     public ModelAndView getJobClasses() {
-        CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
-
-        Set<String> jobClasses = new HashSet<String>();
-        try {
-            for (Resource resource : resResolver.getResources("classpath*:**/*.class")) {
-
-                ClassMetadata metadata = cachingMetadataReaderFactory.getMetadataReader(resource).getClassMetadata();
-
-                try {
-                    Set<Class> interfaces = ClassUtils.getAllInterfacesForClassAsSet(ClassUtils.forName(metadata.
-                            getClassName(), ClassUtils.getDefaultClassLoader()));
-
-                    if ((interfaces.contains(Job.class) || interfaces.contains(StatefulJob.class))
-                            && !metadata.isAbstract() && !SyncJob.class.getName().equals(metadata.getClassName())
-                            && !ReportJob.class.getName().equals(metadata.getClassName())
-                            && !NotificationJob.class.getName().equals(metadata.getClassName())) {
-
-                        jobClasses.add(metadata.getClassName());
-                    }
-                } catch (ClassNotFoundException e) {
-                    LOG.error("Could not load class {}", metadata.getClassName(), e);
-                }
-            }
-        } catch (IOException e) {
-            LOG.error("While searching for class implementing {}", Job.class.getName(), e);
-        }
+        Set<String> jobClasses = classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.JOB);
 
         auditManager.audit(Category.task, TaskSubCategory.getJobClasses, Result.success,
                 "Successfully listed all Job classes: " + jobClasses.size());
@@ -288,27 +251,7 @@ public class TaskController extends Abst
     @PreAuthorize("hasRole('TASK_LIST')")
     @RequestMapping(method = RequestMethod.GET, value = "/jobActionsClasses")
     public ModelAndView getJobActionClasses() {
-        CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
-
-        Set<String> jobActionsClasses = new HashSet<String>();
-        try {
-            for (Resource resource : resResolver.getResources("classpath*:**/*.class")) {
-                ClassMetadata metadata = cachingMetadataReaderFactory.getMetadataReader(resource).getClassMetadata();
-
-                try {
-                    Set<Class> interfaces = ClassUtils.getAllInterfacesForClassAsSet(ClassUtils.forName(metadata.
-                            getClassName(), ClassUtils.getDefaultClassLoader()));
-
-                    if (interfaces.contains(SyncJobActions.class) && !metadata.isAbstract()) {
-                        jobActionsClasses.add(metadata.getClassName());
-                    }
-                } catch (ClassNotFoundException e) {
-                    LOG.error("Could not load class {}", metadata.getClassName(), e);
-                }
-            }
-        } catch (IOException e) {
-            LOG.error("While searching for class implementing {}", SyncJobActions.class.getName(), e);
-        }
+        Set<String> jobActionsClasses = classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.JOB_ACTIONS);
 
         auditManager.audit(Category.task, TaskSubCategory.getJobActionClasses, Result.success,
                 "Successfully listed all SyncJobActions classes: " + jobActionsClasses.size());

Modified: incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/data/ReportDataBinder.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/data/ReportDataBinder.java?rev=1306294&r1=1306293&r2=1306294&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/data/ReportDataBinder.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/data/ReportDataBinder.java Wed Mar 28 12:48:40 2012
@@ -18,7 +18,6 @@
  */
 package org.syncope.core.rest.data;
 
-import java.io.IOException;
 import java.util.HashSet;
 import java.util.Set;
 import org.quartz.Scheduler;
@@ -28,16 +27,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.ResourcePatternResolver;
-import org.springframework.core.type.ClassMetadata;
-import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
 import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 import org.springframework.stereotype.Component;
 import org.springframework.util.ClassUtils;
 import org.syncope.client.report.ReportletConf;
 import org.syncope.client.to.ReportExecTO;
 import org.syncope.client.to.ReportTO;
+import org.syncope.core.init.ImplementationClassNamesLoader;
 import org.syncope.core.init.JobInstanceLoader;
 import org.syncope.core.persistence.beans.Report;
 import org.syncope.core.persistence.beans.ReportExec;
@@ -53,9 +49,9 @@ public class ReportDataBinder {
      */
     private static final Logger LOG = LoggerFactory.getLogger(ReportDataBinder.class);
 
-    private static final String[] IGNORE_REPORT_PROPERTIES = { "id", "reportlets", "executions", "latestExecStatus" };
+    private static final String[] IGNORE_REPORT_PROPERTIES = {"id", "reportlets", "executions", "latestExecStatus"};
 
-    private static final String[] IGNORE_REPORT_EXECUTION_PROPERTIES = { "id", "report", "execResult" };
+    private static final String[] IGNORE_REPORT_EXECUTION_PROPERTIES = {"id", "report", "execResult"};
 
     @Autowired
     private ReportExecDAO reportExecDAO;
@@ -64,31 +60,21 @@ public class ReportDataBinder {
     private SchedulerFactoryBean scheduler;
 
     @Autowired
-    private ResourcePatternResolver resResolver;
+    private ImplementationClassNamesLoader classNamesLoader;
 
     public Set<Class<Reportlet>> getAllReportletClasses() {
-        CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
-
         Set<Class<Reportlet>> reportletClasses = new HashSet<Class<Reportlet>>();
-        try {
-            for (Resource resource : resResolver.getResources("classpath*:**/*.class")) {
-                ClassMetadata metadata = cachingMetadataReaderFactory.getMetadataReader(resource).getClassMetadata();
 
-                try {
-                    Class reportletClass = ClassUtils.forName(metadata.getClassName(), ClassUtils
-                            .getDefaultClassLoader());
-                    Set<Class> interfaces = ClassUtils.getAllInterfacesForClassAsSet(reportletClass);
-                    if (interfaces.contains(Reportlet.class) && !metadata.isAbstract()) {
-                        reportletClasses.add(reportletClass);
-                    }
-                } catch (ClassNotFoundException e) {
-                    LOG.error("Could not load class {}", metadata.getClassName(), e);
-                }
+        for (String className : classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.REPORTLET)) {
+            try {
+                Class reportletClass = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
+                reportletClasses.add(reportletClass);
+            } catch (ClassNotFoundException e) {
+                LOG.warn("Could not load class {}", className);
+            } catch (LinkageError e) {
+                LOG.warn("Could not link class {}", className);
             }
-        } catch (IOException e) {
-            LOG.error("While searching for class implementing {}", Reportlet.class.getName(), e);
         }
-
         return reportletClasses;
     }