http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditConnectionFactory.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditConnectionFactory.java b/core/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditConnectionFactory.java deleted file mode 100644 index b35c42d..0000000 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/audit/AuditConnectionFactory.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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.apache.syncope.core.logic.audit; - -import java.io.InputStream; -import java.sql.Connection; -import java.util.Properties; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.rmi.PortableRemoteObject; -import javax.sql.DataSource; -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; -import javax.xml.xpath.XPathFactory; -import org.apache.commons.dbcp2.BasicDataSource; -import org.apache.commons.io.IOUtils; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PropertiesLoaderUtils; -import org.springframework.jdbc.datasource.DataSourceUtils; -import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; -import org.springframework.jdbc.datasource.init.ScriptUtils; -import org.w3c.dom.Document; -import org.w3c.dom.bootstrap.DOMImplementationRegistry; -import org.w3c.dom.ls.DOMImplementationLS; -import org.w3c.dom.ls.LSInput; -import org.w3c.dom.ls.LSParser; - -/** - * LOG4J SQL connection factory that first attempts to obtain a {@link javax.sql.DataSource} from the JNDI name - * configured in Spring or, when not found, builds a new {@link javax.sql.DataSource DataSource} via Commons DBCP; if - * any datasource if found, the SQL init script is used to populate the database. - */ -public final class AuditConnectionFactory { - - private static DataSource DATASOURCE; - - private static final String PERSISTENCE_CONTEXT = "/persistenceContext.xml"; - - static { - // 1. Attempts to lookup for configured JNDI datasource (if present and available) - InputStream springConf = AuditConnectionFactory.class.getResourceAsStream(PERSISTENCE_CONTEXT); - String primary = null; - String fallback = null; - try { - DOMImplementationRegistry reg = DOMImplementationRegistry.newInstance(); - DOMImplementationLS impl = (DOMImplementationLS) reg.getDOMImplementation("LS"); - LSParser parser = impl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null); - LSInput lsinput = impl.createLSInput(); - lsinput.setByteStream(springConf); - Document source = parser.parse(lsinput); - - XPathFactory xPathfactory = XPathFactory.newInstance(); - XPath xpath = xPathfactory.newXPath(); - - XPathExpression expr = xpath.compile("//*[local-name()='bean' and @id='persistenceProperties']/" - + "child::*[local-name()='property' and @name='primary']/@value"); - primary = (String) expr.evaluate(source, XPathConstants.STRING); - expr = xpath.compile("//*[local-name()='bean' and @id='persistenceProperties']/" - + "child::*[local-name()='property' and @name='fallback']/@value"); - fallback = (String) expr.evaluate(source, XPathConstants.STRING); - - expr = xpath.compile("//*[local-name()='property' and @name='jndiName']/@value"); - String jndiName = (String) expr.evaluate(source, XPathConstants.STRING); - - Context ctx = new InitialContext(); - Object obj = ctx.lookup(jndiName); - - DATASOURCE = (DataSource) PortableRemoteObject.narrow(obj, DataSource.class); - } catch (Exception e) { - // ignore - } finally { - IOUtils.closeQuietly(springConf); - } - - // 2. Creates Commons DBCP datasource - String initSQLScript = null; - try { - Resource persistenceProperties = null; - if (primary != null) { - if (primary.startsWith("file:")) { - persistenceProperties = new FileSystemResource(primary.substring(5)); - } - if (primary.startsWith("classpath:")) { - persistenceProperties = new ClassPathResource(primary.substring(10)); - } - } - if ((persistenceProperties == null || !persistenceProperties.exists()) && fallback != null) { - if (fallback.startsWith("file:")) { - persistenceProperties = new FileSystemResource(fallback.substring(5)); - } - if (fallback.startsWith("classpath:")) { - persistenceProperties = new ClassPathResource(fallback.substring(10)); - } - } - Properties persistence = PropertiesLoaderUtils.loadProperties(persistenceProperties); - - initSQLScript = persistence.getProperty("audit.sql"); - - if (DATASOURCE == null) { - BasicDataSource bds = new BasicDataSource(); - bds.setDriverClassName(persistence.getProperty("jpa.driverClassName")); - bds.setUrl(persistence.getProperty("jpa.url")); - bds.setUsername(persistence.getProperty("jpa.username")); - bds.setPassword(persistence.getProperty("jpa.password")); - - bds.setLogAbandoned(true); - bds.setRemoveAbandonedOnBorrow(true); - bds.setRemoveAbandonedOnMaintenance(true); - - DATASOURCE = bds; - } - } catch (Exception e) { - throw new IllegalStateException("Audit datasource configuration failed", e); - } - - // 3. Initializes the chosen datasource - ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); - populator.setScripts(new Resource[] { new ClassPathResource("/audit/" + initSQLScript) }); - // forces no statement separation - populator.setSeparator(ScriptUtils.EOF_STATEMENT_SEPARATOR); - Connection conn = DataSourceUtils.getConnection(DATASOURCE); - try { - populator.populate(conn); - } finally { - DataSourceUtils.releaseConnection(conn, DATASOURCE); - } - } - - public static Connection getConnection() { - if (DATASOURCE != null) { - return DataSourceUtils.getConnection(DATASOURCE); - } - - throw new IllegalStateException("Audit dataSource init failed: check logs"); - } - - private AuditConnectionFactory() { - // empty constructor for static utility class - } -}
http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/main/java/org/apache/syncope/core/logic/init/ImplementationClassNamesLoader.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/ImplementationClassNamesLoader.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/ImplementationClassNamesLoader.java index b22a54d..2bcd78f 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/ImplementationClassNamesLoader.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/ImplementationClassNamesLoader.java @@ -25,9 +25,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; -import org.apache.syncope.core.provisioning.api.job.PushJob; -import org.apache.syncope.core.provisioning.api.job.SyncJob; -import org.apache.syncope.core.provisioning.api.job.TaskJob; import org.apache.syncope.core.provisioning.api.propagation.PropagationActions; import org.apache.syncope.core.provisioning.api.sync.PushActions; import org.apache.syncope.core.provisioning.api.sync.SyncActions; @@ -35,6 +32,9 @@ import org.apache.syncope.core.provisioning.api.sync.SyncCorrelationRule; import org.apache.syncope.core.logic.report.Reportlet; import org.apache.syncope.core.persistence.api.SyncopeLoader; import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator; +import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate; +import org.apache.syncope.core.provisioning.java.sync.PushJobDelegate; +import org.apache.syncope.core.provisioning.java.sync.SyncJobDelegate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.config.BeanDefinition; @@ -52,7 +52,7 @@ public class ImplementationClassNamesLoader implements SyncopeLoader { public enum Type { REPORTLET, - TASKJOB, + TASKJOBDELEGATE, PROPAGATION_ACTIONS, SYNC_ACTIONS, PUSH_ACTIONS, @@ -83,7 +83,7 @@ public class ImplementationClassNamesLoader implements SyncopeLoader { ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); scanner.addIncludeFilter(new AssignableTypeFilter(Reportlet.class)); - scanner.addIncludeFilter(new AssignableTypeFilter(TaskJob.class)); + scanner.addIncludeFilter(new AssignableTypeFilter(SchedTaskJobDelegate.class)); scanner.addIncludeFilter(new AssignableTypeFilter(SyncActions.class)); scanner.addIncludeFilter(new AssignableTypeFilter(PushActions.class)); scanner.addIncludeFilter(new AssignableTypeFilter(SyncCorrelationRule.class)); @@ -102,11 +102,11 @@ public class ImplementationClassNamesLoader implements SyncopeLoader { classNames.get(Type.REPORTLET).add(clazz.getName()); } - if (TaskJob.class.isAssignableFrom(clazz) && !isAbsractClazz - && !SyncJob.class.isAssignableFrom(clazz) - && !PushJob.class.isAssignableFrom(clazz)) { + if (SchedTaskJobDelegate.class.isAssignableFrom(clazz) && !isAbsractClazz + && !SyncJobDelegate.class.isAssignableFrom(clazz) + && !PushJobDelegate.class.isAssignableFrom(clazz)) { - classNames.get(Type.TASKJOB).add(bd.getBeanClassName()); + classNames.get(Type.TASKJOBDELEGATE).add(bd.getBeanClassName()); } if (SyncActions.class.isAssignableFrom(clazz) && !isAbsractClazz) { http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java index 6a8289a..3e7e90f 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java @@ -19,11 +19,13 @@ package org.apache.syncope.core.logic.init; import java.text.ParseException; -import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; -import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.types.TaskType; import org.apache.syncope.core.persistence.api.dao.ConfDAO; import org.apache.syncope.core.persistence.api.dao.NotFoundException; @@ -37,17 +39,17 @@ import org.apache.syncope.core.persistence.api.entity.task.SyncTask; import org.apache.syncope.core.persistence.api.entity.task.Task; import org.apache.syncope.core.provisioning.api.job.JobInstanceLoader; import org.apache.syncope.core.provisioning.api.job.JobNamer; -import org.apache.syncope.core.provisioning.api.job.SyncJob; -import org.apache.syncope.core.provisioning.api.job.TaskJob; -import org.apache.syncope.core.provisioning.api.sync.SyncActions; import org.apache.syncope.core.logic.notification.NotificationJob; import org.apache.syncope.core.logic.report.ReportJob; +import org.apache.syncope.core.misc.security.AuthContextUtils; import org.apache.syncope.core.misc.spring.ApplicationContextProvider; import org.apache.syncope.core.persistence.api.SyncopeLoader; -import org.apache.syncope.core.provisioning.api.job.PushJob; -import org.apache.syncope.core.provisioning.java.sync.PushJobImpl; -import org.apache.syncope.core.provisioning.java.sync.SyncJobImpl; +import org.apache.syncope.core.persistence.api.DomainsHolder; +import org.apache.syncope.core.provisioning.java.job.TaskJob; +import org.apache.syncope.core.provisioning.java.sync.PushJobDelegate; +import org.apache.syncope.core.provisioning.java.sync.SyncJobDelegate; import org.quartz.Job; +import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobKey; import org.quartz.Scheduler; @@ -70,6 +72,9 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader { private static final Logger LOG = LoggerFactory.getLogger(JobInstanceLoader.class); @Autowired + private DomainsHolder domainsHolder; + + @Autowired private SchedulerFactoryBean scheduler; @Autowired @@ -81,7 +86,8 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader { @Autowired private ConfDAO confDAO; - private void registerJob(final String jobName, final Job jobInstance, final String cronExpression) + private void registerJob( + final String jobName, final Job jobInstance, final String cronExpression, final Map<String, Object> jobMap) throws SchedulerException, ParseException { synchronized (scheduler.getScheduler()) { @@ -112,6 +118,7 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader { jobDetail.setName(jobName); jobDetail.setGroup(Scheduler.DEFAULT_GROUP); jobDetail.setJobClass(jobInstance.getClass()); + jobDetail.setJobDataMap(new JobDataMap(jobMap)); // 3. Trigger if (cronExpression == null) { @@ -127,12 +134,13 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader { } } - private Job createSpringBean(final Class<?> jobClass) { - Job jobInstance = null; + @SuppressWarnings("unchecked") + private <T> T createSpringBean(final Class<T> jobClass) { + T jobInstance = null; for (int i = 0; i < 5 && jobInstance == null; i++) { LOG.debug("{} attempt to create Spring bean for {}", i, jobClass); try { - jobInstance = (Job) ApplicationContextProvider.getBeanFactory(). + jobInstance = (T) ApplicationContextProvider.getBeanFactory(). createBean(jobClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false); LOG.debug("{} attempt to create Spring bean for {} succeeded", i, jobClass); } catch (BeanCreationException e) { @@ -151,75 +159,43 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader { return jobInstance; } - @SuppressWarnings("unchecked") @Override - public void registerJob(final Task task, final String jobClassName, final String cronExpression) - throws ClassNotFoundException, SchedulerException, ParseException { - - Class<?> jobClass = Class.forName(jobClassName); - if (SyncJob.class.equals(jobClass)) { - jobClass = SyncJobImpl.class; - } else if (PushJob.class.equals(jobClass)) { - jobClass = PushJobImpl.class; - } - - Job jobInstance = createSpringBean(jobClass); - if (jobInstance instanceof TaskJob) { - ((TaskJob) jobInstance).setTaskId(task.getKey()); - } - - // In case of synchronization job/task retrieve and set synchronization actions: - // actions cannot be changed at runtime but connector and synchronization policies (reloaded at execution time). - if (jobInstance instanceof SyncJob && task instanceof SyncTask) { - final List<SyncActions> actions = new ArrayList<>(); - for (String className : ((SyncTask) task).getActionsClassNames()) { - try { - Class<?> actionsClass = Class.forName(className); - - SyncActions syncActions = (SyncActions) ApplicationContextProvider.getBeanFactory(). - createBean(actionsClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true); - actions.add(syncActions); - } catch (Exception e) { - LOG.info("Class '{}' not found", className, e); - } - } + public Map<String, Object> registerJob(final SchedTask task, final long interruptMaxRetries) + throws SchedulerException, ParseException { - ((SyncJob) jobInstance).setActions(actions); - } + TaskJob job = createSpringBean(TaskJob.class); + job.setTaskKey(task.getKey()); - registerJob(JobNamer.getJobName(task), jobInstance, cronExpression); - } + String jobDelegateClassName = task instanceof SyncTask + ? SyncJobDelegate.class.getName() + : task instanceof PushTask + ? PushJobDelegate.class.getName() + : task.getJobDelegateClassName(); - @Transactional(readOnly = true) - @Override - public void registerTaskJob(final Long taskKey) - throws ClassNotFoundException, SchedulerException, ParseException { + Map<String, Object> jobMap = new HashMap<>(); + jobMap.put(JobInstanceLoader.DOMAIN, AuthContextUtils.getDomain()); + jobMap.put(TaskJob.DELEGATE_CLASS_KEY, jobDelegateClassName); + jobMap.put(TaskJob.INTERRUPT_MAX_RETRIES_KEY, interruptMaxRetries); - SchedTask task = taskDAO.find(taskKey); - if (task == null) { - throw new NotFoundException("Task " + taskKey); - } else { - registerJob(task, task.getJobClassName(), task.getCronExpression()); - } + registerJob(JobNamer.getJobName(task), job, task.getCronExpression(), jobMap); + return jobMap; } @Override public void registerJob(final Report report) throws SchedulerException, ParseException { - Job jobInstance = createSpringBean(ReportJob.class); - ((ReportJob) jobInstance).setReportKey(report.getKey()); + ReportJob job = createSpringBean(ReportJob.class); + job.setReportKey(report.getKey()); + + Map<String, Object> jobMap = new HashMap<>(); + jobMap.put(JobInstanceLoader.DOMAIN, AuthContextUtils.getDomain()); - registerJob(JobNamer.getJobName(report), jobInstance, report.getCronExpression()); + registerJob(JobNamer.getJobName(report), job, report.getCronExpression(), jobMap); } - @Transactional(readOnly = true) - @Override - public void registerReportJob(final Long reportKey) throws SchedulerException, ParseException { - Report report = reportDAO.find(reportKey); - if (report == null) { - throw new NotFoundException("Report " + reportKey); - } else { - registerJob(report); - } + private void registerNotificationJob(final String cronExpression) throws SchedulerException, ParseException { + NotificationJob job = createSpringBean(NotificationJob.class); + + registerJob("taskNotificationJob", job, cronExpression, Collections.<String, Object>emptyMap()); } private void unregisterJob(final String jobName) { @@ -253,41 +229,62 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader { @Transactional @Override public void load() { - // 1. jobs for SchedTasks - Set<SchedTask> tasks = new HashSet<>(taskDAO.<SchedTask>findAll(TaskType.SCHEDULED)); - tasks.addAll(taskDAO.<SyncTask>findAll(TaskType.SYNCHRONIZATION)); - tasks.addAll(taskDAO.<PushTask>findAll(TaskType.PUSH)); - for (SchedTask task : tasks) { + AuthContextUtils.setFakeAuth(SyncopeConstants.MASTER_DOMAIN); + String notificationJobCronExpression = StringUtils.EMPTY; + long interruptMaxRetries = 1; + try { + CPlainAttr notificationJobCronExp = + confDAO.find("notificationjob.cronExpression", NotificationJob.DEFAULT_CRON_EXP); + if (!notificationJobCronExp.getValuesAsStrings().isEmpty()) { + notificationJobCronExpression = notificationJobCronExp.getValuesAsStrings().get(0); + } + + interruptMaxRetries = confDAO.find("tasks.interruptMaxRetries", "1").getValues().get(0).getLongValue(); + } finally { + AuthContextUtils.clearFakeAuth(); + } + + for (String domain : domainsHolder.getDomains().keySet()) { + AuthContextUtils.setFakeAuth(domain); + try { - registerJob(task, task.getJobClassName(), task.getCronExpression()); - } catch (Exception e) { - LOG.error("While loading job instance for task " + task.getKey(), e); + // 1. jobs for SchedTasks + Set<SchedTask> tasks = new HashSet<>(taskDAO.<SchedTask>findAll(TaskType.SCHEDULED)); + tasks.addAll(taskDAO.<SyncTask>findAll(TaskType.SYNCHRONIZATION)); + tasks.addAll(taskDAO.<PushTask>findAll(TaskType.PUSH)); + for (SchedTask task : tasks) { + try { + registerJob(task, interruptMaxRetries); + } catch (Exception e) { + LOG.error("While loading job instance for task " + task.getKey(), e); + } + } + + // 2. ReportJobs + for (Report report : reportDAO.findAll()) { + try { + registerJob(report); + } catch (Exception e) { + LOG.error("While loading job instance for report " + report.getName(), e); + } + } + } finally { + AuthContextUtils.clearFakeAuth(); } } - // 2. NotificationJob - CPlainAttr notificationJobCronExp = - confDAO.find("notificationjob.cronExpression", NotificationJob.DEFAULT_CRON_EXP); - if (StringUtils.isBlank(notificationJobCronExp.getValuesAsStrings().get(0))) { + // 3. NotificationJob + if (StringUtils.isBlank(notificationJobCronExpression)) { LOG.debug("Empty value provided for NotificationJob's cron, not registering anything on Quartz"); } else { LOG.debug("NotificationJob's cron expression: {} - registering Quartz job and trigger", - notificationJobCronExp); + notificationJobCronExpression); try { - registerJob(null, NotificationJob.class.getName(), notificationJobCronExp.getValuesAsStrings().get(0)); + registerNotificationJob(notificationJobCronExpression); } catch (Exception e) { LOG.error("While loading NotificationJob instance", e); } } - - // 3. ReportJobs - for (Report report : reportDAO.findAll()) { - try { - registerJob(report); - } catch (Exception e) { - LOG.error("While loading job instance for report " + report.getName(), e); - } - } } } http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java index 447a92f..e86b46a 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/LoggerLoader.java @@ -18,19 +18,30 @@ */ package org.apache.syncope.core.logic.init; +import java.sql.Connection; +import java.sql.SQLException; import java.util.HashMap; import java.util.Map; +import javax.sql.DataSource; +import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.db.jdbc.ColumnConfig; +import org.apache.logging.log4j.core.appender.db.jdbc.ConnectionSource; +import org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender; import org.apache.logging.log4j.core.config.LoggerConfig; import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.types.LoggerLevel; import org.apache.syncope.common.lib.types.LoggerType; +import org.apache.syncope.core.misc.AuditManager; +import org.apache.syncope.core.persistence.api.DomainsHolder; import org.apache.syncope.core.persistence.api.SyncopeLoader; import org.apache.syncope.core.persistence.api.dao.LoggerDAO; import org.apache.syncope.core.persistence.api.entity.EntityFactory; import org.apache.syncope.core.persistence.api.entity.Logger; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -38,6 +49,9 @@ import org.springframework.transaction.annotation.Transactional; public class LoggerLoader implements SyncopeLoader { @Autowired + private DomainsHolder domainsHolder; + + @Autowired private LoggerDAO loggerDAO; @Autowired @@ -51,6 +65,39 @@ public class LoggerLoader implements SyncopeLoader { @Transactional @Override public void load() { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + + // 1. Audit table and DataSource for each configured domain + ColumnConfig[] columns = { + ColumnConfig.createColumnConfig(ctx.getConfiguration(), "EVENT_DATE", null, null, "true", null, null), + ColumnConfig.createColumnConfig(ctx.getConfiguration(), "LOGGER_LEVEL", "%level", null, null, null, null), + ColumnConfig.createColumnConfig(ctx.getConfiguration(), "LOGGER", "%logger", null, null, null, null), + ColumnConfig.createColumnConfig(ctx.getConfiguration(), "MESSAGE", "%message", null, null, null, null), + ColumnConfig.createColumnConfig(ctx.getConfiguration(), "THROWABLE", "%ex{full}", null, null, null, null) + }; + for (Map.Entry<String, DataSource> entry : domainsHolder.getDomains().entrySet()) { + Appender appender = ctx.getConfiguration().getAppender("audit_for_" + entry.getKey()); + if (appender == null) { + appender = JdbcAppender.createAppender( + "audit_for_" + entry.getKey(), + "false", + null, + new DataSourceConnectionSource(entry.getValue()), + "0", + "SYNCOPEAUDIT", + columns); + appender.start(); + ctx.getConfiguration().addAppender(appender); + } + + LoggerConfig logConf = new LoggerConfig( + AuditManager.getDomainAuditLoggerName(entry.getKey()), null, false); + logConf.addAppender(appender, Level.DEBUG, null); + ctx.getConfiguration().addLogger(AuditManager.getDomainAuditLoggerName(entry.getKey()), logConf); + } + ctx.updateLoggers(); + + // 2. Aligning log4j conf with database content Map<String, Logger> syncopeLoggers = new HashMap<>(); for (Logger syncopeLogger : loggerDAO.findAll(LoggerType.LOG)) { syncopeLoggers.put(syncopeLogger.getKey(), syncopeLogger); @@ -60,8 +107,6 @@ public class LoggerLoader implements SyncopeLoader { syncopeLoggers.put(syncopeLogger.getKey(), syncopeLogger); } - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - /* * Traverse all defined log4j loggers: if there is a matching SyncopeLogger, set log4j level accordingly, * otherwise create a SyncopeLogger instance with given name and level. @@ -95,4 +140,19 @@ public class LoggerLoader implements SyncopeLoader { ctx.updateLoggers(); } + + private static class DataSourceConnectionSource implements ConnectionSource { + + private final DataSource dataSource; + + public DataSourceConnectionSource(final DataSource dataSource) { + this.dataSource = dataSource; + } + + @Override + public Connection getConnection() throws SQLException { + return DataSourceUtils.getConnection(dataSource); + } + + } } http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/main/java/org/apache/syncope/core/logic/init/LogicInitializer.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/LogicInitializer.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/LogicInitializer.java index 9ae6aa9..856fa13 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/LogicInitializer.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/LogicInitializer.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; +import org.apache.syncope.core.misc.spring.ApplicationContextProvider; import org.apache.syncope.core.persistence.api.SyncopeLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,6 +62,8 @@ public class LogicInitializer implements InitializingBean, BeanFactoryAware { } }); + ApplicationContextProvider.setBeanFactory(beanFactory); + LOG.debug("Starting initialization..."); for (SyncopeLoader loader : loaders) { LOG.debug("Invoking {} with priority {}", AopUtils.getTargetClass(loader).getName(), loader.getPriority()); http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java b/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java index 9e40ff1..a0f21f3 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java @@ -18,21 +18,8 @@ */ package org.apache.syncope.core.logic.notification; -import java.util.Date; -import java.util.Properties; -import javax.mail.internet.MimeMessage; -import org.apache.commons.lang3.StringUtils; -import org.apache.syncope.common.lib.types.AuditElements; -import org.apache.syncope.common.lib.types.AuditElements.Result; -import org.apache.syncope.common.lib.types.TaskType; -import org.apache.syncope.common.lib.types.TraceLevel; -import org.apache.syncope.core.persistence.api.dao.TaskDAO; -import org.apache.syncope.core.persistence.api.entity.EntityFactory; -import org.apache.syncope.core.persistence.api.entity.task.NotificationTask; -import org.apache.syncope.core.persistence.api.entity.task.TaskExec; -import org.apache.syncope.core.misc.AuditManager; -import org.apache.syncope.core.misc.ExceptionUtils2; -import org.apache.syncope.core.provisioning.api.notification.NotificationManager; +import org.apache.syncope.core.misc.security.AuthContextUtils; +import org.apache.syncope.core.persistence.api.DomainsHolder; import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobExecutionContext; @@ -40,15 +27,12 @@ import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.JavaMailSenderImpl; -import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; /** * Periodically checks for notification to send. * - * @see NotificationTask + * @see org.apache.syncope.core.persistence.api.entity.task.NotificationTask */ @Component @DisallowConcurrentExecution @@ -63,221 +47,30 @@ public class NotificationJob implements Job { public static final String DEFAULT_CRON_EXP = "0 0/5 * * * ?"; - /** - * Logger. - */ private static final Logger LOG = LoggerFactory.getLogger(NotificationJob.class); @Autowired - private AuditManager auditManager; + private DomainsHolder domainsHolder; @Autowired - private NotificationManager notificationManager; - - @Autowired - private JavaMailSender mailSender; - - @Autowired - private EntityFactory entityFactory; - - /** - * Task DAO. - */ - @Autowired - private TaskDAO taskDAO; - - private long maxRetries; - - private void init() { - maxRetries = notificationManager.getMaxRetries(); - - if (mailSender instanceof JavaMailSenderImpl - && StringUtils.isNotBlank(((JavaMailSenderImpl) mailSender).getUsername())) { - - Properties javaMailProperties = ((JavaMailSenderImpl) mailSender).getJavaMailProperties(); - javaMailProperties.setProperty("mail.smtp.auth", "true"); - ((JavaMailSenderImpl) mailSender).setJavaMailProperties(javaMailProperties); - } - } - - public TaskExec executeSingle(final NotificationTask task) { - init(); - - TaskExec execution = entityFactory.newEntity(TaskExec.class); - execution.setTask(task); - execution.setStartDate(new Date()); - - boolean retryPossible = true; - - if (StringUtils.isBlank(task.getSubject()) || task.getRecipients().isEmpty() - || StringUtils.isBlank(task.getHtmlBody()) || StringUtils.isBlank(task.getTextBody())) { - - String message = "Could not fetch all required information for sending e-mails:\n" - + task.getRecipients() + "\n" - + task.getSender() + "\n" - + task.getSubject() + "\n" - + task.getHtmlBody() + "\n" - + task.getTextBody(); - LOG.error(message); - - execution.setStatus(Status.NOT_SENT.name()); - retryPossible = false; - - if (task.getTraceLevel().ordinal() >= TraceLevel.FAILURES.ordinal()) { - execution.setMessage(message); - } - } else { - if (LOG.isDebugEnabled()) { - LOG.debug("About to send e-mails:\n" - + task.getRecipients() + "\n" - + task.getSender() + "\n" - + task.getSubject() + "\n" - + task.getHtmlBody() + "\n" - + task.getTextBody() + "\n"); - } - - for (String to : task.getRecipients()) { - try { - MimeMessage message = mailSender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(message, true); - helper.setTo(to); - helper.setFrom(task.getSender()); - helper.setSubject(task.getSubject()); - helper.setText(task.getTextBody(), task.getHtmlBody()); - - mailSender.send(message); - - execution.setStatus(Status.SENT.name()); - - StringBuilder report = new StringBuilder(); - switch (task.getTraceLevel()) { - case ALL: - report.append("FROM: ").append(task.getSender()).append('\n'). - append("TO: ").append(to).append('\n'). - append("SUBJECT: ").append(task.getSubject()).append('\n').append('\n'). - append(task.getTextBody()).append('\n').append('\n'). - append(task.getHtmlBody()).append('\n'); - break; - - case SUMMARY: - report.append("E-mail sent to ").append(to).append('\n'); - break; - - case FAILURES: - case NONE: - default: - } - if (report.length() > 0) { - execution.setMessage(report.toString()); - } - - auditManager.audit( - AuditElements.EventCategoryType.TASK, - "notification", - null, - "send", - Result.SUCCESS, - null, - null, - task, - "Successfully sent notification to " + to); - } catch (Exception e) { - LOG.error("Could not send e-mail", e); - - execution.setStatus(Status.NOT_SENT.name()); - if (task.getTraceLevel().ordinal() >= TraceLevel.FAILURES.ordinal()) { - execution.setMessage(ExceptionUtils2.getFullStackTrace(e)); - } - - auditManager.audit( - AuditElements.EventCategoryType.TASK, - "notification", - null, - "send", - Result.FAILURE, - null, - null, - task, - "Could not send notification to " + to, e); - } - - execution.setEndDate(new Date()); - } - } - - if (hasToBeRegistered(execution)) { - execution = notificationManager.storeExec(execution); - if (retryPossible && (Status.valueOf(execution.getStatus()) == Status.NOT_SENT)) { - handleRetries(execution); - } - } else { - notificationManager.setTaskExecuted(execution.getTask().getKey(), true); - } - - return execution; - } + private NotificationJobDelegate delegate; @Override - public void execute(final JobExecutionContext context) - throws JobExecutionException { - + public void execute(final JobExecutionContext context) throws JobExecutionException { LOG.debug("Waking up..."); - for (NotificationTask task : taskDAO.<NotificationTask>findToExec(TaskType.NOTIFICATION)) { - LOG.debug("Found notification task {} to be executed: starting...", task); - executeSingle(task); - LOG.debug("Notification task {} executed", task); + for (String domain : domainsHolder.getDomains().keySet()) { + AuthContextUtils.setFakeAuth(domain); + try { + delegate.execute(); + } catch (Exception e) { + throw new JobExecutionException(e); + } finally { + AuthContextUtils.clearFakeAuth(); + } } LOG.debug("Sleeping again..."); } - private boolean hasToBeRegistered(final TaskExec execution) { - NotificationTask task = (NotificationTask) execution.getTask(); - - // True if either failed and failures have to be registered, or if ALL - // has to be registered. - return (Status.valueOf(execution.getStatus()) == Status.NOT_SENT - && task.getTraceLevel().ordinal() >= TraceLevel.FAILURES.ordinal()) - || task.getTraceLevel() == TraceLevel.ALL; - } - - private void handleRetries(final TaskExec execution) { - if (maxRetries <= 0) { - return; - } - - long failedExecutionsCount = notificationManager.countExecutionsWithStatus( - execution.getTask().getKey(), Status.NOT_SENT.name()); - - if (failedExecutionsCount <= maxRetries) { - LOG.debug("Execution of notification task {} will be retried [{}/{}]", - execution.getTask(), failedExecutionsCount, maxRetries); - notificationManager.setTaskExecuted(execution.getTask().getKey(), false); - - auditManager.audit( - AuditElements.EventCategoryType.TASK, - "notification", - null, - "retry", - Result.SUCCESS, - null, - null, - execution, - "Notification task " + execution.getTask().getKey() + " will be retried"); - } else { - LOG.error("Maximum number of retries reached for task {} - giving up", execution.getTask()); - - auditManager.audit( - AuditElements.EventCategoryType.TASK, - "notification", - null, - "retry", - Result.FAILURE, - null, - null, - execution, - "Giving up retries on notification task " + execution.getTask().getKey()); - } - } } http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJobDelegate.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJobDelegate.java b/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJobDelegate.java new file mode 100644 index 0000000..aaebe77 --- /dev/null +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJobDelegate.java @@ -0,0 +1,258 @@ +/* + * 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.apache.syncope.core.logic.notification; + +import java.util.Date; +import java.util.Properties; +import javax.mail.internet.MimeMessage; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.common.lib.types.AuditElements; +import org.apache.syncope.common.lib.types.TaskType; +import org.apache.syncope.common.lib.types.TraceLevel; +import org.apache.syncope.core.misc.AuditManager; +import org.apache.syncope.core.misc.ExceptionUtils2; +import org.apache.syncope.core.persistence.api.dao.TaskDAO; +import org.apache.syncope.core.persistence.api.entity.EntityFactory; +import org.apache.syncope.core.persistence.api.entity.task.NotificationTask; +import org.apache.syncope.core.persistence.api.entity.task.TaskExec; +import org.apache.syncope.core.provisioning.api.notification.NotificationManager; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +public class NotificationJobDelegate { + + private static final Logger LOG = LoggerFactory.getLogger(NotificationJobDelegate.class); + + /** + * Task DAO. + */ + @Autowired + private TaskDAO taskDAO; + + @Autowired + private JavaMailSender mailSender; + + @Autowired + private EntityFactory entityFactory; + + @Autowired + private AuditManager auditManager; + + @Autowired + private NotificationManager notificationManager; + + private long maxRetries; + + private void init() { + maxRetries = notificationManager.getMaxRetries(); + + if (mailSender instanceof JavaMailSenderImpl + && StringUtils.isNotBlank(((JavaMailSenderImpl) mailSender).getUsername())) { + + Properties javaMailProperties = ((JavaMailSenderImpl) mailSender).getJavaMailProperties(); + javaMailProperties.setProperty("mail.smtp.auth", "true"); + ((JavaMailSenderImpl) mailSender).setJavaMailProperties(javaMailProperties); + } + } + + @Transactional + public TaskExec executeSingle(final NotificationTask task) { + init(); + + TaskExec execution = entityFactory.newEntity(TaskExec.class); + execution.setTask(task); + execution.setStartDate(new Date()); + + boolean retryPossible = true; + + if (StringUtils.isBlank(task.getSubject()) || task.getRecipients().isEmpty() + || StringUtils.isBlank(task.getHtmlBody()) || StringUtils.isBlank(task.getTextBody())) { + + String message = "Could not fetch all required information for sending e-mails:\n" + + task.getRecipients() + "\n" + + task.getSender() + "\n" + + task.getSubject() + "\n" + + task.getHtmlBody() + "\n" + + task.getTextBody(); + LOG.error(message); + + execution.setStatus(NotificationJob.Status.NOT_SENT.name()); + retryPossible = false; + + if (task.getTraceLevel().ordinal() >= TraceLevel.FAILURES.ordinal()) { + execution.setMessage(message); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("About to send e-mails:\n" + + task.getRecipients() + "\n" + + task.getSender() + "\n" + + task.getSubject() + "\n" + + task.getHtmlBody() + "\n" + + task.getTextBody() + "\n"); + } + + for (String to : task.getRecipients()) { + try { + MimeMessage message = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setTo(to); + helper.setFrom(task.getSender()); + helper.setSubject(task.getSubject()); + helper.setText(task.getTextBody(), task.getHtmlBody()); + + mailSender.send(message); + + execution.setStatus(NotificationJob.Status.SENT.name()); + + StringBuilder report = new StringBuilder(); + switch (task.getTraceLevel()) { + case ALL: + report.append("FROM: ").append(task.getSender()).append('\n'). + append("TO: ").append(to).append('\n'). + append("SUBJECT: ").append(task.getSubject()).append('\n').append('\n'). + append(task.getTextBody()).append('\n').append('\n'). + append(task.getHtmlBody()).append('\n'); + break; + + case SUMMARY: + report.append("E-mail sent to ").append(to).append('\n'); + break; + + case FAILURES: + case NONE: + default: + } + if (report.length() > 0) { + execution.setMessage(report.toString()); + } + + auditManager.audit( + AuditElements.EventCategoryType.TASK, + "notification", + null, + "send", + AuditElements.Result.SUCCESS, + null, + null, + task, + "Successfully sent notification to " + to); + } catch (Exception e) { + LOG.error("Could not send e-mail", e); + + execution.setStatus(NotificationJob.Status.NOT_SENT.name()); + if (task.getTraceLevel().ordinal() >= TraceLevel.FAILURES.ordinal()) { + execution.setMessage(ExceptionUtils2.getFullStackTrace(e)); + } + + auditManager.audit( + AuditElements.EventCategoryType.TASK, + "notification", + null, + "send", + AuditElements.Result.FAILURE, + null, + null, + task, + "Could not send notification to " + to, e); + } + + execution.setEndDate(new Date()); + } + } + + if (hasToBeRegistered(execution)) { + execution = notificationManager.storeExec(execution); + if (retryPossible && (NotificationJob.Status.valueOf(execution.getStatus()) + == NotificationJob.Status.NOT_SENT)) { + handleRetries(execution); + } + } else { + notificationManager.setTaskExecuted(execution.getTask().getKey(), true); + } + + return execution; + } + + @Transactional + public void execute() throws JobExecutionException { + for (NotificationTask task : taskDAO.<NotificationTask>findToExec(TaskType.NOTIFICATION)) { + LOG.debug("Found notification task {} to be executed: starting...", task); + executeSingle(task); + LOG.debug("Notification task {} executed", task); + } + } + + private boolean hasToBeRegistered(final TaskExec execution) { + NotificationTask task = (NotificationTask) execution.getTask(); + + // True if either failed and failures have to be registered, or if ALL + // has to be registered. + return (NotificationJob.Status.valueOf(execution.getStatus()) == NotificationJob.Status.NOT_SENT + && task.getTraceLevel().ordinal() >= TraceLevel.FAILURES.ordinal()) + || task.getTraceLevel() == TraceLevel.ALL; + } + + private void handleRetries(final TaskExec execution) { + if (maxRetries <= 0) { + return; + } + + long failedExecutionsCount = notificationManager.countExecutionsWithStatus( + execution.getTask().getKey(), NotificationJob.Status.NOT_SENT.name()); + + if (failedExecutionsCount <= maxRetries) { + LOG.debug("Execution of notification task {} will be retried [{}/{}]", + execution.getTask(), failedExecutionsCount, maxRetries); + notificationManager.setTaskExecuted(execution.getTask().getKey(), false); + + auditManager.audit( + AuditElements.EventCategoryType.TASK, + "notification", + null, + "retry", + AuditElements.Result.SUCCESS, + null, + null, + execution, + "Notification task " + execution.getTask().getKey() + " will be retried"); + } else { + LOG.error("Maximum number of retries reached for task {} - giving up", execution.getTask()); + + auditManager.audit( + AuditElements.EventCategoryType.TASK, + "notification", + null, + "retry", + AuditElements.Result.FAILURE, + null, + null, + execution, + "Giving up retries on notification task " + execution.getTask().getKey()); + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJob.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJob.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJob.java index e07612a..8e5af91 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJob.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJob.java @@ -18,74 +18,28 @@ */ package org.apache.syncope.core.logic.report; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Date; -import java.util.zip.Deflater; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.sax.SAXTransformerFactory; -import javax.xml.transform.sax.TransformerHandler; -import javax.xml.transform.stream.StreamResult; -import org.apache.commons.io.IOUtils; -import org.apache.syncope.common.lib.SyncopeConstants; -import org.apache.syncope.common.lib.report.ReportletConf; -import org.apache.syncope.common.lib.types.ReportExecStatus; -import org.apache.syncope.core.persistence.api.dao.ReportDAO; -import org.apache.syncope.core.persistence.api.dao.ReportExecDAO; -import org.apache.syncope.core.persistence.api.entity.EntityFactory; -import org.apache.syncope.core.persistence.api.entity.Report; -import org.apache.syncope.core.persistence.api.entity.ReportExec; -import org.apache.syncope.core.logic.ReportLogic; -import org.apache.syncope.core.misc.spring.ApplicationContextProvider; -import org.apache.syncope.core.misc.ExceptionUtils2; +import org.apache.syncope.core.misc.security.AuthContextUtils; +import org.apache.syncope.core.provisioning.api.job.JobInstanceLoader; import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.xml.sax.helpers.AttributesImpl; /** * Quartz job for executing a given report. */ -@SuppressWarnings("unchecked") @DisallowConcurrentExecution public class ReportJob implements Job { /** - * Logger. - */ - private static final Logger LOG = LoggerFactory.getLogger(ReportJob.class); - - /** - * Report DAO. - */ - @Autowired - private ReportDAO reportDAO; - - /** - * Report execution DAO. - */ - @Autowired - private ReportExecDAO reportExecDAO; - - @Autowired - private ReportLogic dataBinder; - - @Autowired - private EntityFactory entityFactory; - - /** * Key, set by the caller, for identifying the report to be executed. */ private Long reportKey; + @Autowired + private ReportJobDelegate delegate; + /** * Report id setter. * @@ -95,109 +49,15 @@ public class ReportJob implements Job { this.reportKey = reportKey; } - @SuppressWarnings("rawtypes") @Override public void execute(final JobExecutionContext context) throws JobExecutionException { - Report report = reportDAO.find(reportKey); - if (report == null) { - throw new JobExecutionException("Report " + reportKey + " not found"); - } - - // 1. create execution - ReportExec execution = entityFactory.newEntity(ReportExec.class); - execution.setStatus(ReportExecStatus.STARTED); - execution.setStartDate(new Date()); - execution.setReport(report); - execution = reportExecDAO.save(execution); - - report.addExec(execution); - report = reportDAO.save(report); - - // 2. define a SAX handler for generating result as XML - TransformerHandler handler; - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ZipOutputStream zos = new ZipOutputStream(baos); - zos.setLevel(Deflater.BEST_COMPRESSION); - try { - SAXTransformerFactory tFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); - handler = tFactory.newTransformerHandler(); - Transformer serializer = handler.getTransformer(); - serializer.setOutputProperty(OutputKeys.ENCODING, SyncopeConstants.DEFAULT_ENCODING); - serializer.setOutputProperty(OutputKeys.INDENT, "yes"); - - // a single ZipEntry in the ZipOutputStream - zos.putNextEntry(new ZipEntry(report.getName())); - - // streaming SAX handler in a compressed byte array stream - handler.setResult(new StreamResult(zos)); - } catch (Exception e) { - throw new JobExecutionException("While configuring for SAX generation", e, true); - } - - execution.setStatus(ReportExecStatus.RUNNING); - execution = reportExecDAO.save(execution); - - // 3. actual report execution - StringBuilder reportExecutionMessage = new StringBuilder(); + AuthContextUtils.setFakeAuth(context.getMergedJobDataMap().getString(JobInstanceLoader.DOMAIN)); try { - // report header - handler.startDocument(); - AttributesImpl atts = new AttributesImpl(); - atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, report.getName()); - handler.startElement("", "", ReportXMLConst.ELEMENT_REPORT, atts); - - // iterate over reportlet instances defined for this report - for (ReportletConf reportletConf : report.getReportletConfs()) { - Class<Reportlet> reportletClass = - dataBinder.findReportletClassHavingConfClass(reportletConf.getClass()); - if (reportletClass != null) { - Reportlet<ReportletConf> autowired = - (Reportlet<ReportletConf>) ApplicationContextProvider.getBeanFactory(). - createBean(reportletClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false); - autowired.setConf(reportletConf); - - // invoke reportlet - try { - autowired.extract(handler); - } catch (Exception e) { - execution.setStatus(ReportExecStatus.FAILURE); - - Throwable t = e instanceof ReportException - ? e.getCause() - : e; - reportExecutionMessage. - append(ExceptionUtils2.getFullStackTrace(t)). - append("\n==================\n"); - } - } - } - - // report footer - handler.endElement("", "", ReportXMLConst.ELEMENT_REPORT); - handler.endDocument(); - - if (!ReportExecStatus.FAILURE.name().equals(execution.getStatus())) { - execution.setStatus(ReportExecStatus.SUCCESS); - } + delegate.execute(reportKey); } catch (Exception e) { - execution.setStatus(ReportExecStatus.FAILURE); - reportExecutionMessage.append(ExceptionUtils2.getFullStackTrace(e)); - - throw new JobExecutionException(e, true); + throw new JobExecutionException(e); } finally { - try { - zos.closeEntry(); - IOUtils.closeQuietly(zos); - IOUtils.closeQuietly(baos); - } catch (IOException e) { - LOG.error("While closing StreamResult's backend", e); - } - - execution.setExecResult(baos.toByteArray()); - execution.setMessage(reportExecutionMessage.toString()); - execution.setEndDate(new Date()); - reportExecDAO.save(execution); + AuthContextUtils.clearFakeAuth(); } } } http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java new file mode 100644 index 0000000..9920c1f --- /dev/null +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReportJobDelegate.java @@ -0,0 +1,181 @@ +/* + * 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.apache.syncope.core.logic.report; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Date; +import java.util.zip.Deflater; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; +import org.apache.commons.io.IOUtils; +import org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.common.lib.report.ReportletConf; +import org.apache.syncope.common.lib.types.ReportExecStatus; +import org.apache.syncope.core.logic.ReportLogic; +import org.apache.syncope.core.misc.ExceptionUtils2; +import org.apache.syncope.core.misc.spring.ApplicationContextProvider; +import org.apache.syncope.core.persistence.api.dao.ReportDAO; +import org.apache.syncope.core.persistence.api.dao.ReportExecDAO; +import org.apache.syncope.core.persistence.api.entity.EntityFactory; +import org.apache.syncope.core.persistence.api.entity.Report; +import org.apache.syncope.core.persistence.api.entity.ReportExec; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.xml.sax.helpers.AttributesImpl; + +@Component +public class ReportJobDelegate { + + private static final Logger LOG = LoggerFactory.getLogger(ReportJobDelegate.class); + + /** + * Report DAO. + */ + @Autowired + private ReportDAO reportDAO; + + /** + * Report execution DAO. + */ + @Autowired + private ReportExecDAO reportExecDAO; + + @Autowired + private EntityFactory entityFactory; + + @Autowired + private ReportLogic dataBinder; + + @Transactional + public void execute(final Long reportKey) throws JobExecutionException { + Report report = reportDAO.find(reportKey); + if (report == null) { + throw new JobExecutionException("Report " + reportKey + " not found"); + } + + // 1. create execution + ReportExec execution = entityFactory.newEntity(ReportExec.class); + execution.setStatus(ReportExecStatus.STARTED); + execution.setStartDate(new Date()); + execution.setReport(report); + execution = reportExecDAO.save(execution); + + report.addExec(execution); + report = reportDAO.save(report); + + // 2. define a SAX handler for generating result as XML + TransformerHandler handler; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ZipOutputStream zos = new ZipOutputStream(baos); + zos.setLevel(Deflater.BEST_COMPRESSION); + try { + SAXTransformerFactory tFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); + handler = tFactory.newTransformerHandler(); + Transformer serializer = handler.getTransformer(); + serializer.setOutputProperty(OutputKeys.ENCODING, SyncopeConstants.DEFAULT_ENCODING); + serializer.setOutputProperty(OutputKeys.INDENT, "yes"); + + // a single ZipEntry in the ZipOutputStream + zos.putNextEntry(new ZipEntry(report.getName())); + + // streaming SAX handler in a compressed byte array stream + handler.setResult(new StreamResult(zos)); + } catch (Exception e) { + throw new JobExecutionException("While configuring for SAX generation", e, true); + } + + execution.setStatus(ReportExecStatus.RUNNING); + execution = reportExecDAO.save(execution); + + // 3. actual report execution + StringBuilder reportExecutionMessage = new StringBuilder(); + try { + // report header + handler.startDocument(); + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, report.getName()); + handler.startElement("", "", ReportXMLConst.ELEMENT_REPORT, atts); + + // iterate over reportlet instances defined for this report + for (ReportletConf reportletConf : report.getReportletConfs()) { + Class<Reportlet> reportletClass = + dataBinder.findReportletClassHavingConfClass(reportletConf.getClass()); + if (reportletClass != null) { + @SuppressWarnings("unchecked") + Reportlet<ReportletConf> autowired = + (Reportlet<ReportletConf>) ApplicationContextProvider.getBeanFactory(). + createBean(reportletClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false); + autowired.setConf(reportletConf); + + // invoke reportlet + try { + autowired.extract(handler); + } catch (Exception e) { + execution.setStatus(ReportExecStatus.FAILURE); + + Throwable t = e instanceof ReportException + ? e.getCause() + : e; + reportExecutionMessage. + append(ExceptionUtils2.getFullStackTrace(t)). + append("\n==================\n"); + } + } + } + + // report footer + handler.endElement("", "", ReportXMLConst.ELEMENT_REPORT); + handler.endDocument(); + + if (!ReportExecStatus.FAILURE.name().equals(execution.getStatus())) { + execution.setStatus(ReportExecStatus.SUCCESS); + } + } catch (Exception e) { + execution.setStatus(ReportExecStatus.FAILURE); + reportExecutionMessage.append(ExceptionUtils2.getFullStackTrace(e)); + + throw new JobExecutionException(e, true); + } finally { + try { + zos.closeEntry(); + IOUtils.closeQuietly(zos); + IOUtils.closeQuietly(baos); + } catch (IOException e) { + LOG.error("While closing StreamResult's backend", e); + } + + execution.setExecResult(baos.toByteArray()); + execution.setMessage(reportExecutionMessage.toString()); + execution.setEndDate(new Date()); + reportExecDAO.save(execution); + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/test/java/org/apache/syncope/core/logic/AbstractTest.java ---------------------------------------------------------------------- diff --git a/core/logic/src/test/java/org/apache/syncope/core/logic/AbstractTest.java b/core/logic/src/test/java/org/apache/syncope/core/logic/AbstractTest.java index 161d0c1..d4b0fa4 100644 --- a/core/logic/src/test/java/org/apache/syncope/core/logic/AbstractTest.java +++ b/core/logic/src/test/java/org/apache/syncope/core/logic/AbstractTest.java @@ -23,7 +23,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.transaction.annotation.Transactional; +import org.springframework.test.context.transaction.TransactionConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { @@ -33,7 +33,7 @@ import org.springframework.transaction.annotation.Transactional; "classpath:persistenceTest.xml", "classpath:logicTest.xml" }) -@Transactional +@TransactionConfiguration(transactionManager = "MasterTransactionManager") public abstract class AbstractTest { protected static final Logger LOG = LoggerFactory.getLogger(AbstractTest.class); http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/test/java/org/apache/syncope/core/logic/MappingTest.java ---------------------------------------------------------------------- diff --git a/core/logic/src/test/java/org/apache/syncope/core/logic/MappingTest.java b/core/logic/src/test/java/org/apache/syncope/core/logic/MappingTest.java index 1f1dab7..770bac9 100644 --- a/core/logic/src/test/java/org/apache/syncope/core/logic/MappingTest.java +++ b/core/logic/src/test/java/org/apache/syncope/core/logic/MappingTest.java @@ -31,7 +31,9 @@ import org.apache.syncope.core.persistence.api.entity.user.User; import org.identityconnectors.framework.common.objects.Name; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +@Transactional public class MappingTest extends AbstractTest { @Autowired http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/test/java/org/apache/syncope/core/logic/NotificationTest.java ---------------------------------------------------------------------- diff --git a/core/logic/src/test/java/org/apache/syncope/core/logic/NotificationTest.java b/core/logic/src/test/java/org/apache/syncope/core/logic/NotificationTest.java index c5dc13c..6c208a2 100644 --- a/core/logic/src/test/java/org/apache/syncope/core/logic/NotificationTest.java +++ b/core/logic/src/test/java/org/apache/syncope/core/logic/NotificationTest.java @@ -79,7 +79,9 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.transaction.annotation.Transactional; +@Transactional public class NotificationTest extends AbstractTest { private static final String SMTP_HOST = "localhost"; @@ -164,7 +166,7 @@ public class NotificationTest extends AbstractTest { } private static UserTO getSampleTO(final String email) { - String uid = email; + String uid = UUID.randomUUID().toString().substring(0, 8) + email; UserTO userTO = new UserTO(); userTO.setPassword("password123"); userTO.setUsername(uid); @@ -175,7 +177,7 @@ public class NotificationTest extends AbstractTest { userTO.getPlainAttrs().add(attributeTO("surname", "surname")); userTO.getPlainAttrs().add(attributeTO("type", "a type")); userTO.getPlainAttrs().add(attributeTO("userId", uid)); - userTO.getPlainAttrs().add(attributeTO("email", uid)); + userTO.getPlainAttrs().add(attributeTO("email", email)); userTO.getPlainAttrs().add(attributeTO("loginDate", new SimpleDateFormat("yyyy-MM-dd").format(new Date()))); userTO.getDerAttrs().add(attributeTO("cn", null)); userTO.getVirAttrs().add(attributeTO("virtualdata", "virtualvalue")); http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/logic/src/test/resources/logicTest.xml ---------------------------------------------------------------------- diff --git a/core/logic/src/test/resources/logicTest.xml b/core/logic/src/test/resources/logicTest.xml index 3cf0ab0..2dca918 100644 --- a/core/logic/src/test/resources/logicTest.xml +++ b/core/logic/src/test/resources/logicTest.xml @@ -26,6 +26,7 @@ under the License. <property name="locations"> <list> <value>classpath:persistence.properties</value> + <value>classpath:domains/*.properties</value> <value>classpath:security.properties</value> <value>classpath:connid.properties</value> <value>classpath:mail.properties</value> @@ -37,10 +38,5 @@ under the License. <property name="ignoreResourceNotFound" value="true"/> <property name="ignoreUnresolvablePlaceholders" value="true"/> </bean> - - <bean id="contentXML" class="org.apache.syncope.core.misc.spring.ResourceWithFallbackLoader"> - <property name="primary" value="file:${conf.directory}/content.xml"/> - <property name="fallback" value="classpath:content.xml"/> - </bean> </beans> http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/misc/src/main/java/org/apache/syncope/core/misc/AuditManager.java ---------------------------------------------------------------------- diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/AuditManager.java b/core/misc/src/main/java/org/apache/syncope/core/misc/AuditManager.java index a8d8aac..d370895 100644 --- a/core/misc/src/main/java/org/apache/syncope/core/misc/AuditManager.java +++ b/core/misc/src/main/java/org/apache/syncope/core/misc/AuditManager.java @@ -23,13 +23,18 @@ import org.apache.syncope.common.lib.types.AuditElements; import org.apache.syncope.common.lib.types.AuditElements.Result; import org.apache.syncope.common.lib.types.AuditLoggerName; import org.apache.syncope.common.lib.types.LoggerLevel; +import org.apache.syncope.common.lib.types.LoggerType; +import org.apache.syncope.core.misc.security.AuthContextUtils; +import org.apache.syncope.core.misc.security.SyncopeAuthenticationDetails; import org.apache.syncope.core.persistence.api.dao.LoggerDAO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; @Component public class AuditManager { @@ -39,6 +44,11 @@ public class AuditManager { @Autowired private LoggerDAO loggerDAO; + public static String getDomainAuditLoggerName(final String domain) { + return LoggerType.AUDIT.getPrefix() + "." + domain; + } + + @Transactional(readOnly = true) public void audit( final AuditElements.EventCategoryType type, final String category, @@ -88,13 +98,22 @@ public class AuditManager { if (syncopeLogger != null && syncopeLogger.getLevel() == LoggerLevel.DEBUG) { StringBuilder auditMessage = new StringBuilder(); - final SecurityContext ctx = SecurityContextHolder.getContext(); + SecurityContext ctx = SecurityContextHolder.getContext(); if (ctx != null && ctx.getAuthentication() != null) { auditMessage.append('[').append(ctx.getAuthentication().getName()).append("] "); } auditMessage.append(message); - final Logger logger = LoggerFactory.getLogger(auditLoggerName.toLoggerName()); + String domain = AuthContextUtils.getDomain(); + if (input != null && input.length > 0 && input[0] instanceof UsernamePasswordAuthenticationToken) { + UsernamePasswordAuthenticationToken token = + UsernamePasswordAuthenticationToken.class.cast(input[0]); + if (token.getDetails() instanceof SyncopeAuthenticationDetails) { + domain = SyncopeAuthenticationDetails.class.cast(token.getDetails()).getDomain(); + } + } + + Logger logger = LoggerFactory.getLogger(getDomainAuditLoggerName(domain)); if (throwable == null) { logger.debug(auditMessage.toString()); } else { http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java ---------------------------------------------------------------------- diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java index e655809..95a16b1 100644 --- a/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java +++ b/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java @@ -73,7 +73,7 @@ import org.identityconnectors.framework.common.objects.Name; import org.identityconnectors.framework.common.objects.OperationalAttributes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; public final class MappingUtils { @@ -141,9 +141,9 @@ public final class MappingUtils { LOG.debug("Preparing resource attributes for {} with provision {} for attributes {}", any, provision, any.getPlainAttrs()); - ConfigurableApplicationContext context = ApplicationContextProvider.getApplicationContext(); - VirAttrCache virAttrCache = context.getBean(VirAttrCache.class); - PasswordGenerator passwordGenerator = context.getBean(PasswordGenerator.class); + DefaultListableBeanFactory beanFactory = ApplicationContextProvider.getBeanFactory(); + VirAttrCache virAttrCache = beanFactory.getBean(VirAttrCache.class); + PasswordGenerator passwordGenerator = beanFactory.getBean(PasswordGenerator.class); Set<Attribute> attributes = new HashSet<>(); String connObjectKey = null; @@ -227,9 +227,9 @@ public final class MappingUtils { List<Any<?, ?, ?>> anys = new ArrayList<>(); - ConfigurableApplicationContext context = ApplicationContextProvider.getApplicationContext(); - AnyUtilsFactory anyUtilsFactory = context.getBean(AnyUtilsFactory.class); - VirAttrHandler virAttrHandler = context.getBean(VirAttrHandler.class); + DefaultListableBeanFactory beanFactory = ApplicationContextProvider.getBeanFactory(); + AnyUtilsFactory anyUtilsFactory = beanFactory.getBean(AnyUtilsFactory.class); + VirAttrHandler virAttrHandler = beanFactory.getBean(VirAttrHandler.class); switch (mapItem.getIntMappingType().getAnyTypeKind()) { case USER: @@ -240,7 +240,7 @@ public final class MappingUtils { case GROUP: if (any instanceof User) { - UserDAO userDAO = context.getBean(UserDAO.class); + UserDAO userDAO = beanFactory.getBean(UserDAO.class); for (Group group : userDAO.findAllGroups((User) any)) { virAttrHandler.retrieveVirAttrValues(group); anys.add(group); @@ -271,7 +271,7 @@ public final class MappingUtils { case UserPlainSchema: case GroupPlainSchema: case AnyObjectPlainSchema: - final PlainSchemaDAO plainSchemaDAO = context.getBean(PlainSchemaDAO.class); + PlainSchemaDAO plainSchemaDAO = beanFactory.getBean(PlainSchemaDAO.class); schema = plainSchemaDAO.find(mapItem.getIntAttrName()); schemaType = schema == null ? AttrSchemaType.String : schema.getType(); break; @@ -279,7 +279,7 @@ public final class MappingUtils { case UserVirtualSchema: case GroupVirtualSchema: case AnyObjectVirtualSchema: - VirSchemaDAO virSchemaDAO = context.getBean(VirSchemaDAO.class); + VirSchemaDAO virSchemaDAO = beanFactory.getBean(VirSchemaDAO.class); VirSchema virSchema = virSchemaDAO.find(mapItem.getIntAttrName()); readOnlyVirSchema = (virSchema != null && virSchema.isReadonly()); schemaType = AttrSchemaType.String; @@ -434,9 +434,9 @@ public final class MappingUtils { LOG.debug("Get attributes for '{}' and mapping type '{}'", anys, mappingItem.getIntMappingType()); EntityFactory entityFactory = - ApplicationContextProvider.getApplicationContext().getBean(EntityFactory.class); + ApplicationContextProvider.getBeanFactory().getBean(EntityFactory.class); AnyUtilsFactory anyUtilsFactory = - ApplicationContextProvider.getApplicationContext().getBean(AnyUtilsFactory.class); + ApplicationContextProvider.getBeanFactory().getBean(AnyUtilsFactory.class); List<PlainAttrValue> values = new ArrayList<>(); PlainAttrValue attrValue; switch (mappingItem.getIntMappingType()) { @@ -551,7 +551,7 @@ public final class MappingUtils { break; case GroupOwnerSchema: - AnyTypeDAO anyTypeDAO = ApplicationContextProvider.getApplicationContext().getBean(AnyTypeDAO.class); + AnyTypeDAO anyTypeDAO = ApplicationContextProvider.getBeanFactory().getBean(AnyTypeDAO.class); Mapping uMapping = provision.getAnyType().equals(anyTypeDAO.findUser()) ? null : provision.getMapping(); http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java ---------------------------------------------------------------------- diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java index 4b8faec..13ddc84 100644 --- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java +++ b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/AccountPolicyEnforcer.java @@ -22,8 +22,6 @@ import java.util.regex.Pattern; import org.apache.syncope.common.lib.types.AccountPolicySpec; import org.apache.syncope.common.lib.types.PolicyType; import org.apache.syncope.core.persistence.api.entity.user.User; -import org.apache.syncope.core.provisioning.api.UserSuspender; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component @@ -31,11 +29,8 @@ public class AccountPolicyEnforcer implements PolicyEnforcer<AccountPolicySpec, private static final Pattern DEFAULT_PATTERN = Pattern.compile("[a-zA-Z0-9-_@. ]+"); - @Autowired(required = false) - private UserSuspender userSuspender; - @Override - public void enforce(final AccountPolicySpec policy, final PolicyType type, final User user) { + public boolean enforce(final AccountPolicySpec policy, final PolicyType type, final User user) { if (user.getUsername() == null) { throw new PolicyEnforceException("Invalid account"); } @@ -90,11 +85,7 @@ public class AccountPolicyEnforcer implements PolicyEnforcer<AccountPolicySpec, } // check for subsequent failed logins - if (userSuspender != null - && user.getFailedLogins() != null && policy.getMaxAuthenticationAttempts() > 0 - && user.getFailedLogins() > policy.getMaxAuthenticationAttempts() && !user.isSuspended()) { - - userSuspender.suspend(user, policy.isPropagateSuspension()); - } + return (user.getFailedLogins() != null && policy.getMaxAuthenticationAttempts() > 0 + && user.getFailedLogins() > policy.getMaxAuthenticationAttempts() && !user.isSuspended()); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/34a1c214/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java ---------------------------------------------------------------------- diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java index 41a6bb6..1313d2e 100644 --- a/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java +++ b/core/misc/src/main/java/org/apache/syncope/core/misc/policy/PasswordPolicyEnforcer.java @@ -27,7 +27,7 @@ import org.springframework.stereotype.Component; public class PasswordPolicyEnforcer implements PolicyEnforcer<PasswordPolicySpec, User> { @Override - public void enforce(final PasswordPolicySpec policy, final PolicyType type, final User user) { + public boolean enforce(final PasswordPolicySpec policy, final PolicyType type, final User user) { final String clearPassword = user.getClearPassword(); final String password = user.getPassword(); @@ -147,6 +147,8 @@ public class PasswordPolicyEnforcer implements PolicyEnforcer<PasswordPolicySpec throw new PasswordPolicyException("Password mustn't end with a non-alphanumeric character"); } } + + return false; } private boolean checkForDigit(final String str) {
