package at.gv.egovernment.moa.id.moduls.moduleregistration; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.ServiceLoader; import javax.annotation.PostConstruct; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.core.io.Resource; import com.datentechnik.process_engine.ProcessDefinitionParserException; import com.datentechnik.process_engine.ProcessEngine; import com.datentechnik.process_engine.api.ExecutionContext; /** * This class handles registering modules. The modules are detected either with * the ServiceLoader mechanism or via Spring. All detected modules are ranked * according to their priority. */ public class ModuleRegistration { private static ModuleRegistration instance = new ModuleRegistration(); private List orderedModules = new ArrayList<>(); @Autowired private ApplicationContext ctx; @Autowired ProcessEngine processEngine; private Logger log = LoggerFactory.getLogger(getClass()); public static ModuleRegistration getInstance() { return instance; } private ModuleRegistration() { } @PostConstruct private void init() { // load modules via the ServiceLoader initServiceLoaderModules(); // load modules via Spring initSpringModules(); // order modules according to their priority orderModules(); } /** * Discovers modules which use the ServiceLoader mechanism. */ private void initServiceLoaderModules() { log.debug("Discovering modules which use the ServiceLoader mechanism."); ServiceLoader loader = ServiceLoader.load(AuthModule.class); Iterator modules = loader.iterator(); while (modules.hasNext()) { AuthModule module = modules.next(); registerResourceUris(module); orderedModules.add(module); } } /** * Discovers modules which use Spring. */ private void initSpringModules() { log.debug("Discovering Spring modules."); Map modules = ctx.getBeansOfType(AuthModule.class); for (AuthModule module : modules.values()) { registerResourceUris(module); orderedModules.add(module); } } /** * Registers the resource uris for the module. * * @param module * the module. */ private void registerResourceUris(AuthModule module) { for (String uri : module.getProcessDefinitions()) { Resource resource = ctx.getResource(uri); if (resource.exists()) { log.debug("Registering process definition resource uri: '{}'.", resource); try (InputStream processDefinitionInputStream = resource.getInputStream()) { processEngine.registerProcessDefinition(processDefinitionInputStream); } catch (IOException e) { log.info("Resource uri: '{}' could NOT be read.", resource); } catch (ProcessDefinitionParserException e) { log.warn("Error while parsing process definition in '{}'", resource); } } else { log.info("Resource uri: '{}' does NOT exist.", resource); } } } /** * Order the modules in descending order according to their priority. */ private void orderModules() { Collections.sort(orderedModules, new Comparator() { @Override public int compare(AuthModule thisAuthModule, AuthModule otherAuthModule) { int thisOrder = thisAuthModule.getPriority(); int otherOrder = otherAuthModule.getPriority(); return (thisOrder < otherOrder ? -1 : (thisOrder == otherOrder ? 0 : 1)); } }); log.debug("Modules are ordered in descending order, according to their priority."); } /** * Returns the process id of the first process, in the highest ranked * module, which is able to work with the given execution context. * * @param context * the {@link ExecutionContext}. * @return the process id or {@code null} */ public String selectProcess(ExecutionContext context) { for (AuthModule module : orderedModules) { String id = module.selectProcess(context); if (StringUtils.isNotEmpty(id)) { log.debug("Process with id '{}' selected, for context '{}'.", id, context); return id; } } log.info("No process is able to handle context '{}'.", context); return null; } }